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