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 189 .seealso: PetscFPTrapPush(), PetscFPTrapPop(), PetscDetermineInitialFPTrap() 190 @*/ 191 PetscErrorCode PetscDetermineInitialFPTrap(void) 192 { 193 PetscErrorCode ierr; 194 195 PetscFunctionBegin; 196 ierr = PetscInfo(NULL,"Unable to determine initial floating point trapping. Assuming it is off\n");CHKERRQ(ierr); 197 PetscFunctionReturn(0); 198 } 199 200 /* -------------------------------------------------------------------------------------------*/ 201 #elif defined(PETSC_HAVE_SOLARIS_STYLE_FPTRAP) 202 #include <sunmath.h> 203 #include <floatingpoint.h> 204 #include <siginfo.h> 205 #include <ucontext.h> 206 207 static struct { int code_no; char *name; } error_codes[] = { 208 { FPE_FLTINV,"invalid floating point operand"}, 209 { FPE_FLTRES,"inexact floating point result"}, 210 { FPE_FLTDIV,"division-by-zero"}, 211 { FPE_FLTUND,"floating point underflow"}, 212 { FPE_FLTOVF,"floating point overflow"}, 213 { 0, "unknown error"} 214 }; 215 #define SIGPC(scp) (scp->si_addr) 216 217 void PetscDefaultFPTrap(int sig,siginfo_t *scp,ucontext_t *uap) 218 { 219 int err_ind,j,code = scp->si_code; 220 PetscErrorCode ierr; 221 222 PetscFunctionBegin; 223 err_ind = -1; 224 for (j = 0; error_codes[j].code_no; j++) { 225 if (error_codes[j].code_no == code) err_ind = j; 226 } 227 228 if (err_ind >= 0) (*PetscErrorPrintf)("*** %s occurred at pc=%X ***\n",error_codes[err_ind].name,SIGPC(scp)); 229 else (*PetscErrorPrintf)("*** floating point error 0x%x occurred at pc=%X ***\n",code,SIGPC(scp)); 230 231 ierr = PetscError(PETSC_COMM_SELF,0,"User provided function","Unknown file",PETSC_ERR_FP,PETSC_ERROR_REPEAT,"floating point error"); 232 PETSCABORT(MPI_COMM_WORLD,PETSC_ERR_FP); 233 } 234 235 PetscErrorCode PetscSetFPTrap(PetscFPTrap flag) 236 { 237 char *out; 238 239 PetscFunctionBegin; 240 /* Clear accumulated exceptions. Used to suppress meaningless messages from f77 programs */ 241 (void) ieee_flags("clear","exception","all",&out); 242 if (flag == PETSC_FP_TRAP_ON) { 243 if (ieee_handler("set","common",(sigfpe_handler_type)PetscDefaultFPTrap)) (*PetscErrorPrintf)("Can't set floating point handler\n"); 244 } else { 245 if (ieee_handler("clear","common",(sigfpe_handler_type)PetscDefaultFPTrap)) (*PetscErrorPrintf)("Can't clear floatingpoint handler\n"); 246 } 247 _trapmode = flag; 248 PetscFunctionReturn(0); 249 } 250 251 PetscErrorCode PetscDetermineInitialFPTrap(void) 252 { 253 PetscErrorCode ierr; 254 255 PetscFunctionBegin; 256 ierr = PetscInfo(NULL,"Unable to determine initial floating point trapping. Assuming it is off\n");CHKERRQ(ierr); 257 PetscFunctionReturn(0); 258 } 259 260 /* ------------------------------------------------------------------------------------------*/ 261 #elif defined(PETSC_HAVE_IRIX_STYLE_FPTRAP) 262 #include <sigfpe.h> 263 static struct { int code_no; char *name; } error_codes[] = { 264 { _INVALID ,"IEEE operand error" }, 265 { _OVERFL ,"floating point overflow" }, 266 { _UNDERFL ,"floating point underflow" }, 267 { _DIVZERO ,"floating point divide" }, 268 { 0 ,"unknown error" } 269 } ; 270 void PetscDefaultFPTrap(unsigned exception[],int val[]) 271 { 272 int err_ind,j,code; 273 274 PetscFunctionBegin; 275 code = exception[0]; 276 err_ind = -1; 277 for (j = 0; error_codes[j].code_no; j++) { 278 if (error_codes[j].code_no == code) err_ind = j; 279 } 280 if (err_ind >= 0) (*PetscErrorPrintf)("*** %s occurred ***\n",error_codes[err_ind].name); 281 else (*PetscErrorPrintf)("*** floating point error 0x%x occurred ***\n",code); 282 283 PetscError(PETSC_COMM_SELF,0,"User provided function","Unknown file",PETSC_ERR_FP,PETSC_ERROR_REPEAT,"floating point error"); 284 PETSCABORT(MPI_COMM_WORLD,PETSC_ERR_FP); 285 } 286 287 PetscErrorCode PetscSetFPTrap(PetscFPTrap flag) 288 { 289 PetscFunctionBegin; 290 if (flag == PETSC_FP_TRAP_ON) handle_sigfpes(_ON,,_EN_UNDERFL|_EN_OVERFL|_EN_DIVZERO|_EN_INVALID,PetscDefaultFPTrap,_ABORT_ON_ERROR,0); 291 else handle_sigfpes(_OFF,_EN_UNDERFL|_EN_OVERFL|_EN_DIVZERO|_EN_INVALID,0,_ABORT_ON_ERROR,0); 292 _trapmode = flag; 293 PetscFunctionReturn(0); 294 } 295 296 PetscErrorCode PetscDetermineInitialFPTrap(void) 297 { 298 PetscErrorCode ierr; 299 300 PetscFunctionBegin; 301 ierr = PetscInfo(NULL,"Unable to determine initial floating point trapping. Assuming it is off\n");CHKERRQ(ierr); 302 PetscFunctionReturn(0); 303 } 304 305 /* -------------------------------------------------------------------------------------------*/ 306 #elif defined(PETSC_HAVE_SOLARIS_STYLE_FPTRAP) 307 #include <sunmath.h> 308 #include <floatingpoint.h> 309 #include <siginfo.h> 310 #include <ucontext.h> 311 312 static struct { int code_no; char *name; } error_codes[] = { 313 { FPE_FLTINV,"invalid floating point operand"}, 314 { FPE_FLTRES,"inexact floating point result"}, 315 { FPE_FLTDIV,"division-by-zero"}, 316 { FPE_FLTUND,"floating point underflow"}, 317 { FPE_FLTOVF,"floating point overflow"}, 318 { 0, "unknown error"} 319 }; 320 #define SIGPC(scp) (scp->si_addr) 321 322 void PetscDefaultFPTrap(int sig,siginfo_t *scp,ucontext_t *uap) 323 { 324 int err_ind,j,code = scp->si_code; 325 PetscErrorCode ierr; 326 327 PetscFunctionBegin; 328 err_ind = -1; 329 for (j = 0; error_codes[j].code_no; j++) { 330 if (error_codes[j].code_no == code) err_ind = j; 331 } 332 333 if (err_ind >= 0) (*PetscErrorPrintf)("*** %s occurred at pc=%X ***\n",error_codes[err_ind].name,SIGPC(scp)); 334 else (*PetscErrorPrintf)("*** floating point error 0x%x occurred at pc=%X ***\n",code,SIGPC(scp)); 335 336 ierr = PetscError(PETSC_COMM_SELF,0,"User provided function","Unknown file",PETSC_ERR_FP,PETSC_ERROR_REPEAT,"floating point error"); 337 PETSCABORT(MPI_COMM_WORLD,PETSC_ERR_FP); 338 } 339 340 PetscErrorCode PetscSetFPTrap(PetscFPTrap flag) 341 { 342 char *out; 343 344 PetscFunctionBegin; 345 /* Clear accumulated exceptions. Used to suppress meaningless messages from f77 programs */ 346 (void) ieee_flags("clear","exception","all",&out); 347 if (flag == PETSC_FP_TRAP_ON) { 348 if (ieee_handler("set","common",(sigfpe_handler_type)PetscDefaultFPTrap)) (*PetscErrorPrintf)("Can't set floating point handler\n"); 349 } else { 350 if (ieee_handler("clear","common",(sigfpe_handler_type)PetscDefaultFPTrap)) (*PetscErrorPrintf)("Can't clear floatingpoint handler\n"); 351 } 352 _trapmode = flag; 353 PetscFunctionReturn(0); 354 } 355 356 PetscErrorCode PetscDetermineInitialFPTrap(void) 357 { 358 PetscErrorCode ierr; 359 360 PetscFunctionBegin; 361 ierr = PetscInfo(NULL,"Unable to determine initial floating point trapping. Assuming it is off\n");CHKERRQ(ierr); 362 PetscFunctionReturn(0); 363 } 364 365 /*----------------------------------------------- --------------------------------------------*/ 366 #elif defined(PETSC_HAVE_RS6000_STYLE_FPTRAP) 367 /* In "fast" mode, floating point traps are imprecise and ignored. 368 This is the reason for the fptrap(FP_TRAP_SYNC) call */ 369 struct sigcontext; 370 #include <fpxcp.h> 371 #include <fptrap.h> 372 #define FPE_FLTOPERR_TRAP (fptrap_t)(0x20000000) 373 #define FPE_FLTOVF_TRAP (fptrap_t)(0x10000000) 374 #define FPE_FLTUND_TRAP (fptrap_t)(0x08000000) 375 #define FPE_FLTDIV_TRAP (fptrap_t)(0x04000000) 376 #define FPE_FLTINEX_TRAP (fptrap_t)(0x02000000) 377 378 static struct { int code_no; char *name; } error_codes[] = { 379 {FPE_FLTOPERR_TRAP ,"IEEE operand error" }, 380 { FPE_FLTOVF_TRAP ,"floating point overflow" }, 381 { FPE_FLTUND_TRAP ,"floating point underflow" }, 382 { FPE_FLTDIV_TRAP ,"floating point divide" }, 383 { FPE_FLTINEX_TRAP ,"inexact floating point result" }, 384 { 0 ,"unknown error" } 385 } ; 386 #define SIGPC(scp) (0) /* Info MIGHT be in scp->sc_jmpbuf.jmp_context.iar */ 387 /* 388 For some reason, scp->sc_jmpbuf does not work on the RS6000, even though 389 it looks like it should from the include definitions. It is probably 390 some strange interaction with the "POSIX_SOURCE" that we require. 391 */ 392 393 void PetscDefaultFPTrap(int sig,int code,struct sigcontext *scp) 394 { 395 PetscErrorCode ierr; 396 int err_ind,j; 397 fp_ctx_t flt_context; 398 399 PetscFunctionBegin; 400 fp_sh_trap_info(scp,&flt_context); 401 402 err_ind = -1; 403 for (j = 0; error_codes[j].code_no; j++) { 404 if (error_codes[j].code_no == flt_context.trap) err_ind = j; 405 } 406 407 if (err_ind >= 0) (*PetscErrorPrintf)("*** %s occurred ***\n",error_codes[err_ind].name); 408 else (*PetscErrorPrintf)("*** floating point error 0x%x occurred ***\n",flt_context.trap); 409 410 ierr = PetscError(PETSC_COMM_SELF,0,"User provided function","Unknown file",PETSC_ERR_FP,PETSC_ERROR_REPEAT,"floating point error"); 411 PETSCABORT(MPI_COMM_WORLD,PETSC_ERR_FP); 412 } 413 414 PetscErrorCode PetscSetFPTrap(PetscFPTrap on) 415 { 416 PetscFunctionBegin; 417 if (on == PETSC_FP_TRAP_ON) { 418 signal(SIGFPE,(void (*)(int))PetscDefaultFPTrap); 419 fp_trap(FP_TRAP_SYNC); 420 fp_enable(TRP_INVALID | TRP_DIV_BY_ZERO | TRP_OVERFLOW | TRP_UNDERFLOW); 421 /* fp_enable(mask) for individual traps. Values are: 422 TRP_INVALID 423 TRP_DIV_BY_ZERO 424 TRP_OVERFLOW 425 TRP_UNDERFLOW 426 TRP_INEXACT 427 Can OR then together. 428 fp_enable_all(); for all traps. 429 */ 430 } else { 431 signal(SIGFPE,SIG_DFL); 432 fp_disable(TRP_INVALID | TRP_DIV_BY_ZERO | TRP_OVERFLOW | TRP_UNDERFLOW); 433 fp_trap(FP_TRAP_OFF); 434 } 435 _trapmode = on; 436 PetscFunctionReturn(0); 437 } 438 439 PetscErrorCode PetscDetermineInitialFPTrap(void) 440 { 441 PetscErrorCode ierr; 442 443 PetscFunctionBegin; 444 ierr = PetscInfo(NULL,"Unable to determine initial floating point trapping. Assuming it is off\n");CHKERRQ(ierr); 445 PetscFunctionReturn(0); 446 } 447 448 /* ------------------------------------------------------------*/ 449 #elif defined(PETSC_HAVE_WINDOWS_COMPILERS) 450 #include <float.h> 451 void PetscDefaultFPTrap(int sig) 452 { 453 PetscFunctionBegin; 454 (*PetscErrorPrintf)("*** floating point error occurred ***\n"); 455 PetscError(PETSC_COMM_SELF,0,"User provided function","Unknown file",PETSC_ERR_FP,PETSC_ERROR_REPEAT,"floating point error"); 456 PETSCABORT(MPI_COMM_WORLD,PETSC_ERR_FP); 457 } 458 459 PetscErrorCode PetscSetFPTrap(PetscFPTrap on) 460 { 461 unsigned int cw; 462 463 PetscFunctionBegin; 464 if (on == PETSC_FP_TRAP_ON) { 465 cw = _EM_INVALID | _EM_ZERODIVIDE | _EM_OVERFLOW | _EM_UNDERFLOW; 466 if (SIG_ERR == signal(SIGFPE,PetscDefaultFPTrap)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Can't set floating point handler\n"); 467 } else { 468 cw = 0; 469 if (SIG_ERR == signal(SIGFPE,SIG_DFL)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Can't clear floating point handler\n"); 470 } 471 (void)_controlfp(0, cw); 472 _trapmode = on; 473 PetscFunctionReturn(0); 474 } 475 476 PetscErrorCode PetscDetermineInitialFPTrap(void) 477 { 478 PetscErrorCode ierr; 479 480 PetscFunctionBegin; 481 ierr = PetscInfo(NULL,"Unable to determine initial floating point trapping. Assuming it is off\n");CHKERRQ(ierr); 482 PetscFunctionReturn(0); 483 } 484 485 /* ------------------------------------------------------------*/ 486 #elif defined(PETSC_HAVE_FENV_H) && !defined(__cplusplus) 487 /* 488 C99 style floating point environment. 489 490 Note that C99 merely specifies how to save, restore, and clear the floating 491 point environment as well as defining an enumeration of exception codes. In 492 particular, C99 does not specify how to make floating point exceptions raise 493 a signal. Glibc offers this capability through FE_NOMASK_ENV (or with finer 494 granularity, feenableexcept()), xmmintrin.h offers _MM_SET_EXCEPTION_MASK(). 495 */ 496 #include <fenv.h> 497 typedef struct {int code; const char *name;} FPNode; 498 static const FPNode error_codes[] = { 499 {FE_DIVBYZERO,"divide by zero"}, 500 {FE_INEXACT, "inexact floating point result"}, 501 {FE_INVALID, "invalid floating point arguments (domain error)"}, 502 {FE_OVERFLOW, "floating point overflow"}, 503 {FE_UNDERFLOW,"floating point underflow"}, 504 {0 ,"unknown error"} 505 }; 506 507 void PetscDefaultFPTrap(int sig) 508 { 509 const FPNode *node; 510 int code; 511 PetscBool matched = PETSC_FALSE; 512 513 PetscFunctionBegin; 514 /* Note: While it is possible for the exception state to be preserved by the 515 * kernel, this seems to be rare which makes the following flag testing almost 516 * useless. But on a system where the flags can be preserved, it would provide 517 * more detail. 518 */ 519 code = fetestexcept(FE_ALL_EXCEPT); 520 for (node=&error_codes[0]; node->code; node++) { 521 if (code & node->code) { 522 matched = PETSC_TRUE; 523 (*PetscErrorPrintf)("*** floating point error \"%s\" occurred ***\n",node->name); 524 code &= ~node->code; /* Unset this flag since it has been processed */ 525 } 526 } 527 if (!matched || code) { /* If any remaining flags are set, or we didn't process any flags */ 528 (*PetscErrorPrintf)("*** unknown floating point error occurred ***\n"); 529 (*PetscErrorPrintf)("The specific exception can be determined by running in a debugger. When the\n"); 530 (*PetscErrorPrintf)("debugger traps the signal, the exception can be found with fetestexcept(0x%x)\n",FE_ALL_EXCEPT); 531 (*PetscErrorPrintf)("where the result is a bitwise OR of the following flags:\n"); 532 (*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); 533 } 534 535 (*PetscErrorPrintf)("Try option -start_in_debugger\n"); 536 if (PetscDefined(USE_DEBUG)) { 537 if (!PetscStackActive()) (*PetscErrorPrintf)(" or try option -log_stack\n"); 538 else { 539 (*PetscErrorPrintf)("likely location of problem given in stack below\n"); 540 (*PetscErrorPrintf)("--------------------- Stack Frames ------------------------------------\n"); 541 PetscStackView(PETSC_STDOUT); 542 } 543 } else { 544 (*PetscErrorPrintf)("configure using --with-debugging=yes, recompile, link, and run \n"); 545 (*PetscErrorPrintf)("with -start_in_debugger to get more information on the crash.\n"); 546 } 547 PetscError(PETSC_COMM_SELF,0,"User provided function","Unknown file",PETSC_ERR_FP,PETSC_ERROR_INITIAL,"trapped floating point error"); 548 PETSCABORT(MPI_COMM_WORLD,PETSC_ERR_FP); 549 } 550 551 PetscErrorCode PetscSetFPTrap(PetscFPTrap on) 552 { 553 PetscFunctionBegin; 554 if (on == PETSC_FP_TRAP_ON) { 555 /* Clear any flags that are currently set so that activating trapping will not immediately call the signal handler. */ 556 if (feclearexcept(FE_ALL_EXCEPT)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Cannot clear floating point exception flags\n"); 557 #if defined(FE_NOMASK_ENV) 558 /* Could use fesetenv(FE_NOMASK_ENV), but that causes spurious exceptions (like gettimeofday() -> PetscLogDouble). */ 559 if (feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW) == -1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Cannot activate floating point exceptions\n"); 560 #elif defined PETSC_HAVE_XMMINTRIN_H 561 _MM_SET_EXCEPTION_MASK(_MM_GET_EXCEPTION_MASK() & ~_MM_MASK_DIV_ZERO); 562 _MM_SET_EXCEPTION_MASK(_MM_GET_EXCEPTION_MASK() & ~_MM_MASK_UNDERFLOW); 563 _MM_SET_EXCEPTION_MASK(_MM_GET_EXCEPTION_MASK() & ~_MM_MASK_OVERFLOW); 564 _MM_SET_EXCEPTION_MASK(_MM_GET_EXCEPTION_MASK() & ~_MM_MASK_INVALID); 565 #else 566 /* C99 does not provide a way to modify the environment so there is no portable way to activate trapping. */ 567 #endif 568 if (SIG_ERR == signal(SIGFPE,PetscDefaultFPTrap)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Can't set floating point handler\n"); 569 } else { 570 if (fesetenv(FE_DFL_ENV)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Cannot disable floating point exceptions"); 571 /* can use _MM_SET_EXCEPTION_MASK(_MM_GET_EXCEPTION_MASK() | _MM_MASK_UNDERFLOW); if PETSC_HAVE_XMMINTRIN_H exists */ 572 if (SIG_ERR == signal(SIGFPE,SIG_DFL)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Can't clear floating point handler\n"); 573 } 574 _trapmode = on; 575 PetscFunctionReturn(0); 576 } 577 578 PetscErrorCode PetscDetermineInitialFPTrap(void) 579 { 580 #if defined(FE_NOMASK_ENV) || defined PETSC_HAVE_XMMINTRIN_H 581 unsigned int flags; 582 #endif 583 PetscErrorCode ierr; 584 585 PetscFunctionBegin; 586 #if defined(FE_NOMASK_ENV) 587 flags = fegetexcept(); 588 if (flags & FE_DIVBYZERO) { 589 #elif defined PETSC_HAVE_XMMINTRIN_H 590 flags = _MM_GET_EXCEPTION_MASK(); 591 if (!(flags & _MM_MASK_DIV_ZERO)) { 592 #else 593 ierr = PetscInfo(NULL,"Floating point trapping unknown, assuming off\n");CHKERRQ(ierr); 594 PetscFunctionReturn(0); 595 #endif 596 #if defined(FE_NOMASK_ENV) || defined PETSC_HAVE_XMMINTRIN_H 597 _trapmode = PETSC_FP_TRAP_ON; 598 ierr = PetscInfo1(NULL,"Floating point trapping is on by default %d\n",flags);CHKERRQ(ierr); 599 } else { 600 _trapmode = PETSC_FP_TRAP_OFF; 601 ierr = PetscInfo1(NULL,"Floating point trapping is off by default %d\n",flags);CHKERRQ(ierr); 602 } 603 PetscFunctionReturn(0); 604 #endif 605 } 606 607 /* ------------------------------------------------------------*/ 608 #elif defined(PETSC_HAVE_IEEEFP_H) 609 #include <ieeefp.h> 610 void PetscDefaultFPTrap(int sig) 611 { 612 PetscFunctionBegin; 613 (*PetscErrorPrintf)("*** floating point error occurred ***\n"); 614 PetscError(PETSC_COMM_SELF,0,"User provided function","Unknown file",PETSC_ERR_FP,PETSC_ERROR_REPEAT,"floating point error"); 615 PETSCABORT(MPI_COMM_WORLD,PETSC_ERR_FP); 616 } 617 618 PetscErrorCode PetscSetFPTrap(PetscFPTrap on) 619 { 620 PetscFunctionBegin; 621 if (on == PETSC_FP_TRAP_ON) { 622 #if defined(PETSC_HAVE_FPPRESETSTICKY) 623 fpresetsticky(fpgetsticky()); 624 #elif defined(PETSC_HAVE_FPSETSTICKY) 625 fpsetsticky(fpgetsticky()); 626 #endif 627 fpsetmask(FP_X_INV | FP_X_DZ | FP_X_OFL | FP_X_OFL); 628 if (SIG_ERR == signal(SIGFPE,PetscDefaultFPTrap)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Can't set floating point handler\n"); 629 } else { 630 #if defined(PETSC_HAVE_FPPRESETSTICKY) 631 fpresetsticky(fpgetsticky()); 632 #elif defined(PETSC_HAVE_FPSETSTICKY) 633 fpsetsticky(fpgetsticky()); 634 #endif 635 fpsetmask(0); 636 if (SIG_ERR == signal(SIGFPE,SIG_DFL)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Can't clear floating point handler\n"); 637 } 638 _trapmode = on; 639 PetscFunctionReturn(0); 640 } 641 642 PetscErrorCode PetscDetermineInitialFPTrap(void) 643 { 644 PetscErrorCode ierr; 645 646 PetscFunctionBegin; 647 ierr = PetscInfo(NULL,"Unable to determine initial floating point trapping. Assuming it is off\n");CHKERRQ(ierr); 648 PetscFunctionReturn(0); 649 } 650 651 /* -------------------------Default -----------------------------------*/ 652 #else 653 654 void PetscDefaultFPTrap(int sig) 655 { 656 PetscFunctionBegin; 657 (*PetscErrorPrintf)("*** floating point error occurred ***\n"); 658 PetscError(PETSC_COMM_SELF,0,"User provided function","Unknown file",PETSC_ERR_FP,PETSC_ERROR_REPEAT,"floating point error"); 659 PETSCABORT(MPI_COMM_WORLD,PETSC_ERR_FP); 660 } 661 662 PetscErrorCode PetscSetFPTrap(PetscFPTrap on) 663 { 664 PetscFunctionBegin; 665 if (on == PETSC_FP_TRAP_ON) { 666 if (SIG_ERR == signal(SIGFPE,PetscDefaultFPTrap)) (*PetscErrorPrintf)("Can't set floatingpoint handler\n"); 667 } else if (SIG_ERR == signal(SIGFPE,SIG_DFL)) (*PetscErrorPrintf)("Can't clear floatingpoint handler\n"); 668 669 _trapmode = on; 670 PetscFunctionReturn(0); 671 } 672 673 PetscErrorCode PetscDetermineInitialFPTrap(void) 674 { 675 PetscErrorCode ierr; 676 677 PetscFunctionBegin; 678 ierr = PetscInfo(NULL,"Unable to determine initial floating point trapping. Assuming it is off\n");CHKERRQ(ierr); 679 PetscFunctionReturn(0); 680 } 681 #endif 682 683 684 685