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 PetscErrorCode ierr; 379 int err_ind,j; 380 fp_ctx_t flt_context; 381 382 PetscFunctionBegin; 383 fp_sh_trap_info(scp,&flt_context); 384 385 err_ind = -1; 386 for (j = 0; error_codes[j].code_no; j++) { 387 if (error_codes[j].code_no == flt_context.trap) err_ind = j; 388 } 389 390 if (err_ind >= 0) (*PetscErrorPrintf)("*** %s occurred ***\n",error_codes[err_ind].name); 391 else (*PetscErrorPrintf)("*** floating point error 0x%x occurred ***\n",flt_context.trap); 392 393 ierr = PetscError(PETSC_COMM_SELF,0,"User provided function","Unknown file",PETSC_ERR_FP,PETSC_ERROR_REPEAT,"floating point error"); 394 PETSCABORT(MPI_COMM_WORLD,PETSC_ERR_FP); 395 } 396 397 PetscErrorCode PetscSetFPTrap(PetscFPTrap on) 398 { 399 PetscFunctionBegin; 400 if (on == PETSC_FP_TRAP_ON) { 401 signal(SIGFPE,(void (*)(int))PetscDefaultFPTrap); 402 fp_trap(FP_TRAP_SYNC); 403 fp_enable(TRP_INVALID | TRP_DIV_BY_ZERO | TRP_OVERFLOW | TRP_UNDERFLOW); 404 /* fp_enable(mask) for individual traps. Values are: 405 TRP_INVALID 406 TRP_DIV_BY_ZERO 407 TRP_OVERFLOW 408 TRP_UNDERFLOW 409 TRP_INEXACT 410 Can OR then together. 411 fp_enable_all(); for all traps. 412 */ 413 } else { 414 signal(SIGFPE,SIG_DFL); 415 fp_disable(TRP_INVALID | TRP_DIV_BY_ZERO | TRP_OVERFLOW | TRP_UNDERFLOW); 416 fp_trap(FP_TRAP_OFF); 417 } 418 _trapmode = on; 419 PetscFunctionReturn(0); 420 } 421 422 PetscErrorCode PetscDetermineInitialFPTrap(void) 423 { 424 PetscFunctionBegin; 425 PetscCall(PetscInfo(NULL,"Unable to determine initial floating point trapping. Assuming it is off\n")); 426 PetscFunctionReturn(0); 427 } 428 429 /* ------------------------------------------------------------*/ 430 #elif defined(PETSC_HAVE_WINDOWS_COMPILERS) 431 #include <float.h> 432 void PetscDefaultFPTrap(int sig) 433 { 434 PetscFunctionBegin; 435 (*PetscErrorPrintf)("*** floating point error occurred ***\n"); 436 PetscError(PETSC_COMM_SELF,0,"User provided function","Unknown file",PETSC_ERR_FP,PETSC_ERROR_REPEAT,"floating point error"); 437 PETSCABORT(MPI_COMM_WORLD,PETSC_ERR_FP); 438 } 439 440 PetscErrorCode PetscSetFPTrap(PetscFPTrap on) 441 { 442 unsigned int cw; 443 444 PetscFunctionBegin; 445 if (on == PETSC_FP_TRAP_ON) { 446 cw = _EM_INVALID | _EM_ZERODIVIDE | _EM_OVERFLOW | _EM_UNDERFLOW; 447 PetscCheck(SIG_ERR != signal(SIGFPE,PetscDefaultFPTrap),PETSC_COMM_SELF,PETSC_ERR_LIB,"Can't set floating point handler"); 448 } else { 449 cw = 0; 450 PetscCheck(SIG_ERR != signal(SIGFPE,SIG_DFL),PETSC_COMM_SELF,PETSC_ERR_LIB,"Can't clear floating point handler"); 451 } 452 (void)_controlfp(0, cw); 453 _trapmode = on; 454 PetscFunctionReturn(0); 455 } 456 457 PetscErrorCode PetscDetermineInitialFPTrap(void) 458 { 459 PetscFunctionBegin; 460 PetscCall(PetscInfo(NULL,"Unable to determine initial floating point trapping. Assuming it is off\n")); 461 PetscFunctionReturn(0); 462 } 463 464 /* ------------------------------------------------------------*/ 465 #elif defined(PETSC_HAVE_FENV_H) && !defined(__cplusplus) 466 /* 467 C99 style floating point environment. 468 469 Note that C99 merely specifies how to save, restore, and clear the floating 470 point environment as well as defining an enumeration of exception codes. In 471 particular, C99 does not specify how to make floating point exceptions raise 472 a signal. Glibc offers this capability through FE_NOMASK_ENV (or with finer 473 granularity, feenableexcept()), xmmintrin.h offers _MM_SET_EXCEPTION_MASK(). 474 */ 475 #include <fenv.h> 476 typedef struct {int code; const char *name;} FPNode; 477 static const FPNode error_codes[] = { 478 {FE_DIVBYZERO,"divide by zero"}, 479 {FE_INEXACT, "inexact floating point result"}, 480 {FE_INVALID, "invalid floating point arguments (domain error)"}, 481 {FE_OVERFLOW, "floating point overflow"}, 482 {FE_UNDERFLOW,"floating point underflow"}, 483 {0 ,"unknown error"} 484 }; 485 486 void PetscDefaultFPTrap(int sig) 487 { 488 const FPNode *node; 489 int code; 490 PetscBool matched = PETSC_FALSE; 491 492 PetscFunctionBegin; 493 /* Note: While it is possible for the exception state to be preserved by the 494 * kernel, this seems to be rare which makes the following flag testing almost 495 * useless. But on a system where the flags can be preserved, it would provide 496 * more detail. 497 */ 498 code = fetestexcept(FE_ALL_EXCEPT); 499 for (node=&error_codes[0]; node->code; node++) { 500 if (code & node->code) { 501 matched = PETSC_TRUE; 502 (*PetscErrorPrintf)("*** floating point error \"%s\" occurred ***\n",node->name); 503 code &= ~node->code; /* Unset this flag since it has been processed */ 504 } 505 } 506 if (!matched || code) { /* If any remaining flags are set, or we didn't process any flags */ 507 (*PetscErrorPrintf)("*** unknown floating point error occurred ***\n"); 508 (*PetscErrorPrintf)("The specific exception can be determined by running in a debugger. When the\n"); 509 (*PetscErrorPrintf)("debugger traps the signal, the exception can be found with fetestexcept(0x%x)\n",FE_ALL_EXCEPT); 510 (*PetscErrorPrintf)("where the result is a bitwise OR of the following flags:\n"); 511 (*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); 512 } 513 514 (*PetscErrorPrintf)("Try option -start_in_debugger\n"); 515 #if PetscDefined(USE_DEBUG) 516 (*PetscErrorPrintf)("likely location of problem given in stack below\n"); 517 (*PetscErrorPrintf)("--------------------- Stack Frames ------------------------------------\n"); 518 PetscStackView(PETSC_STDOUT); 519 #else 520 (*PetscErrorPrintf)("configure using --with-debugging=yes, recompile, link, and run \n"); 521 (*PetscErrorPrintf)("with -start_in_debugger to get more information on the crash.\n"); 522 #endif 523 PetscError(PETSC_COMM_SELF,0,"User provided function","Unknown file",PETSC_ERR_FP,PETSC_ERROR_INITIAL,"trapped floating point error"); 524 PETSCABORT(MPI_COMM_WORLD,PETSC_ERR_FP); 525 } 526 527 PetscErrorCode PetscSetFPTrap(PetscFPTrap on) 528 { 529 PetscFunctionBegin; 530 if (on == PETSC_FP_TRAP_ON) { 531 /* Clear any flags that are currently set so that activating trapping will not immediately call the signal handler. */ 532 PetscCheckFalse(feclearexcept(FE_ALL_EXCEPT),PETSC_COMM_SELF,PETSC_ERR_LIB,"Cannot clear floating point exception flags"); 533 #if defined(FE_NOMASK_ENV) 534 /* Could use fesetenv(FE_NOMASK_ENV), but that causes spurious exceptions (like gettimeofday() -> PetscLogDouble). */ 535 PetscCheck(feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW) != -1,PETSC_COMM_SELF,PETSC_ERR_LIB,"Cannot activate floating point exceptions"); 536 #elif defined PETSC_HAVE_XMMINTRIN_H 537 _MM_SET_EXCEPTION_MASK(_MM_GET_EXCEPTION_MASK() & ~_MM_MASK_DIV_ZERO); 538 _MM_SET_EXCEPTION_MASK(_MM_GET_EXCEPTION_MASK() & ~_MM_MASK_UNDERFLOW); 539 _MM_SET_EXCEPTION_MASK(_MM_GET_EXCEPTION_MASK() & ~_MM_MASK_OVERFLOW); 540 _MM_SET_EXCEPTION_MASK(_MM_GET_EXCEPTION_MASK() & ~_MM_MASK_INVALID); 541 #else 542 /* C99 does not provide a way to modify the environment so there is no portable way to activate trapping. */ 543 #endif 544 PetscCheck(SIG_ERR != signal(SIGFPE,PetscDefaultFPTrap),PETSC_COMM_SELF,PETSC_ERR_LIB,"Can't set floating point handler"); 545 } else { 546 PetscCheckFalse(fesetenv(FE_DFL_ENV),PETSC_COMM_SELF,PETSC_ERR_LIB,"Cannot disable floating point exceptions"); 547 /* can use _MM_SET_EXCEPTION_MASK(_MM_GET_EXCEPTION_MASK() | _MM_MASK_UNDERFLOW); if PETSC_HAVE_XMMINTRIN_H exists */ 548 PetscCheck(SIG_ERR != signal(SIGFPE,SIG_DFL),PETSC_COMM_SELF,PETSC_ERR_LIB,"Can't clear floating point handler"); 549 } 550 _trapmode = on; 551 PetscFunctionReturn(0); 552 } 553 554 PetscErrorCode PetscDetermineInitialFPTrap(void) 555 { 556 #if defined(FE_NOMASK_ENV) || defined PETSC_HAVE_XMMINTRIN_H 557 unsigned int flags; 558 #endif 559 560 PetscFunctionBegin; 561 #if defined(FE_NOMASK_ENV) 562 flags = fegetexcept(); 563 if (flags & FE_DIVBYZERO) { 564 #elif defined PETSC_HAVE_XMMINTRIN_H 565 flags = _MM_GET_EXCEPTION_MASK(); 566 if (!(flags & _MM_MASK_DIV_ZERO)) { 567 #else 568 PetscCall(PetscInfo(NULL,"Floating point trapping unknown, assuming off\n")); 569 PetscFunctionReturn(0); 570 #endif 571 #if defined(FE_NOMASK_ENV) || defined PETSC_HAVE_XMMINTRIN_H 572 _trapmode = PETSC_FP_TRAP_ON; 573 PetscCall(PetscInfo(NULL,"Floating point trapping is on by default %d\n",flags)); 574 } else { 575 _trapmode = PETSC_FP_TRAP_OFF; 576 PetscCall(PetscInfo(NULL,"Floating point trapping is off by default %d\n",flags)); 577 } 578 PetscFunctionReturn(0); 579 #endif 580 } 581 582 /* ------------------------------------------------------------*/ 583 #elif defined(PETSC_HAVE_IEEEFP_H) 584 #include <ieeefp.h> 585 void PetscDefaultFPTrap(int sig) 586 { 587 PetscFunctionBegin; 588 (*PetscErrorPrintf)("*** floating point error occurred ***\n"); 589 PetscError(PETSC_COMM_SELF,0,"User provided function","Unknown file",PETSC_ERR_FP,PETSC_ERROR_REPEAT,"floating point error"); 590 PETSCABORT(MPI_COMM_WORLD,PETSC_ERR_FP); 591 } 592 593 PetscErrorCode PetscSetFPTrap(PetscFPTrap on) 594 { 595 PetscFunctionBegin; 596 if (on == PETSC_FP_TRAP_ON) { 597 #if defined(PETSC_HAVE_FPPRESETSTICKY) 598 fpresetsticky(fpgetsticky()); 599 #elif defined(PETSC_HAVE_FPSETSTICKY) 600 fpsetsticky(fpgetsticky()); 601 #endif 602 fpsetmask(FP_X_INV | FP_X_DZ | FP_X_OFL | FP_X_OFL); 603 PetscCheck(SIG_ERR != signal(SIGFPE,PetscDefaultFPTrap),PETSC_COMM_SELF,PETSC_ERR_LIB,"Can't set floating point handler"); 604 } else { 605 #if defined(PETSC_HAVE_FPPRESETSTICKY) 606 fpresetsticky(fpgetsticky()); 607 #elif defined(PETSC_HAVE_FPSETSTICKY) 608 fpsetsticky(fpgetsticky()); 609 #endif 610 fpsetmask(0); 611 PetscCheck(SIG_ERR != signal(SIGFPE,SIG_DFL),PETSC_COMM_SELF,PETSC_ERR_LIB,"Can't clear floating point handler"); 612 } 613 _trapmode = on; 614 PetscFunctionReturn(0); 615 } 616 617 PetscErrorCode PetscDetermineInitialFPTrap(void) 618 { 619 PetscFunctionBegin; 620 PetscCall(PetscInfo(NULL,"Unable to determine initial floating point trapping. Assuming it is off\n")); 621 PetscFunctionReturn(0); 622 } 623 624 /* -------------------------Default -----------------------------------*/ 625 #else 626 627 void PetscDefaultFPTrap(int sig) 628 { 629 PetscFunctionBegin; 630 (*PetscErrorPrintf)("*** floating point error occurred ***\n"); 631 PetscError(PETSC_COMM_SELF,0,"User provided function","Unknown file",PETSC_ERR_FP,PETSC_ERROR_REPEAT,"floating point error"); 632 PETSCABORT(MPI_COMM_WORLD,PETSC_ERR_FP); 633 } 634 635 PetscErrorCode PetscSetFPTrap(PetscFPTrap on) 636 { 637 PetscFunctionBegin; 638 if (on == PETSC_FP_TRAP_ON) { 639 if (SIG_ERR == signal(SIGFPE,PetscDefaultFPTrap)) (*PetscErrorPrintf)("Can't set floatingpoint handler\n"); 640 } else if (SIG_ERR == signal(SIGFPE,SIG_DFL)) (*PetscErrorPrintf)("Can't clear floatingpoint handler\n"); 641 642 _trapmode = on; 643 PetscFunctionReturn(0); 644 } 645 646 PetscErrorCode PetscDetermineInitialFPTrap(void) 647 { 648 PetscFunctionBegin; 649 PetscCall(PetscInfo(NULL,"Unable to determine initial floating point trapping. Assuming it is off\n")); 650 PetscFunctionReturn(0); 651 } 652 #endif 653