Skip site navigation (1)Skip section navigation (2)
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>