Port-amd64 archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

SIGFPE for inexact result do not set si_code to FPE_FLTRES ?



Hi,

I do have a test code (attached) to exercise the fpsetmask() function
which works fine on both i386 and alpha (if compiled with
-mieee-with-inexact) but fails on amd64.

For a floating point inexact result, when unmasked, a SIGFPE signal is
correctly sent but the siginfo si_code member is not set to
FPE_FLTRES.

Do i miss something or this is a bug ?

Thanks.

-- 
Nicolas Joly

Projects and Developments in Bioinformatics
Institut Pasteur, Paris.
#include <assert.h>
#include <err.h>
#include <float.h>
#include <ieeefp.h>
#include <math.h>
#include <setjmp.h>
#include <signal.h>
#include <stdlib.h>

static sigjmp_buf fpe;

void fltbogus(int sig, siginfo_t *inf, void *ctx) {
  siglongjmp(fpe, -1); }

void flthandler(int sig, siginfo_t *inf, void *ctx) {
  siglongjmp(fpe, inf->si_code); }

fp_except_t msks[] = { FP_X_INV, FP_X_DZ, FP_X_OFL, FP_X_UFL, FP_X_IMP };

int main() {
  double volatile d;
  int volatile i;
  fp_except_t msk;
  struct sigaction sa;

  msk = fpgetmask();

  for (i = 0; i < __arraycount(msks); i++) {
    (void)fpsetmask(msk | msks[i]);
    msk = fpgetmask();
    assert((msk & msks[i]) != 0);
    (void)fpsetmask(msk & ~msks[i]);
    msk = fpgetmask();
    assert((msk & msks[i]) == 0); }

  sa.sa_flags = SA_RESETHAND|SA_SIGINFO;
  sigemptyset(&sa.sa_mask);

  (void)fpsetmask(msk | FP_X_INV);
  (void)fpsetsticky(0);
  i = sigsetjmp(fpe, 1);
  if (i == 0) {
    sa.sa_sigaction = flthandler;
    sigaction(SIGFPE, &sa, NULL);
    d = 0.0; d /= 0.0;
    d = 1.0; d *= 1.0; }
  assert(i == FPE_FLTINV);

  (void)fpsetmask(msk & ~FP_X_INV);
  (void)fpsetsticky(0);
  i = sigsetjmp(fpe, 1);
  if (i == 0) {
    sa.sa_sigaction = fltbogus;
    sigaction(SIGFPE, &sa, NULL);
    d = 0.0; d /= 0.0;
    d = 1.0; d *= 1.0; }
  assert(i == 0);

  (void)fpsetmask(msk | FP_X_DZ);
  (void)fpsetsticky(0);
  i = sigsetjmp(fpe, 1);
  if (i == 0) {
    sa.sa_sigaction = flthandler;
    sigaction(SIGFPE, &sa, NULL);
    d = 1.0; d /= 0.0;
    d = 1.0; d *= 1.0; }
  assert(i == FPE_FLTDIV);

  (void)fpsetmask(msk & ~FP_X_DZ);
  (void)fpsetsticky(0);
  i = sigsetjmp(fpe, 1);
  if (i == 0) {
    sa.sa_sigaction = fltbogus;
    sigaction(SIGFPE, &sa, NULL);
    d = 1.0; d /= 0.0;
    d = 1.0; d *= 1.0; }
  assert(i == 0);

  (void)fpsetmask(msk | FP_X_OFL);
  (void)fpsetsticky(0);
  i = sigsetjmp(fpe, 1);
  if (i == 0) {
    sa.sa_sigaction = flthandler;
    sigaction(SIGFPE, &sa, NULL);
    d = DBL_MAX; d *= DBL_MAX;
    d = 1.0; d *= 1.0; }
  assert(i == FPE_FLTOVF);

  (void)fpsetmask(msk & ~FP_X_OFL);
  (void)fpsetsticky(0);
  i = sigsetjmp(fpe, 1);
  if (i == 0) {
    sa.sa_sigaction = fltbogus;
    sigaction(SIGFPE, &sa, NULL);
    d = DBL_MAX; d *= DBL_MAX;
    d = 1.0; d *= 1.0; }
  assert(i == 0);

  (void)fpsetmask(msk | FP_X_UFL);
  (void)fpsetsticky(0);
  i = sigsetjmp(fpe, 1);
  if (i == 0) {
    sa.sa_sigaction = flthandler;
    sigaction(SIGFPE, &sa, NULL);
    d = DBL_MIN; d *= DBL_MIN;
    d = 1.0; d *= 1.0; }
  assert(i == FPE_FLTUND);

  (void)fpsetmask(msk & ~FP_X_UFL);
  (void)fpsetsticky(0);
  i = sigsetjmp(fpe, 1);
  if (i == 0) {
    sa.sa_sigaction = fltbogus;
    sigaction(SIGFPE, &sa, NULL);
    d = DBL_MIN; d *= DBL_MIN;
    d = 1.0; d *= 1.0; }
  assert(i == 0);

  (void)fpsetmask(msk | FP_X_IMP);
  (void)fpsetsticky(0);
  i = sigsetjmp(fpe, 1);
  if (i == 0) {
    sa.sa_sigaction = flthandler;
    sigaction(SIGFPE, &sa, NULL);
    d = 1.0; d /= 3.0;
    d = 1.0; d *= 1.0; }
  assert(i == FPE_FLTRES);

  (void)fpsetmask(msk & ~FP_X_IMP);
  (void)fpsetsticky(0);
  i = sigsetjmp(fpe, 1);
  if (i == 0) {
    sa.sa_sigaction = fltbogus;
    sigaction(SIGFPE, &sa, NULL);
    d = 1.0; d /= 3.0;
    d = 1.0; d *= 1.0; }
  assert(i == 0);

  return 0; }


Home | Main Index | Thread Index | Old Index