From owner-freebsd-current Tue Aug 25 16:52:55 1998 Return-Path: Received: (from majordom@localhost) by hub.freebsd.org (8.8.8/8.8.8) id QAA04369 for freebsd-current-outgoing; Tue, 25 Aug 1998 16:52:55 -0700 (PDT) (envelope-from owner-freebsd-current@FreeBSD.ORG) Received: from godzilla.zeta.org.au (godzilla.zeta.org.au [203.15.68.22]) by hub.freebsd.org (8.8.8/8.8.8) with ESMTP id QAA04361 for ; Tue, 25 Aug 1998 16:52:51 -0700 (PDT) (envelope-from bde@godzilla.zeta.org.au) Received: (from bde@localhost) by godzilla.zeta.org.au (8.8.7/8.8.7) id JAA32306; Wed, 26 Aug 1998 09:51:57 +1000 Date: Wed, 26 Aug 1998 09:51:57 +1000 From: Bruce Evans Message-Id: <199808252351.JAA32306@godzilla.zeta.org.au> To: current@FreeBSD.ORG, luoqi@watermarkgroup.com, shocking@prth.pgs.com Subject: Re: Floating Point Exceptions, signal handlers & subsequent ops Sender: owner-freebsd-current@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.ORG >> I've noticed in one of my applications that the first FP operation after >> return from a caught SIGFPE is invalid. I have a signal handler installed that This is normal. Returning from a SIGFPE handler gives explicitly undefined behaviour in ANSI C. It gives various bad behaviours for FreeBSD on i386's: 1) if the SIGFPE was for integer division by zero, then the division will be restarted and the SIGFPE will be repeated endlessly. 2) if the SIGFPE was for an FP operation, then the FP operatation will be restarted. The kernel has cleared the trap-pending flag before delivering the SIGFPE to the application, and on i386's traps are delivered to the kernel on the the first non-control FP operation after the one that caused the exception, so it is certain that the restarted FP operation won't trap; it may cause an exception which will be delivered to the kernel on the next non-control FP operation. >> just prints out some basic info (like "SIGFPE caught"). The first FP op after >> this (in my case, converting a long to a double) just gives garbage. Repeat Long to double conversion actually takes 4 or 5 FP operations. long to double conversion will only trap on i386's for FP stack overflow. It's normal for botched signal handling to leave junk on the stack. E.g., faddp normally pops one operand, but if it causes an exception then it doesn't change the stack. >Your SIGFPE handler has to restore the FP register stack top, and this is >no easy job to do, you have to handle each exception type differently. It's >not FreeBSD's problem, rather a stupid design on intel's part. It has to do much more than that if it wants to return: 1) First decide if the exception is for FP or integer division by 0, by looking at the trap code. FreeBSD's support for trap codes is primitive and unportable (see ), but probably good enough to distinguish integer division by zero. 2) Handle the easy case of integer division by zero (if this can happen). Just modify the operands so that it doesn't happen, or advance the program counter and supply a result. 3) Handle all cases of FP exceptions that can happen, much like the integer division case except there are potentially thousands more cases. You basically need an FP emulator. Changing the stack top is not sufficient. You also need to supply a result for the exception operation and leave it at the approriate place on the stack. The FPU doesn't generate a default result for trapped exceptions, presumably because leaving it on the stack would usually clobber an operand, making it impossible for smart SIGFPE handlers (which no one writes :-) to do a complete fixup. The right way to handle this problem is to avoid it, either by not trapping FP exceptions (this causes different problems), or by longjmping out of the SIGFPE handler (set up the longjmp before each FP operation that may trap), or by checking operands to ensure that there are no traps. Bruce To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-current" in the body of the message