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