Date: Wed, 26 Aug 1998 15:42:41 +0200 From: Martin Cracauer <cracauer@cons.org> To: Bruce Evans <bde@zeta.org.au>, current@FreeBSD.ORG, luoqi@watermarkgroup.com, shocking@prth.pgs.com Subject: Re: Floating Point Exceptions, signal handlers & subsequent ops Message-ID: <19980826154241.A22184@cons.org> In-Reply-To: <199808252351.JAA32306@godzilla.zeta.org.au>; from Bruce Evans on Wed, Aug 26, 1998 at 09:51:57AM %2B1000 References: <199808252351.JAA32306@godzilla.zeta.org.au>
next in thread | previous in thread | raw e-mail | index | archive | help
In <199808252351.JAA32306@godzilla.zeta.org.au>, Bruce Evans wrote:
> 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.
I'm not able to reproduce this behaviour. I wrote a short test program
that runs like this:
Trying to trigger a FPE and see if FP still works afterwards.
First round - FPE-causing operation and then a non-exception operation.
Operation caused exception -> right.
Next operation after fpe worked and gave correct result -> right.
Second round - directly following FPE-causing operations.
First operation caused exception -> right.
Second operation caused exception -> right
>From your description, I would expect the next FP operating after a
caught FPE exception to fail. Either by issuing a wrong result, by not
troughing FPE where it should or throughing one where it shouldn't.
Here's what I do. Don't compile this with optimization, my actions
against it aren't sufficient.
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
volatile sig_atomic_t fpe_was_here = 0;
static void
handler(int s)
{
fpe_was_here++;
write(2, "sig\n", 4);
}
/* Don't use printf, it uses floating point */
#define TO_STDERR(arg) write(2, arg, sizeof(arg))
int
main(void)
{
double f0;
double f2;
double f4;
double f8;
double res;
double old_res;
int old_fpe_was_here;
double killopt = 0.0;
/* Prevent optimization */
f0 = atof("0.0");
f2 = atof("2.0");
f4 = atof("4.0");
f8 = atof("8.0");
TO_STDERR("Trying to trigger a FPE and see if FP still works afterwards.\n");
TO_STDERR("\nFirst round - FPE-causing operation and then a non-exception "
"operation.\n");
signal(SIGFPE, handler);
res = f2 / f0;
killopt += res;
if (fpe_was_here) {
TO_STDERR("Operation caused exception -> right.\n");
fpe_was_here--;
}
else {
TO_STDERR("Operation works fine -> wrong.\n");
}
if (fpe_was_here) {
TO_STDERR("Aehm, what?\n");
exit(1);
}
res = f4 + f8;
killopt += res;
if (fpe_was_here) {
TO_STDERR("Next normal operation caused exception -> wrong.\n");
fpe_was_here--;
}
if (res != 12.0) {
TO_STDERR("Next operation gave wrong result :-(\n");
}
else {
TO_STDERR("Next operation after fpe worked and gave correct result "
"-> right.\n");
}
TO_STDERR("\nSecond round - directly following FPE-causing operations.\n");
old_res = f2 / f0;
/* Don't do a any output here to keep Schroedinger happy */
old_fpe_was_here = fpe_was_here;
fpe_was_here--;
res = f2 / f0;
killopt += old_res;
killopt += res;
if (old_fpe_was_here) {
TO_STDERR("First operation caused exception -> right.\n");
old_fpe_was_here--;
}
else {
TO_STDERR("First operation works fine -> wrong.\n");
}
if (old_fpe_was_here) {
TO_STDERR("Aehm, what?\n");
exit(1);
}
if (fpe_was_here) {
TO_STDERR("Second operation caused exception -> right\n");
fpe_was_here--;
}
else {
TO_STDERR("Second operation works fine -> wrong\n");
}
if (fpe_was_here) {
TO_STDERR("Aehm, what?\n");
exit(1);
}
fprintf(stderr,"For the record and against the optimizer: %g\n",
killopt);
return 0;
}
--
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Martin Cracauer <cracauer@cons.org> http://www.cons.org/cracauer
BSD User Group Hamburg, Germany http://www.bsdhh.org/
To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-current" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?19980826154241.A22184>
