1 2 /* 3 IEEE error handler for all machines. Since each OS has 4 enough slight differences we have completely separate codes for each one. 5 */ 6 7 /* 8 This feature test macro provides FE_NOMASK_ENV on GNU. It must be defined 9 at the top of the file because other headers may pull in fenv.h even when 10 not strictly necessary. Strictly speaking, we could include ONLY petscconf.h, 11 check PETSC_HAVE_FENV_H, and only define _GNU_SOURCE in that case, but such 12 shenanigans ought to be unnecessary. 13 */ 14 #if !defined(_GNU_SOURCE) 15 #define _GNU_SOURCE 16 #endif 17 18 #include <petsc/private/petscimpl.h> /*I "petscsys.h" I*/ 19 #include <signal.h> 20 21 struct PetscFPTrapLink { 22 PetscFPTrap trapmode; 23 struct PetscFPTrapLink *next; 24 }; 25 static PetscFPTrap _trapmode = PETSC_FP_TRAP_OFF; /* Current trapping mode; see PetscDetermineInitialFPTrap() */ 26 static struct PetscFPTrapLink *_trapstack; /* Any pushed states of _trapmode */ 27 28 /*@ 29 PetscFPTrapPush - push a floating point trapping mode, restored using PetscFPTrapPop() 30 31 Not Collective 32 33 Input Parameter: 34 . trap - PETSC_FP_TRAP_ON or PETSC_FP_TRAP_OFF 35 36 Level: advanced 37 38 Notes: 39 This only changes the trapping if the new mode is different than the current mode. 40 41 This routine is called to turn off trapping for certain LAPACK routines that assume that dividing 42 by zero is acceptable. In particular the routine ieeeck(). 43 44 Most systems by default have all trapping turned off, but certain Fortran compilers have 45 link flags that turn on trapping before the program begins. 46 $ gfortran -ffpe-trap=invalid,zero,overflow,underflow,denormal 47 $ ifort -fpe0 48 49 .seealso: PetscFPTrapPop(), PetscSetFPTrap(), PetscDetermineInitialFPTrap() 50 @*/ 51 PetscErrorCode PetscFPTrapPush(PetscFPTrap trap) 52 { 53 struct PetscFPTrapLink *link; 54 55 PetscFunctionBegin; 56 PetscCall(PetscNew(&link)); 57 link->trapmode = _trapmode; 58 link->next = _trapstack; 59 _trapstack = link; 60 if (trap != _trapmode) PetscCall(PetscSetFPTrap(trap)); 61 PetscFunctionReturn(0); 62 } 63 64 /*@ 65 PetscFPTrapPop - push a floating point trapping mode, to be restored using PetscFPTrapPop() 66 67 Not Collective 68 69 Level: advanced 70 71 .seealso: PetscFPTrapPush(), PetscSetFPTrap(), PetscDetermineInitialFPTrap() 72 @*/ 73 PetscErrorCode PetscFPTrapPop(void) 74 { 75 struct PetscFPTrapLink *link; 76 77 PetscFunctionBegin; 78 if (_trapstack->trapmode != _trapmode) PetscCall(PetscSetFPTrap(_trapstack->trapmode)); 79 link = _trapstack; 80 _trapstack = _trapstack->next; 81 PetscCall(PetscFree(link)); 82 PetscFunctionReturn(0); 83 } 84 85 /*--------------------------------------- ---------------------------------------------------*/ 86 #if defined(PETSC_HAVE_SUN4_STYLE_FPTRAP) 87 #include <floatingpoint.h> 88 89 PETSC_EXTERN PetscErrorCode ieee_flags(char*,char*,char*,char**); 90 PETSC_EXTERN PetscErrorCode ieee_handler(char*,char*,sigfpe_handler_type(int,int,struct sigcontext*,char*)); 91 92 static struct { int code_no; char *name; } error_codes[] = { 93 { FPE_INTDIV_TRAP ,"integer divide" }, 94 { FPE_FLTOPERR_TRAP ,"IEEE operand error" }, 95 { FPE_FLTOVF_TRAP ,"floating point overflow" }, 96 { FPE_FLTUND_TRAP ,"floating point underflow" }, 97 { FPE_FLTDIV_TRAP ,"floating pointing divide" }, 98 { FPE_FLTINEX_TRAP ,"inexact floating point result" }, 99 { 0 ,"unknown error" } 100 }; 101 #define SIGPC(scp) (scp->sc_pc) 102 103 sigfpe_handler_type PetscDefaultFPTrap(int sig,int code,struct sigcontext *scp,char *addr) 104 { 105 int err_ind = -1; 106 107 PetscFunctionBegin; 108 for (int j = 0; error_codes[j].code_no; j++) { 109 if (error_codes[j].code_no == code) err_ind = j; 110 } 111 112 if (err_ind >= 0) (*PetscErrorPrintf)("*** %s occurred at pc=%X ***\n",error_codes[err_ind].name,SIGPC(scp)); 113 else (*PetscErrorPrintf)("*** floating point error 0x%x occurred at pc=%X ***\n",code,SIGPC(scp)); 114 115 (void)PetscError(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided function","Unknown file",PETSC_ERR_FP,PETSC_ERROR_REPEAT,"floating point error"); 116 PETSCABORT(MPI_COMM_WORLD,PETSC_ERR_FP); 117 PetscFunctionReturn(0); 118 } 119 120 /*@ 121 PetscSetFPTrap - Enables traps/exceptions on common floating point errors. 122 This option may not work on certain systems. 123 124 Not Collective 125 126 Input Parameters: 127 . flag - PETSC_FP_TRAP_ON, PETSC_FP_TRAP_OFF. 128 129 Options Database Keys: 130 . -fp_trap - Activates floating point trapping 131 132 Level: advanced 133 134 Description: 135 On systems that support it, when called with PETSC_FP_TRAP_ON this routine causes floating point 136 underflow, overflow, divide-by-zero, and invalid-operand (e.g., a NaN) to 137 cause a message to be printed and the program to exit. 138 139 Note: 140 On many common systems, the floating 141 point exception state is not preserved from the location where the trap 142 occurred through to the signal handler. In this case, the signal handler 143 will just say that an unknown floating point exception occurred and which 144 function it occurred in. If you run with -fp_trap in a debugger, it will 145 break on the line where the error occurred. On systems that support C99 146 floating point exception handling You can check which 147 exception occurred using fetestexcept(FE_ALL_EXCEPT). See fenv.h 148 (usually at /usr/include/bits/fenv.h) for the enum values on your system. 149 150 Caution: 151 On certain machines, in particular the IBM PowerPC, floating point 152 trapping may be VERY slow! 153 154 .seealso: PetscFPTrapPush(), PetscFPTrapPop(), PetscDetermineInitialFPTrap() 155 @*/ 156 PetscErrorCode PetscSetFPTrap(PetscFPTrap flag) 157 { 158 char *out; 159 160 PetscFunctionBegin; 161 /* Clear accumulated exceptions. Used to suppress meaningless messages from f77 programs */ 162 (void) ieee_flags("clear","exception","all",&out); 163 if (flag == PETSC_FP_TRAP_ON) { 164 /* 165 To trap more fp exceptions, including underflow, change the line below to 166 if (ieee_handler("set","all",PetscDefaultFPTrap)) { 167 */ 168 if (ieee_handler("set","common",PetscDefaultFPTrap)) (*PetscErrorPrintf)("Can't set floatingpoint handler\n"); 169 } else if (ieee_handler("clear","common",PetscDefaultFPTrap)) (*PetscErrorPrintf)("Can't clear floatingpoint handler\n"); 170 171 _trapmode = flag; 172 PetscFunctionReturn(0); 173 } 174 175 /*@ 176 PetscDetermineInitialFPTrap - Attempts to determine the floating point trapping that exists when PetscInitialize() is called 177 178 Not Collective 179 180 Notes: 181 Currently only supported on Linux and MacOS. Checks if divide by zero is enable and if so declares that trapping is on. 182 183 Level: advanced 184 185 .seealso: PetscFPTrapPush(), PetscFPTrapPop(), PetscDetermineInitialFPTrap() 186 @*/ 187 PetscErrorCode PetscDetermineInitialFPTrap(void) 188 { 189 PetscFunctionBegin; 190 PetscCall(PetscInfo(NULL,"Unable to determine initial floating point trapping. Assuming it is off\n")); 191 PetscFunctionReturn(0); 192 } 193 194 /* -------------------------------------------------------------------------------------------*/ 195 #elif defined(PETSC_HAVE_SOLARIS_STYLE_FPTRAP) 196 #include <sunmath.h> 197 #include <floatingpoint.h> 198 #include <siginfo.h> 199 #include <ucontext.h> 200 201 static struct { int code_no; char *name; } error_codes[] = { 202 { FPE_FLTINV,"invalid floating point operand"}, 203 { FPE_FLTRES,"inexact floating point result"}, 204 { FPE_FLTDIV,"division-by-zero"}, 205 { FPE_FLTUND,"floating point underflow"}, 206 { FPE_FLTOVF,"floating point overflow"}, 207 { 0, "unknown error"} 208 }; 209 #define SIGPC(scp) (scp->si_addr) 210 211 void PetscDefaultFPTrap(int sig,siginfo_t *scp,ucontext_t *uap) 212 { 213 int err_ind = -1,code = scp->si_code; 214 215 PetscFunctionBegin; 216 for (int j = 0; error_codes[j].code_no; j++) { 217 if (error_codes[j].code_no == code) err_ind = j; 218 } 219 220 if (err_ind >= 0) (*PetscErrorPrintf)("*** %s occurred at pc=%X ***\n",error_codes[err_ind].name,SIGPC(scp)); 221 else (*PetscErrorPrintf)("*** floating point error 0x%x occurred at pc=%X ***\n",code,SIGPC(scp)); 222 223 (void)PetscError(PETSC_COMM_SELF,0,"User provided function","Unknown file",PETSC_ERR_FP,PETSC_ERROR_REPEAT,"floating point error"); 224 PETSCABORT(MPI_COMM_WORLD,PETSC_ERR_FP); 225 } 226 227 PetscErrorCode PetscSetFPTrap(PetscFPTrap flag) 228 { 229 char *out; 230 231 PetscFunctionBegin; 232 /* Clear accumulated exceptions. Used to suppress meaningless messages from f77 programs */ 233 (void) ieee_flags("clear","exception","all",&out); 234 if (flag == PETSC_FP_TRAP_ON) { 235 if (ieee_handler("set","common",(sigfpe_handler_type)PetscDefaultFPTrap)) (*PetscErrorPrintf)("Can't set floating point handler\n"); 236 } else { 237 if (ieee_handler("clear","common",(sigfpe_handler_type)PetscDefaultFPTrap)) (*PetscErrorPrintf)("Can't clear floatingpoint handler\n"); 238 } 239 _trapmode = flag; 240 PetscFunctionReturn(0); 241 } 242 243 PetscErrorCode PetscDetermineInitialFPTrap(void) 244 { 245 PetscFunctionBegin; 246 PetscCall(PetscInfo(NULL,"Unable to determine initial floating point trapping. Assuming it is off\n")); 247 PetscFunctionReturn(0); 248 } 249 250 /* ------------------------------------------------------------------------------------------*/ 251 #elif defined(PETSC_HAVE_IRIX_STYLE_FPTRAP) 252 #include <sigfpe.h> 253 static struct { int code_no; char *name; } error_codes[] = { 254 { _INVALID ,"IEEE operand error" }, 255 { _OVERFL ,"floating point overflow" }, 256 { _UNDERFL ,"floating point underflow" }, 257 { _DIVZERO ,"floating point divide" }, 258 { 0 ,"unknown error" } 259 } ; 260 void PetscDefaultFPTrap(unsigned exception[],int val[]) 261 { 262 int err_ind = -1,code = exception[0]; 263 264 PetscFunctionBegin; 265 for (int j = 0; error_codes[j].code_no; j++) { 266 if (error_codes[j].code_no == code) err_ind = j; 267 } 268 if (err_ind >= 0) (*PetscErrorPrintf)("*** %s occurred ***\n",error_codes[err_ind].name); 269 else (*PetscErrorPrintf)("*** floating point error 0x%x occurred ***\n",code); 270 271 (void)PetscError(PETSC_COMM_SELF,0,"User provided function","Unknown file",PETSC_ERR_FP,PETSC_ERROR_REPEAT,"floating point error"); 272 PETSCABORT(MPI_COMM_WORLD,PETSC_ERR_FP); 273 } 274 275 PetscErrorCode PetscSetFPTrap(PetscFPTrap flag) 276 { 277 PetscFunctionBegin; 278 if (flag == PETSC_FP_TRAP_ON) handle_sigfpes(_ON,,_EN_UNDERFL|_EN_OVERFL|_EN_DIVZERO|_EN_INVALID,PetscDefaultFPTrap,_ABORT_ON_ERROR,0); 279 else handle_sigfpes(_OFF,_EN_UNDERFL|_EN_OVERFL|_EN_DIVZERO|_EN_INVALID,0,_ABORT_ON_ERROR,0); 280 _trapmode = flag; 281 PetscFunctionReturn(0); 282 } 283 284 PetscErrorCode PetscDetermineInitialFPTrap(void) 285 { 286 PetscFunctionBegin; 287 PetscCall(PetscInfo(NULL,"Unable to determine initial floating point trapping. Assuming it is off\n")); 288 PetscFunctionReturn(0); 289 } 290 291 /* -------------------------------------------------------------------------------------------*/ 292 #elif defined(PETSC_HAVE_SOLARIS_STYLE_FPTRAP) 293 #include <sunmath.h> 294 #include <floatingpoint.h> 295 #include <siginfo.h> 296 #include <ucontext.h> 297 298 static struct { int code_no; char *name; } error_codes[] = { 299 { FPE_FLTINV,"invalid floating point operand"}, 300 { FPE_FLTRES,"inexact floating point result"}, 301 { FPE_FLTDIV,"division-by-zero"}, 302 { FPE_FLTUND,"floating point underflow"}, 303 { FPE_FLTOVF,"floating point overflow"}, 304 { 0, "unknown error"} 305 }; 306 #define SIGPC(scp) (scp->si_addr) 307 308 void PetscDefaultFPTrap(int sig,siginfo_t *scp,ucontext_t *uap) 309 { 310 int err_ind = -1,code = scp->si_code; 311 312 PetscFunctionBegin; 313 err_ind = -1; 314 for (int j = 0; error_codes[j].code_no; j++) { 315 if (error_codes[j].code_no == code) err_ind = j; 316 } 317 318 if (err_ind >= 0) (*PetscErrorPrintf)("*** %s occurred at pc=%X ***\n",error_codes[err_ind].name,SIGPC(scp)); 319 else (*PetscErrorPrintf)("*** floating point error 0x%x occurred at pc=%X ***\n",code,SIGPC(scp)); 320 321 (void)PetscError(PETSC_COMM_SELF,0,"User provided function","Unknown file",PETSC_ERR_FP,PETSC_ERROR_REPEAT,"floating point error"); 322 PETSCABORT(MPI_COMM_WORLD,PETSC_ERR_FP); 323 } 324 325 PetscErrorCode PetscSetFPTrap(PetscFPTrap flag) 326 { 327 char *out; 328 329 PetscFunctionBegin; 330 /* Clear accumulated exceptions. Used to suppress meaningless messages from f77 programs */ 331 (void) ieee_flags("clear","exception","all",&out); 332 if (flag == PETSC_FP_TRAP_ON) { 333 if (ieee_handler("set","common",(sigfpe_handler_type)PetscDefaultFPTrap)) (*PetscErrorPrintf)("Can't set floating point handler\n"); 334 } else { 335 if (ieee_handler("clear","common",(sigfpe_handler_type)PetscDefaultFPTrap)) (*PetscErrorPrintf)("Can't clear floatingpoint handler\n"); 336 } 337 _trapmode = flag; 338 PetscFunctionReturn(0); 339 } 340 341 PetscErrorCode PetscDetermineInitialFPTrap(void) 342 { 343 PetscFunctionBegin; 344 PetscCall(PetscInfo(NULL,"Unable to determine initial floating point trapping. Assuming it is off\n")); 345 PetscFunctionReturn(0); 346 } 347 348 /*----------------------------------------------- --------------------------------------------*/ 349 #elif defined(PETSC_HAVE_RS6000_STYLE_FPTRAP) 350 /* In "fast" mode, floating point traps are imprecise and ignored. 351 This is the reason for the fptrap(FP_TRAP_SYNC) call */ 352 struct sigcontext; 353 #include <fpxcp.h> 354 #include <fptrap.h> 355 #define FPE_FLTOPERR_TRAP (fptrap_t)(0x20000000) 356 #define FPE_FLTOVF_TRAP (fptrap_t)(0x10000000) 357 #define FPE_FLTUND_TRAP (fptrap_t)(0x08000000) 358 #define FPE_FLTDIV_TRAP (fptrap_t)(0x04000000) 359 #define FPE_FLTINEX_TRAP (fptrap_t)(0x02000000) 360 361 static struct { int code_no; char *name; } error_codes[] = { 362 {FPE_FLTOPERR_TRAP ,"IEEE operand error" }, 363 { FPE_FLTOVF_TRAP ,"floating point overflow" }, 364 { FPE_FLTUND_TRAP ,"floating point underflow" }, 365 { FPE_FLTDIV_TRAP ,"floating point divide" }, 366 { FPE_FLTINEX_TRAP ,"inexact floating point result" }, 367 { 0 ,"unknown error" } 368 } ; 369 #define SIGPC(scp) (0) /* Info MIGHT be in scp->sc_jmpbuf.jmp_context.iar */ 370 /* 371 For some reason, scp->sc_jmpbuf does not work on the RS6000, even though 372 it looks like it should from the include definitions. It is probably 373 some strange interaction with the "POSIX_SOURCE" that we require. 374 */ 375 376 void PetscDefaultFPTrap(int sig,int code,struct sigcontext *scp) 377 { 378 int err_ind,j; 379 fp_ctx_t flt_context; 380 381 PetscFunctionBegin; 382 fp_sh_trap_info(scp,&flt_context); 383 384 err_ind = -1; 385 for (j = 0; error_codes[j].code_no; j++) { 386 if (error_codes[j].code_no == flt_context.trap) err_ind = j; 387 } 388 389 if (err_ind >= 0) (*PetscErrorPrintf)("*** %s occurred ***\n",error_codes[err_ind].name); 390 else (*PetscErrorPrintf)("*** floating point error 0x%x occurred ***\n",flt_context.trap); 391 392 (void)PetscError(PETSC_COMM_SELF,0,"User provided function","Unknown file",PETSC_ERR_FP,PETSC_ERROR_REPEAT,"floating point error"); 393 PETSCABORT(MPI_COMM_WORLD,PETSC_ERR_FP); 394 } 395 396 PetscErrorCode PetscSetFPTrap(PetscFPTrap on) 397 { 398 PetscFunctionBegin; 399 if (on == PETSC_FP_TRAP_ON) { 400 signal(SIGFPE,(void (*)(int))PetscDefaultFPTrap); 401 fp_trap(FP_TRAP_SYNC); 402 fp_enable(TRP_INVALID | TRP_DIV_BY_ZERO | TRP_OVERFLOW | TRP_UNDERFLOW); 403 /* fp_enable(mask) for individual traps. Values are: 404 TRP_INVALID 405 TRP_DIV_BY_ZERO 406 TRP_OVERFLOW 407 TRP_UNDERFLOW 408 TRP_INEXACT 409 Can OR then together. 410 fp_enable_all(); for all traps. 411 */ 412 } else { 413 signal(SIGFPE,SIG_DFL); 414 fp_disable(TRP_INVALID | TRP_DIV_BY_ZERO | TRP_OVERFLOW | TRP_UNDERFLOW); 415 fp_trap(FP_TRAP_OFF); 416 } 417 _trapmode = on; 418 PetscFunctionReturn(0); 419 } 420 421 PetscErrorCode PetscDetermineInitialFPTrap(void) 422 { 423 PetscFunctionBegin; 424 PetscCall(PetscInfo(NULL,"Unable to determine initial floating point trapping. Assuming it is off\n")); 425 PetscFunctionReturn(0); 426 } 427 428 /* ------------------------------------------------------------*/ 429 #elif defined(PETSC_HAVE_WINDOWS_COMPILERS) 430 #include <float.h> 431 void PetscDefaultFPTrap(int sig) 432 { 433 PetscFunctionBegin; 434 (*PetscErrorPrintf)("*** floating point error occurred ***\n"); 435 PetscError(PETSC_COMM_SELF,0,"User provided function","Unknown file",PETSC_ERR_FP,PETSC_ERROR_REPEAT,"floating point error"); 436 PETSCABORT(MPI_COMM_WORLD,PETSC_ERR_FP); 437 } 438 439 PetscErrorCode PetscSetFPTrap(PetscFPTrap on) 440 { 441 unsigned int cw; 442 443 PetscFunctionBegin; 444 if (on == PETSC_FP_TRAP_ON) { 445 cw = _EM_INVALID | _EM_ZERODIVIDE | _EM_OVERFLOW | _EM_UNDERFLOW; 446 PetscCheck(SIG_ERR != signal(SIGFPE,PetscDefaultFPTrap),PETSC_COMM_SELF,PETSC_ERR_LIB,"Can't set floating point handler"); 447 } else { 448 cw = 0; 449 PetscCheck(SIG_ERR != signal(SIGFPE,SIG_DFL),PETSC_COMM_SELF,PETSC_ERR_LIB,"Can't clear floating point handler"); 450 } 451 (void)_controlfp(0, cw); 452 _trapmode = on; 453 PetscFunctionReturn(0); 454 } 455 456 PetscErrorCode PetscDetermineInitialFPTrap(void) 457 { 458 PetscFunctionBegin; 459 PetscCall(PetscInfo(NULL,"Unable to determine initial floating point trapping. Assuming it is off\n")); 460 PetscFunctionReturn(0); 461 } 462 463 /* ------------------------------------------------------------*/ 464 #elif defined(PETSC_HAVE_FENV_H) && !defined(__cplusplus) 465 /* 466 C99 style floating point environment. 467 468 Note that C99 merely specifies how to save, restore, and clear the floating 469 point environment as well as defining an enumeration of exception codes. In 470 particular, C99 does not specify how to make floating point exceptions raise 471 a signal. Glibc offers this capability through FE_NOMASK_ENV (or with finer 472 granularity, feenableexcept()), xmmintrin.h offers _MM_SET_EXCEPTION_MASK(). 473 */ 474 #include <fenv.h> 475 typedef struct {int code; const char *name;} FPNode; 476 static const FPNode error_codes[] = { 477 {FE_DIVBYZERO,"divide by zero"}, 478 {FE_INEXACT, "inexact floating point result"}, 479 {FE_INVALID, "invalid floating point arguments (domain error)"}, 480 {FE_OVERFLOW, "floating point overflow"}, 481 {FE_UNDERFLOW,"floating point underflow"}, 482 {0 ,"unknown error"} 483 }; 484 485 void PetscDefaultFPTrap(int sig) 486 { 487 const FPNode *node; 488 int code; 489 PetscBool matched = PETSC_FALSE; 490 491 PetscFunctionBegin; 492 /* Note: While it is possible for the exception state to be preserved by the 493 * kernel, this seems to be rare which makes the following flag testing almost 494 * useless. But on a system where the flags can be preserved, it would provide 495 * more detail. 496 */ 497 code = fetestexcept(FE_ALL_EXCEPT); 498 for (node=&error_codes[0]; node->code; node++) { 499 if (code & node->code) { 500 matched = PETSC_TRUE; 501 (*PetscErrorPrintf)("*** floating point error \"%s\" occurred ***\n",node->name); 502 code &= ~node->code; /* Unset this flag since it has been processed */ 503 } 504 } 505 if (!matched || code) { /* If any remaining flags are set, or we didn't process any flags */ 506 (*PetscErrorPrintf)("*** unknown floating point error occurred ***\n"); 507 (*PetscErrorPrintf)("The specific exception can be determined by running in a debugger. When the\n"); 508 (*PetscErrorPrintf)("debugger traps the signal, the exception can be found with fetestexcept(0x%x)\n",FE_ALL_EXCEPT); 509 (*PetscErrorPrintf)("where the result is a bitwise OR of the following flags:\n"); 510 (*PetscErrorPrintf)("FE_INVALID=0x%x FE_DIVBYZERO=0x%x FE_OVERFLOW=0x%x FE_UNDERFLOW=0x%x FE_INEXACT=0x%x\n",FE_INVALID,FE_DIVBYZERO,FE_OVERFLOW,FE_UNDERFLOW,FE_INEXACT); 511 } 512 513 (*PetscErrorPrintf)("Try option -start_in_debugger\n"); 514 #if PetscDefined(USE_DEBUG) 515 (*PetscErrorPrintf)("likely location of problem given in stack below\n"); 516 (*PetscErrorPrintf)("--------------------- Stack Frames ------------------------------------\n"); 517 PetscStackView(PETSC_STDOUT); 518 #else 519 (*PetscErrorPrintf)("configure using --with-debugging=yes, recompile, link, and run \n"); 520 (*PetscErrorPrintf)("with -start_in_debugger to get more information on the crash.\n"); 521 #endif 522 PetscError(PETSC_COMM_SELF,0,"User provided function","Unknown file",PETSC_ERR_FP,PETSC_ERROR_INITIAL,"trapped floating point error"); 523 PETSCABORT(MPI_COMM_WORLD,PETSC_ERR_FP); 524 } 525 526 PetscErrorCode PetscSetFPTrap(PetscFPTrap on) 527 { 528 PetscFunctionBegin; 529 if (on == PETSC_FP_TRAP_ON) { 530 /* Clear any flags that are currently set so that activating trapping will not immediately call the signal handler. */ 531 PetscCheckFalse(feclearexcept(FE_ALL_EXCEPT),PETSC_COMM_SELF,PETSC_ERR_LIB,"Cannot clear floating point exception flags"); 532 #if defined(FE_NOMASK_ENV) 533 /* Could use fesetenv(FE_NOMASK_ENV), but that causes spurious exceptions (like gettimeofday() -> PetscLogDouble). */ 534 PetscCheck(feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW) != -1,PETSC_COMM_SELF,PETSC_ERR_LIB,"Cannot activate floating point exceptions"); 535 #elif defined PETSC_HAVE_XMMINTRIN_H 536 _MM_SET_EXCEPTION_MASK(_MM_GET_EXCEPTION_MASK() & ~_MM_MASK_DIV_ZERO); 537 _MM_SET_EXCEPTION_MASK(_MM_GET_EXCEPTION_MASK() & ~_MM_MASK_UNDERFLOW); 538 _MM_SET_EXCEPTION_MASK(_MM_GET_EXCEPTION_MASK() & ~_MM_MASK_OVERFLOW); 539 _MM_SET_EXCEPTION_MASK(_MM_GET_EXCEPTION_MASK() & ~_MM_MASK_INVALID); 540 #else 541 /* C99 does not provide a way to modify the environment so there is no portable way to activate trapping. */ 542 #endif 543 PetscCheck(SIG_ERR != signal(SIGFPE,PetscDefaultFPTrap),PETSC_COMM_SELF,PETSC_ERR_LIB,"Can't set floating point handler"); 544 } else { 545 PetscCheckFalse(fesetenv(FE_DFL_ENV),PETSC_COMM_SELF,PETSC_ERR_LIB,"Cannot disable floating point exceptions"); 546 /* can use _MM_SET_EXCEPTION_MASK(_MM_GET_EXCEPTION_MASK() | _MM_MASK_UNDERFLOW); if PETSC_HAVE_XMMINTRIN_H exists */ 547 PetscCheck(SIG_ERR != signal(SIGFPE,SIG_DFL),PETSC_COMM_SELF,PETSC_ERR_LIB,"Can't clear floating point handler"); 548 } 549 _trapmode = on; 550 PetscFunctionReturn(0); 551 } 552 553 PetscErrorCode PetscDetermineInitialFPTrap(void) 554 { 555 #if defined(FE_NOMASK_ENV) || defined PETSC_HAVE_XMMINTRIN_H 556 unsigned int flags; 557 #endif 558 559 PetscFunctionBegin; 560 #if defined(FE_NOMASK_ENV) 561 flags = fegetexcept(); 562 if (flags & FE_DIVBYZERO) { 563 #elif defined PETSC_HAVE_XMMINTRIN_H 564 flags = _MM_GET_EXCEPTION_MASK(); 565 if (!(flags & _MM_MASK_DIV_ZERO)) { 566 #else 567 PetscCall(PetscInfo(NULL,"Floating point trapping unknown, assuming off\n")); 568 PetscFunctionReturn(0); 569 #endif 570 #if defined(FE_NOMASK_ENV) || defined PETSC_HAVE_XMMINTRIN_H 571 _trapmode = PETSC_FP_TRAP_ON; 572 PetscCall(PetscInfo(NULL,"Floating point trapping is on by default %d\n",flags)); 573 } else { 574 _trapmode = PETSC_FP_TRAP_OFF; 575 PetscCall(PetscInfo(NULL,"Floating point trapping is off by default %d\n",flags)); 576 } 577 PetscFunctionReturn(0); 578 #endif 579 } 580 581 /* ------------------------------------------------------------*/ 582 #elif defined(PETSC_HAVE_IEEEFP_H) 583 #include <ieeefp.h> 584 void PetscDefaultFPTrap(int sig) 585 { 586 PetscFunctionBegin; 587 (*PetscErrorPrintf)("*** floating point error occurred ***\n"); 588 PetscError(PETSC_COMM_SELF,0,"User provided function","Unknown file",PETSC_ERR_FP,PETSC_ERROR_REPEAT,"floating point error"); 589 PETSCABORT(MPI_COMM_WORLD,PETSC_ERR_FP); 590 } 591 592 PetscErrorCode PetscSetFPTrap(PetscFPTrap on) 593 { 594 PetscFunctionBegin; 595 if (on == PETSC_FP_TRAP_ON) { 596 #if defined(PETSC_HAVE_FPPRESETSTICKY) 597 fpresetsticky(fpgetsticky()); 598 #elif defined(PETSC_HAVE_FPSETSTICKY) 599 fpsetsticky(fpgetsticky()); 600 #endif 601 fpsetmask(FP_X_INV | FP_X_DZ | FP_X_OFL | FP_X_OFL); 602 PetscCheck(SIG_ERR != signal(SIGFPE,PetscDefaultFPTrap),PETSC_COMM_SELF,PETSC_ERR_LIB,"Can't set floating point handler"); 603 } else { 604 #if defined(PETSC_HAVE_FPPRESETSTICKY) 605 fpresetsticky(fpgetsticky()); 606 #elif defined(PETSC_HAVE_FPSETSTICKY) 607 fpsetsticky(fpgetsticky()); 608 #endif 609 fpsetmask(0); 610 PetscCheck(SIG_ERR != signal(SIGFPE,SIG_DFL),PETSC_COMM_SELF,PETSC_ERR_LIB,"Can't clear floating point handler"); 611 } 612 _trapmode = on; 613 PetscFunctionReturn(0); 614 } 615 616 PetscErrorCode PetscDetermineInitialFPTrap(void) 617 { 618 PetscFunctionBegin; 619 PetscCall(PetscInfo(NULL,"Unable to determine initial floating point trapping. Assuming it is off\n")); 620 PetscFunctionReturn(0); 621 } 622 623 /* -------------------------Default -----------------------------------*/ 624 #else 625 626 void PetscDefaultFPTrap(int sig) 627 { 628 PetscFunctionBegin; 629 (*PetscErrorPrintf)("*** floating point error occurred ***\n"); 630 PetscError(PETSC_COMM_SELF,0,"User provided function","Unknown file",PETSC_ERR_FP,PETSC_ERROR_REPEAT,"floating point error"); 631 PETSCABORT(MPI_COMM_WORLD,PETSC_ERR_FP); 632 } 633 634 PetscErrorCode PetscSetFPTrap(PetscFPTrap on) 635 { 636 PetscFunctionBegin; 637 if (on == PETSC_FP_TRAP_ON) { 638 if (SIG_ERR == signal(SIGFPE,PetscDefaultFPTrap)) (*PetscErrorPrintf)("Can't set floatingpoint handler\n"); 639 } else if (SIG_ERR == signal(SIGFPE,SIG_DFL)) (*PetscErrorPrintf)("Can't clear floatingpoint handler\n"); 640 641 _trapmode = on; 642 PetscFunctionReturn(0); 643 } 644 645 PetscErrorCode PetscDetermineInitialFPTrap(void) 646 { 647 PetscFunctionBegin; 648 PetscCall(PetscInfo(NULL,"Unable to determine initial floating point trapping. Assuming it is off\n")); 649 PetscFunctionReturn(0); 650 } 651 #endif 652