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