/* IBM_PROLOG_BEGIN_TAG */ /* This is an automatically generated prolog. */ /* */ /* bos720 src/bos/usr/samples/fp/sigfpe_samp2.c 1.1 */ /* */ /* Licensed Materials - Property of IBM */ /* */ /* COPYRIGHT International Business Machines Corp. 1993 */ /* All Rights Reserved */ /* */ /* US Government Users Restricted Rights - Use, duplication or */ /* disclosure restricted by GSA ADP Schedule Contract with IBM Corp. */ /* */ /* IBM_PROLOG_END_TAG */ static char sccsid[] = "@(#)78 1.1 src/bos/usr/samples/fp/sigfpe_samp2.c, fpsamp, bos720 9/8/93 10:22:22"; /* * COMPONENT_NAME: BOSSAMP * * FUNCTIONS: f_trap_sigfpe * sigfpe_handler * * ORIGINS: 27 * * * (C) COPYRIGHT International Business Machines Corp. 1993 * All Rights Reserved * Licensed Materials - Property of IBM * US Government Users Restricted Rights - Use, duplication or * disclosure restricted by GSA ADP Schedule Contract with IBM Corp. */ /* * This demonstates a floating point exception handler, * and some glue code to set up floating point exception * traping. The glue code can be called from Fortran. */ #include #include #include #include #include /* * the fp_list structure will allow text descriptions * of each possible trap type to be tied to the mask * which identifies it. */ typedef struct { fpflag_t mask; char *text; } fp_list_t; /* IEEE required trap types */ fp_list_t trap_list[] = { { FP_INVALID, "FP_INVALID"}, { FP_OVERFLOW, "FP_OVERFLOW"}, { FP_UNDERFLOW, "FP_UNDERFLOW"}, { FP_DIV_BY_ZERO, "FP_DIV_BY_ZERO"}, { FP_INEXACT, "FP_INEXACT"} }; /* INEXACT detail list -- this is an IBM RISC System/6000 extension */ fp_list_t detail_list[] = { { FP_INV_SNAN, "FP_INV_SNAN" } , { FP_INV_ISI, "FP_INV_ISI" } , { FP_INV_IDI, "FP_INV_IDI" } , { FP_INV_ZDZ, "FP_INV_ZDZ" } , { FP_INV_IMZ, "FP_INV_IMZ" } , { FP_INV_CMP, "FP_INV_CMP" } , { FP_INV_SQRT, "FP_INV_SQRT" } , { FP_INV_CVI, "FP_INV_CVI" } , { FP_INV_VXSOFT, "FP_INV_VXSOFT" } }; /* * NAME: sigfpe_handler * * FUNCTION: a trap handler which is entered when * a floating point exception occurs. The * functions determines what exception(s) caused * the trap, prints this to stdout, and returns * to the process which caused the trap. * * NOTES: * When entered, all floating point traps are * disabled. * * This sample uses printf(). This should be used * with caution since since printf() of a floating * point number can cause a trap, and then a * another printf() of a floating point number * in the signal handler will corrupt the static * buffer used for the conversion. * * OUTPUTS: The type of exception(s) which caused * the trap. */ static void sigfpe_handler(int sig, int code, struct sigcontext *SCP) { struct mstsave * state = &SCP->sc_jmpbuf.jmp_context; fp_sh_info_t flt_context; /* structure for fp_sh_info() call */ int i; /* loop counter */ /* * Determine which floating point exception(s) caused * the trap. fp_sh_info() is used to build the floating signal * handler info structure, and then the member flt_context.trap * can be examined. First the trap type is compared for the IEEE * required traps, and if the trap type is an invalid operation, * the detail bits are examined. */ fp_sh_info(SCP, &flt_context, FP_SH_INFO_SIZE); for (i = 0; i < (sizeof(trap_list) / sizeof(fp_list_t)); i++) { if (flt_context.trap & trap_list[i].mask) (void) printf("Trap caused by %s error\n", trap_list[i].text); } if (flt_context.trap & FP_INVALID) { for (i = 0; i < (sizeof(detail_list) / sizeof(fp_list_t)); i++) { if (flt_context.trap & detail_list[i].mask) (void) printf("Type of invalid op is %s\n", detail_list[i].text); } } /* report which trap mode was in effect */ switch (flt_context.trap_mode) { case FP_TRAP_OFF: puts("Trapping Mode is OFF"); break; case FP_TRAP_SYNC: puts("Trapping Mode is SYNC"); break; case FP_TRAP_IMP: puts("Trapping Mode is IMP"); break; case FP_TRAP_IMP_REC: puts("Trapping Mode is IMP_REC"); break; default: puts("ERROR: Invalid trap mode"); } (void) fflush(stdout); /* clear exception bits to prevent recurrence of trap */ fp_sh_set_stat(SCP, (flt_context.fpscr & ((fpstat_t) ~flt_context.trap))); /* * increment the iar of the process that caused the trap, to prevent * re-execution of the instruction. * * The FP_IAR_STAT bit in flt_context.flags indicates if state->iar points * to an instruction which has logically been started. If this bit is true, * state->iar points to an operation which has been started, and if re-executed * will cause another exception. In this case we want to continue execution and * ignore the results of that operation, so the iar is advanced to point to the * next instruction. If the bit is false, the iar already points to the next * instruction which must be executed. */ if ( flt_context.flags & FP_IAR_STAT ) { puts("Increment IAR"); state->iar += 4; } return; } #define TRAP_OFF 0 #define TRAP_ON 1 /* * NAME: f_trap_sigfpe * * FUNCTION: provide a sample interface for Fortran to * enable/disable traping. * * DESCRIPTION: The first argument is an action * code. If non-zero, the call will establish * sigfpe_handler() as the trap handler for * for sigfpe, put the process in synchronous * execution mode, and enable the trap(s) * specified by the second argument. * * If the second argument is zero, the call * will remove the sigfpe_handler (if installed), * put the process in synchonous execution mode, * and disable all traps. */ void f_trap_sigfpe(int *action, fptrap_t *trap_type) { struct sigaction response; static struct sigaction old_response; static int trap_status = TRAP_OFF; /* if action is zero, then turn off trapping, and * also restore previous signal handler(s) if any. */ if (! *action) { (void) fp_trap(FP_TRAP_OFF); fp_disable_all(); if (trap_status) { trap_status = TRAP_OFF; (void) sigaction(SIGFPE, &old_response, NULL); } } else { if (! trap_status) { (void) sigaction(SIGFPE, NULL, &old_response); (void) sigemptyset(&response.sa_mask); response.sa_flags = FALSE; response.sa_handler = (void (*)(int)) sigfpe_handler; (void) sigaction(SIGFPE, &response, NULL); (void) fp_trap(FP_TRAP_SYNC); fp_enable(*trap_type); trap_status = TRAP_ON; } } }