1 #define PETSC_DLL 2 /* 3 * IEEE error handler for all machines. Since each machine has 4 * enough slight differences we have completely separate codes for each one. 5 * 6 */ 7 #include "petsc.h" /*I "petsc.h" I*/ 8 #include "petscsys.h" 9 #include <signal.h> 10 #if defined(PETSC_HAVE_STDLIB_H) 11 #include <stdlib.h> 12 #endif 13 #include "petscfix.h" 14 15 16 /*--------------------------------------- ---------------------------------------------------*/ 17 #if defined(PETSC_HAVE_SUN4_STYLE_FPTRAP) 18 #include <floatingpoint.h> 19 20 EXTERN_C_BEGIN 21 PetscErrorCode ieee_flags(char*,char*,char*,char**); 22 PetscErrorCode ieee_handler(char *,char *,sigfpe_handler_type(int,int,struct sigcontext*,char *)); 23 EXTERN_C_END 24 25 struct { int code_no; char *name; } error_codes[] = { 26 { FPE_INTDIV_TRAP ,"integer divide" }, 27 { FPE_FLTOPERR_TRAP ,"IEEE operand error" }, 28 { FPE_FLTOVF_TRAP ,"floating point overflow" }, 29 { FPE_FLTUND_TRAP ,"floating point underflow" }, 30 { FPE_FLTDIV_TRAP ,"floating pointing divide" }, 31 { FPE_FLTINEX_TRAP ,"inexact floating point result" }, 32 { 0 ,"unknown error" } 33 } ; 34 #define SIGPC(scp) (scp->sc_pc) 35 36 #undef __FUNCT__ 37 #define __FUNCT__ "PetscDefaultFPTrap" 38 sigfpe_handler_type PetscDefaultFPTrap(int sig,int code,struct sigcontext *scp,char *addr) 39 { 40 PetscErrorCode ierr; 41 int err_ind = -1,j; 42 43 PetscFunctionBegin; 44 for (j = 0 ; error_codes[j].code_no ; j++) { 45 if (error_codes[j].code_no == code) err_ind = j; 46 } 47 48 if (err_ind >= 0) { 49 (*PetscErrorPrintf)("*** %s occurred at pc=%X ***\n",error_codes[err_ind].name,SIGPC(scp)); 50 } else { 51 (*PetscErrorPrintf)("*** floating point error 0x%x occurred at pc=%X ***\n",code,SIGPC(scp)); 52 } 53 ierr = PetscError(PETSC_ERR_FP,"User provided function","Unknown file","Unknown directory",PETSC_ERR_FP,1,"floating point error"); 54 MPI_Abort(PETSC_COMM_WORLD,0); 55 PetscFunctionReturn(0); 56 } 57 58 #undef __FUNCT__ 59 #define __FUNCT__ "PetscSetFPTrap" 60 /*@ 61 PetscSetFPTrap - Enables traps/exceptions on common floating point errors. 62 This option may not work on certain machines. 63 64 Not Collective 65 66 Input Parameters: 67 . flag - PETSC_FP_TRAP_ON, PETSC_FP_TRAP_OFF. 68 69 Options Database Keys: 70 . -fp_trap - Activates floating point trapping 71 72 Level: advanced 73 74 Description: 75 On systems that support it, this routine causes floating point 76 overflow, divide-by-zero, and invalid-operand (e.g., a NaN) to 77 cause a message to be printed and the program to exit. 78 79 Caution: 80 On certain machines, in particular the IBM rs6000, floating point 81 trapping is VERY slow! 82 83 Concepts: floating point exceptions^trapping 84 Concepts: divide by zero 85 86 @*/ 87 PetscErrorCode PetscSetFPTrap(PetscFPTrap flag) 88 { 89 char *out; 90 91 PetscFunctionBegin; 92 /* Clear accumulated exceptions. Used to suppress meaningless messages from f77 programs */ 93 (void) ieee_flags("clear","exception","all",&out); 94 if (flag == PETSC_FP_TRAP_ON) { 95 if (ieee_handler("set","common",PetscDefaultFPTrap)) { 96 /* 97 To trap more fp exceptions, including undrflow, change the above line to 98 if (ieee_handler("set","all",PetscDefaultFPTrap)) { 99 */ 100 (*PetscErrorPrintf)("Can't set floatingpoint handler\n"); 101 } 102 } else { 103 if (ieee_handler("clear","common",PetscDefaultFPTrap)) { 104 (*PetscErrorPrintf)("Can't clear floatingpoint handler\n"); 105 } 106 } 107 PetscFunctionReturn(0); 108 } 109 110 /* -------------------------------------------------------------------------------------------*/ 111 #elif defined(PETSC_HAVE_SOLARIS_STYLE_FPTRAP) 112 #include <sunmath.h> 113 #include <floatingpoint.h> 114 #include <siginfo.h> 115 #include <ucontext.h> 116 117 struct { int code_no; char *name; } error_codes[] = { 118 { FPE_FLTINV,"invalid floating point operand"}, 119 { FPE_FLTRES,"inexact floating point result"}, 120 { FPE_FLTDIV,"division-by-zero"}, 121 { FPE_FLTUND,"floating point underflow"}, 122 { FPE_FLTOVF,"floating point overflow"}, 123 { 0, "unknown error"} 124 }; 125 #define SIGPC(scp) (scp->si_addr) 126 127 #undef __FUNCT__ 128 #define __FUNCT__ "PetscDefaultFPTrap" 129 void PetscDefaultFPTrap(int sig,siginfo_t *scp,ucontext_t *uap) 130 { 131 int err_ind,j,code = scp->si_code; 132 PetscErrorCode ierr; 133 134 PetscFunctionBegin; 135 err_ind = -1 ; 136 for (j = 0 ; error_codes[j].code_no ; j++) { 137 if (error_codes[j].code_no == code) err_ind = j; 138 } 139 140 if (err_ind >= 0) { 141 (*PetscErrorPrintf)("*** %s occurred at pc=%X ***\n",error_codes[err_ind].name,SIGPC(scp)); 142 } else { 143 (*PetscErrorPrintf)("*** floating point error 0x%x occurred at pc=%X ***\n",code,SIGPC(scp)); 144 } 145 ierr = PetscError(0,"User provided function","Unknown file","Unknown directory",PETSC_ERR_FP,1,"floating point error"); 146 MPI_Abort(PETSC_COMM_WORLD,0); 147 } 148 149 #undef __FUNCT__ 150 #define __FUNCT__ "PetscSetFPTrap" 151 PetscErrorCode PetscSetFPTrap(PetscFPTrap flag) 152 { 153 char *out; 154 155 PetscFunctionBegin; 156 /* Clear accumulated exceptions. Used to suppress meaningless messages from f77 programs */ 157 (void) ieee_flags("clear","exception","all",&out); 158 if (flag == PETSC_FP_TRAP_ON) { 159 if (ieee_handler("set","common",(sigfpe_handler_type)PetscDefaultFPTrap)) { 160 (*PetscErrorPrintf)("Can't set floating point handler\n"); 161 } 162 } else { 163 if (ieee_handler("clear","common",(sigfpe_handler_type)PetscDefaultFPTrap)) { 164 (*PetscErrorPrintf)("Can't clear floatingpoint handler\n"); 165 } 166 } 167 PetscFunctionReturn(0); 168 } 169 170 /* ------------------------------------------------------------------------------------------*/ 171 172 #elif defined (PETSC_HAVE_IRIX_STYLE_FPTRAP) 173 #include <sigfpe.h> 174 struct { int code_no; char *name; } error_codes[] = { 175 { _INVALID ,"IEEE operand error" }, 176 { _OVERFL ,"floating point overflow" }, 177 { _UNDERFL ,"floating point underflow" }, 178 { _DIVZERO ,"floating point divide" }, 179 { 0 ,"unknown error" } 180 } ; 181 #undef __FUNCT__ 182 #define __FUNCT__ "PetscDefaultFPTrap" 183 void PetscDefaultFPTrap(unsigned exception[],int val[]) 184 { 185 int err_ind,j,code; 186 187 PetscFunctionBegin; 188 code = exception[0]; 189 err_ind = -1 ; 190 for (j = 0 ; error_codes[j].code_no ; j++){ 191 if (error_codes[j].code_no == code) err_ind = j; 192 } 193 if (err_ind >= 0){ 194 (*PetscErrorPrintf)("*** %s occurred ***\n",error_codes[err_ind].name); 195 } else{ 196 (*PetscErrorPrintf)("*** floating point error 0x%x occurred ***\n",code); 197 } 198 PetscError(0,"User provided function","Unknown file","Unknown directory",PETSC_ERR_FP,1,"floating point error"); 199 MPI_Abort(PETSC_COMM_WORLD,0); 200 } 201 202 #undef __FUNCT__ 203 #define __FUNCT__ "PetscSetFPTrap" 204 PetscErrorCode PetscSetFPTrap(PetscFPTrap flag) 205 { 206 PetscFunctionBegin; 207 if (flag == PETSC_FP_TRAP_ON) { 208 handle_sigfpes(_ON,_EN_OVERFL|_EN_DIVZERO|_EN_INVALID,PetscDefaultFPTrap,_ABORT_ON_ERROR,0); 209 } else { 210 handle_sigfpes(_OFF,_EN_OVERFL|_EN_DIVZERO|_EN_INVALID,0,_ABORT_ON_ERROR,0); 211 } 212 PetscFunctionReturn(0); 213 } 214 /*----------------------------------------------- --------------------------------------------*/ 215 /* In "fast" mode, floating point traps are imprecise and ignored. 216 This is the reason for the fptrap(FP_TRAP_SYNC) call */ 217 #elif defined(PETSC_HAVE_RS6000_STYLE_FPTRAP) 218 struct sigcontext; 219 #include <fpxcp.h> 220 #include <fptrap.h> 221 #include <stdlib.h> 222 #define FPE_FLTOPERR_TRAP (fptrap_t)(0x20000000) 223 #define FPE_FLTOVF_TRAP (fptrap_t)(0x10000000) 224 #define FPE_FLTUND_TRAP (fptrap_t)(0x08000000) 225 #define FPE_FLTDIV_TRAP (fptrap_t)(0x04000000) 226 #define FPE_FLTINEX_TRAP (fptrap_t)(0x02000000) 227 228 struct { int code_no; char *name; } error_codes[] = { 229 {FPE_FLTOPERR_TRAP ,"IEEE operand error" }, 230 { FPE_FLTOVF_TRAP ,"floating point overflow" }, 231 { FPE_FLTUND_TRAP ,"floating point underflow" }, 232 { FPE_FLTDIV_TRAP ,"floating point divide" }, 233 { FPE_FLTINEX_TRAP ,"inexact floating point result" }, 234 { 0 ,"unknown error" } 235 } ; 236 #define SIGPC(scp) (0) /* Info MIGHT be in scp->sc_jmpbuf.jmp_context.iar */ 237 /* 238 For some reason, scp->sc_jmpbuf does not work on the RS6000, even though 239 it looks like it should from the include definitions. It is probably 240 some strange interaction with the "POSIX_SOURCE" that we require. 241 */ 242 243 #undef __FUNCT__ 244 #define __FUNCT__ "PetscDefaultFPTrap" 245 void PetscDefaultFPTrap(int sig,int code,struct sigcontext *scp) 246 { 247 PetscErrorCode ierr; 248 int err_ind,j; 249 fp_ctx_t flt_context; 250 251 PetscFunctionBegin; 252 fp_sh_trap_info(scp,&flt_context); 253 254 err_ind = -1 ; 255 for (j = 0 ; error_codes[j].code_no ; j++) { 256 if (error_codes[j].code_no == flt_context.trap) err_ind = j; 257 } 258 259 if (err_ind >= 0){ 260 (*PetscErrorPrintf)("*** %s occurred ***\n",error_codes[err_ind].name); 261 } else{ 262 (*PetscErrorPrintf)("*** floating point error 0x%x occurred ***\n",flt_context.trap); 263 } 264 ierr = PetscError(0,"User provided function","Unknown file","Unknown directory",PETSC_ERR_FP,1,"floating point error"); 265 MPI_Abort(PETSC_COMM_WORLD,0); 266 } 267 268 #undef __FUNCT__ 269 #define __FUNCT__ "PetscSetFPTrap" 270 PetscErrorCode PetscSetFPTrap(PetscFPTrap on) 271 { 272 int flag; 273 274 PetscFunctionBegin; 275 if (on == PETSC_FP_TRAP_ON) { 276 signal(SIGFPE,(void (*)(int))PetscDefaultFPTrap); 277 fp_trap(FP_TRAP_SYNC); 278 fp_enable(TRP_INVALID | TRP_DIV_BY_ZERO | TRP_OVERFLOW); 279 /* fp_enable(mask) for individual traps. Values are: 280 TRP_INVALID 281 TRP_DIV_BY_ZERO 282 TRP_OVERFLOW 283 TRP_UNDERFLOW 284 TRP_INEXACT 285 Can OR then together. 286 fp_enable_all(); for all traps. 287 */ 288 } else { 289 signal(SIGFPE,SIG_DFL); 290 fp_disable(TRP_INVALID | TRP_DIV_BY_ZERO | TRP_OVERFLOW); 291 fp_trap(FP_TRAP_OFF); 292 } 293 PetscFunctionReturn(0); 294 } 295 296 /* -------------------------Default -----------------------------------*/ 297 #else 298 struct PETSCERRORCODES { int code_no; const char *name; } error_codes[] = { 299 { 0 ,"unknown error" } 300 } ; 301 EXTERN_C_BEGIN 302 #undef __FUNCT__ 303 #define __FUNCT__ "PetscDefaultFPTrap" 304 void PetscDefaultFPTrap(int sig) 305 { 306 PetscFunctionBegin; 307 (*PetscErrorPrintf)("*** floating point error occurred ***\n"); 308 PetscError(0,"User provided function","Unknown file","Unknown directory",PETSC_ERR_FP,1,"floating point error"); 309 MPI_Abort(PETSC_COMM_WORLD,0); 310 } 311 EXTERN_C_END 312 #undef __FUNCT__ 313 #define __FUNCT__ "PetscSetFPTrap" 314 PetscErrorCode PETSC_DLLEXPORT PetscSetFPTrap(PetscFPTrap on) 315 { 316 PetscFunctionBegin; 317 if (on == PETSC_FP_TRAP_ON) { 318 if (SIG_ERR == signal(SIGFPE,PetscDefaultFPTrap)) { 319 (*PetscErrorPrintf)("Can't set floatingpoint handler\n"); 320 } 321 } else { 322 if (SIG_ERR == signal(SIGFPE,SIG_DFL)) { 323 (*PetscErrorPrintf)("Can't clear floatingpoint handler\n"); 324 } 325 } 326 PetscFunctionReturn(0); 327 } 328 #endif 329 330 331 332