Date: Sun, 30 Aug 1998 17:51:49 +0200 From: Martin Cracauer <cracauer@cons.org> To: Bruce Evans <bde@zeta.org.au>, cracauer@cons.org, current@FreeBSD.ORG, luoqi@watermarkgroup.com, shocking@prth.pgs.com Subject: Re: Floating Point Exceptions, signal handlers & subsequent ops Message-ID: <19980830175149.A22835@cons.org> In-Reply-To: <199808270253.MAA15661@godzilla.zeta.org.au>; from Bruce Evans on Thu, Aug 27, 1998 at 12:53:36PM %2B1000 References: <199808270253.MAA15661@godzilla.zeta.org.au>
next in thread | previous in thread | raw e-mail | index | archive | help
--envbJBWh7q8WU6mo Content-Type: text/plain; charset=us-ascii In <199808270253.MAA15661@godzilla.zeta.org.au>, Bruce Evans wrote: > >Ah, now I got it. > > > >If sig == SIGFPE, then expect the trap code to be one of FPE_*_TRAP > >values from machine/trap.h, *not* one of the T_* values. > > Except this is not implemented. Does the appended diff count as an implementation? Test program included. I'm sure I violate more kernel code rules that DBL_MAX can express :-) > >Why is this, why two classes of trap codes? > > T_* is for the kernel and is unportable. FPE_* is for the user SIGFPE > handler and is not so unportable in theory. I found that the FP_X_ macros are in wide enough use to be valuable for portable code. I changed the values of the non-FPU SIGFPE macros on x86 so that they are in the same value domain as the FP_X_ macros. Thus, in a SIGFPE handler you'll find one of the FP_X_ or FPE_......_TRAP macros as the second argument to the handler. IMHO the fact that the argument can be from one of two completely different macros sets models the fact that you'll get non-FPU exceptions to your FPE handler on a x86 machine quite well. Martin -- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Martin Cracauer <cracauer@cons.org> http://www.cons.org/cracauer BSD User Group Hamburg, Germany http://www.bsdhh.org/ --envbJBWh7q8WU6mo Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="diff.float" ? compile/WINGS ? i386/conf/WINGS ? i386/conf/WINGS.from-SMP-GENERIC Index: i386/i386/machdep.c =================================================================== RCS file: /home/CVS-FreeBSD/src/sys/i386/i386/machdep.c,v retrieving revision 1.304 diff -c -r1.304 machdep.c *** machdep.c 1998/08/18 07:46:58 1.304 --- machdep.c 1998/08/30 00:22:59 *************** *** 136,141 **** --- 136,143 ---- #include <machine/random.h> #include <sys/ptrace.h> + #include <machine/floatingpoint.h> + extern void init386 __P((int first)); extern void dblfault_handler __P((void)); *************** *** 502,508 **** --- 504,515 ---- struct sigframe sf; struct sigacts *psp = p->p_sigacts; int oonstack; + u_long fpuctrl; + if (sig == SIGFPE && code == 0) { + __fnstcw(&fpuctrl); + code = 0x3F & ~fpuctrl & curpcb->pcb_savefpu.sv_ex_sw; + } regs = p->p_md.md_regs; oonstack = psp->ps_sigstk.ss_flags & SS_ONSTACK; /* Index: i386/include/trap.h =================================================================== RCS file: /home/CVS-FreeBSD/src/sys/i386/include/trap.h,v retrieving revision 1.7 diff -c -r1.7 trap.h *** trap.h 1997/02/22 09:35:19 1.7 --- trap.h 1998/08/30 00:23:00 *************** *** 76,89 **** #define ILL_ALIGN_FAULT T_ALIGNFLT #define ILL_FPOP_FAULT T_FPOPFLT /* coprocessor operand fault */ ! /* codes for SIGFPE/ARITHTRAP */ ! #define FPE_INTOVF_TRAP 0x1 /* integer overflow */ ! #define FPE_INTDIV_TRAP 0x2 /* integer divide by zero */ ! #define FPE_FLTDIV_TRAP 0x3 /* floating/decimal divide by zero */ ! #define FPE_FLTOVF_TRAP 0x4 /* floating overflow */ ! #define FPE_FLTUND_TRAP 0x5 /* floating underflow */ ! #define FPE_FPU_NP_TRAP 0x6 /* floating point unit not present */ ! #define FPE_SUBRNG_TRAP 0x7 /* subrange out of bounds */ /* codes for SIGBUS */ #define BUS_PAGE_FAULT T_PAGEFLT /* page fault protection base */ --- 76,92 ---- #define ILL_ALIGN_FAULT T_ALIGNFLT #define ILL_FPOP_FAULT T_FPOPFLT /* coprocessor operand fault */ ! /* ! * codes for SIGFPE/ARITHTRAP ! * avoid values used for FPU exceptions (FP_X_...) ! */ ! #define FPE_INTOVF_TRAP 0xFF01 /* integer overflow */ ! #define FPE_INTDIV_TRAP 0xFF02 /* integer divide by zero */ ! #define FPE_FLTDIV_TRAP 0xFF03 /* floating/decimal divide by zero */ ! #define FPE_FLTOVF_TRAP 0xFF04 /* floating overflow */ ! #define FPE_FLTUND_TRAP 0xFF05 /* floating underflow */ ! #define FPE_FPU_NP_TRAP 0xFF06 /* floating point unit not present */ ! #define FPE_SUBRNG_TRAP 0xFF07 /* subrange out of bounds */ /* codes for SIGBUS */ #define BUS_PAGE_FAULT T_PAGEFLT /* page fault protection base */ --envbJBWh7q8WU6mo Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="freebsd-signal.c" #include <stdio.h> #include <signal.h> #include <setjmp.h> #include <sys/types.h> #include <unistd.h> #include <math.h> #include <float.h> #include <floatingpoint.h> volatile static sig_atomic_t sig_fpe_was_here = 0; volatile static int sig_sig; volatile static int sig_code; static struct sigcontext sig_context; static jmp_buf jmpbuf; static int handler(int sig, int code, struct sigcontext *scp) { #if 0 #define TMP "FPE handler\n" write(2,TMP,sizeof(TMP)-1); #undef TMP #endif sig_fpe_was_here++; sig_sig = sig; sig_code = code; memcpy(&sig_context, scp, sizeof(*scp)); longjmp(jmpbuf,1); return sig; } static const char * codestring(int code) { switch (code) { case FPE_INTOVF_TRAP: return "FPE_INTOVF_TRAP"; case FPE_INTDIV_TRAP: return "FPE_INTDIV_TRAP"; case FPE_FPU_NP_TRAP: return "FPE_FPU_NP_TRAP"; case FPE_SUBRNG_TRAP: return "FPE_SUBRNG_TRAP"; case FP_X_INV : return "FP_X_INV"; case FP_X_DNML: return "FP_X_DNML"; case FP_X_DZ : return "FP_X_DZ "; case FP_X_OFL : return "FP_X_OFL"; case FP_X_UFL : return "FP_X_UFL"; case FP_X_IMP : return "FP_X_IMP"; default: return "Unknwon code"; } } #if 0 static double deopt(double d) { return d; } #endif static double l_idiv(double p1, double p2) { return (double)((int)p1 / (int)p2); } static double l_fadd(double p1, double p2) { return p1 + p2; } static double l_fmul(double p1, double p2) { return p1 * p2; } static double l_fdiv(double p1, double p2) { return p1 / p2; } static double l_fsub(double p1, double p2) { return p1 - p2; } static double l_sin(double p1, double p2) { return sin(p1); } static double l_sqrt(double p1, double p2) { return sqrt(p1); } typedef double (test_f_t)(double, double); struct funcpair { test_f_t *func; const double p1; const double p2; const char *const descr; } const funcs[] = { {l_idiv, 0.0, 0.0, "int 0/0 "}, {l_idiv, 1.0, 0.0, "int 1/0 "}, {l_fdiv, 0.0, 0.0, "dbl 0/0 "}, {l_fdiv, 1.0, 0.0, "dbl 1/0 "}, {l_fdiv, DBL_MIN, DBL_MIN, "dbl MIN/MIN "}, {l_fdiv, DBL_MIN, 2.0, "dbl MIN/2 "}, {l_fsub, DBL_MIN, DBL_MIN, "dbl MIN-MIN "}, {l_fmul, DBL_MAX, 2.0, "dbl 2*MAX "}, {l_fmul, DBL_MAX, DBL_MAX, "dbl MAX*MAX "}, {l_fadd, DBL_MAX, DBL_MAX, "dbl MAX+MAX "}, {l_sin, 10.0, 0.0, "dbl sin(10.0)"}, {l_sqrt, -1.0, 0.0, "dbl sqrt(-1) "}, {NULL, NULL} }; #define forcefpe() asm("wait") static void dotests(void) { const struct funcpair *volatile it; double res; it = funcs; while (it->func) { fprintf(stderr, "Function '%s'", it->descr); if (setjmp(jmpbuf) == 0) { res = it->func(it->p1, it->p2); forcefpe(); fprintf(stderr, " survived, res: %g", res); } else { if (sig_fpe_was_here != 1) { fprintf(stderr,"Strange, %d exception after jongjmp\n" , sig_fpe_was_here); exit(2); } sig_fpe_was_here = 0; fprintf(stderr, " signal %d, code %-20s (%2d)" , sig_sig , codestring(sig_code) , sig_code ); } fputc('\n', stderr); it++; } } int main(int argc, char *argv[]) { int oldmask; fprintf(stderr,"Round: %x, Precision: %x\n", fpgetround(), fpgetprec()); oldmask = fpgetmask(); signal(SIGFPE,(__sighandler_t *)handler); fprintf(stderr,"Testing with all exceptions enabled\n"); fpsetmask(FP_X_INV|FP_X_DNML|FP_X_DZ|FP_X_OFL|FP_X_UFL|FP_X_IMP); dotests(); fprintf(stderr,"Testing with all exceptions except precision loss\n"); fpsetmask(FP_X_INV|FP_X_DNML|FP_X_DZ|FP_X_OFL|FP_X_UFL); dotests(); fprintf(stderr,"Testing with exceptions disabled\n"); fpsetmask(0L); dotests(); fprintf(stderr,"Round: %x, Precision: %x\n", fpgetround(), fpgetprec()); return 0; } --envbJBWh7q8WU6mo-- 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?19980830175149.A22835>