Actual source code: fp.c
1: /*
2: * IEEE error handler for all machines. Since each machine has
3: * enough slight differences we have completely separate codes for each one.
4: *
5: */
6: #include petsc.h
7: #include petscsys.h
8: #include <signal.h>
9: #if defined(PETSC_HAVE_STDLIB_H)
10: #include <stdlib.h>
11: #endif
12: #include "petscfix.h"
15: /*--------------------------------------- ---------------------------------------------------*/
16: #if defined(PETSC_HAVE_SUN4_STYLE_FPTRAP)
17: #include <floatingpoint.h>
20: PetscErrorCode ieee_flags(char*,char*,char*,char**);
21: PetscErrorCode ieee_handler(char *,char *,sigfpe_handler_type(int,int,struct sigcontext*,char *));
24: struct { int code_no; char *name; } error_codes[] = {
25: { FPE_INTDIV_TRAP ,"integer divide" },
26: { FPE_FLTOPERR_TRAP ,"IEEE operand error" },
27: { FPE_FLTOVF_TRAP ,"floating point overflow" },
28: { FPE_FLTUND_TRAP ,"floating point underflow" },
29: { FPE_FLTDIV_TRAP ,"floating pointing divide" },
30: { FPE_FLTINEX_TRAP ,"inexact floating point result" },
31: { 0 ,"unknown error" }
32: } ;
33: #define SIGPC(scp) (scp->sc_pc)
37: sigfpe_handler_type PetscDefaultFPTrap(int sig,int code,struct sigcontext *scp,char *addr)
38: {
40: int err_ind = -1,j;
43: for (j = 0 ; error_codes[j].code_no ; j++) {
44: if (error_codes[j].code_no == code) err_ind = j;
45: }
47: if (err_ind >= 0) {
48: (*PetscErrorPrintf)("*** %s occurred at pc=%X ***\n",error_codes[err_ind].name,SIGPC(scp));
49: } else {
50: (*PetscErrorPrintf)("*** floating point error 0x%x occurred at pc=%X ***\n",code,SIGPC(scp));
51: }
52: PetscError(PETSC_ERR_FP,"User provided function","Unknown file","Unknown directory",PETSC_ERR_FP,1,"floating point error");
53: MPI_Abort(PETSC_COMM_WORLD,0);
54: return(0);
55: }
59: /*@C
60: PetscSetFPTrap - Enables traps/exceptions on common floating point errors.
61: This option may not work on certain machines.
63: Not Collective
65: Input Parameters:
66: . flag - PETSC_FP_TRAP_ON, PETSC_FP_TRAP_OFF.
68: Options Database Keys:
69: . -fp_trap - Activates floating point trapping
71: Level: advanced
73: Description:
74: On systems that support it, this routine causes floating point
75: overflow, divide-by-zero, and invalid-operand (e.g., a NaN) to
76: cause a message to be printed and the program to exit.
78: Caution:
79: On certain machines, in particular the IBM rs6000, floating point
80: trapping is VERY slow!
82: Concepts: floating point exceptions^trapping
83: Concepts: divide by zero
85: @*/
86: PetscErrorCode PetscSetFPTrap(PetscFPTrap flag)
87: {
88: char *out;
91: /* Clear accumulated exceptions. Used to suppress meaningless messages from f77 programs */
92: (void) ieee_flags("clear","exception","all",&out);
93: if (flag == PETSC_FP_TRAP_ON) {
94: if (ieee_handler("set","common",PetscDefaultFPTrap)) {
95: /*
96: To trap more fp exceptions, including undrflow, change the above line to
97: if (ieee_handler("set","all",PetscDefaultFPTrap)) {
98: */
99: (*PetscErrorPrintf)("Can't set floatingpoint handler\n");
100: }
101: } else {
102: if (ieee_handler("clear","common",PetscDefaultFPTrap)) {
103: (*PetscErrorPrintf)("Can't clear floatingpoint handler\n");
104: }
105: }
106: return(0);
107: }
109: /* -------------------------------------------------------------------------------------------*/
110: #elif defined(PETSC_HAVE_SOLARIS_STYLE_FPTRAP)
111: #include <sunmath.h>
112: #include <floatingpoint.h>
113: #include <siginfo.h>
114: #include <ucontext.h>
116: struct { int code_no; char *name; } error_codes[] = {
117: { FPE_FLTINV,"invalid floating point operand"},
118: { FPE_FLTRES,"inexact floating point result"},
119: { FPE_FLTDIV,"division-by-zero"},
120: { FPE_FLTUND,"floating point underflow"},
121: { FPE_FLTOVF,"floating point overflow"},
122: { 0, "unknown error"}
123: };
124: #define SIGPC(scp) (scp->si_addr)
128: void PetscDefaultFPTrap(int sig,siginfo_t *scp,ucontext_t *uap)
129: {
130: int err_ind,j,code = scp->si_code;
134: err_ind = -1 ;
135: for (j = 0 ; error_codes[j].code_no ; j++) {
136: if (error_codes[j].code_no == code) err_ind = j;
137: }
139: if (err_ind >= 0) {
140: (*PetscErrorPrintf)("*** %s occurred at pc=%X ***\n",error_codes[err_ind].name,SIGPC(scp));
141: } else {
142: (*PetscErrorPrintf)("*** floating point error 0x%x occurred at pc=%X ***\n",code,SIGPC(scp));
143: }
144: PetscError(0,"User provided function","Unknown file","Unknown directory",PETSC_ERR_FP,1,"floating point error");
145: MPI_Abort(PETSC_COMM_WORLD,0);
146: }
150: PetscErrorCode PetscSetFPTrap(PetscFPTrap flag)
151: {
152: char *out;
155: /* Clear accumulated exceptions. Used to suppress meaningless messages from f77 programs */
156: (void) ieee_flags("clear","exception","all",&out);
157: if (flag == PETSC_FP_TRAP_ON) {
158: if (ieee_handler("set","common",(sigfpe_handler_type)PetscDefaultFPTrap)) {
159: (*PetscErrorPrintf)("Can't set floating point handler\n");
160: }
161: } else {
162: if (ieee_handler("clear","common",(sigfpe_handler_type)PetscDefaultFPTrap)) {
163: (*PetscErrorPrintf)("Can't clear floatingpoint handler\n");
164: }
165: }
166: return(0);
167: }
169: /* ------------------------------------------------------------------------------------------*/
171: #elif defined (PETSC_HAVE_IRIX_STYLE_FPTRAP)
172: #include <sigfpe.h>
173: struct { int code_no; char *name; } error_codes[] = {
174: { _INVALID ,"IEEE operand error" },
175: { _OVERFL ,"floating point overflow" },
176: { _UNDERFL ,"floating point underflow" },
177: { _DIVZERO ,"floating point divide" },
178: { 0 ,"unknown error" }
179: } ;
182: void PetscDefaultFPTrap(unsigned exception[],int val[])
183: {
184: int err_ind,j,code;
187: code = exception[0];
188: err_ind = -1 ;
189: for (j = 0 ; error_codes[j].code_no ; j++){
190: if (error_codes[j].code_no == code) err_ind = j;
191: }
192: if (err_ind >= 0){
193: (*PetscErrorPrintf)("*** %s occurred ***\n",error_codes[err_ind].name);
194: } else{
195: (*PetscErrorPrintf)("*** floating point error 0x%x occurred ***\n",code);
196: }
197: PetscError(0,"User provided function","Unknown file","Unknown directory",PETSC_ERR_FP,1,"floating point error");
198: MPI_Abort(PETSC_COMM_WORLD,0);
199: }
203: PetscErrorCode PetscSetFPTrap(PetscFPTrap flag)
204: {
206: if (flag == PETSC_FP_TRAP_ON) {
207: handle_sigfpes(_ON,_EN_OVERFL|_EN_DIVZERO|_EN_INVALID,PetscDefaultFPTrap,_ABORT_ON_ERROR,0);
208: } else {
209: handle_sigfpes(_OFF,_EN_OVERFL|_EN_DIVZERO|_EN_INVALID,0,_ABORT_ON_ERROR,0);
210: }
211: return(0);
212: }
213: /*----------------------------------------------- --------------------------------------------*/
214: /* In "fast" mode, floating point traps are imprecise and ignored.
215: This is the reason for the fptrap(FP_TRAP_SYNC) call */
216: #elif defined(PETSC_HAVE_RS6000_STYLE_FPTRAP)
217: struct sigcontext;
218: #include <fpxcp.h>
219: #include <fptrap.h>
220: #include <stdlib.h>
221: #define FPE_FLTOPERR_TRAP (fptrap_t)(0x20000000)
222: #define FPE_FLTOVF_TRAP (fptrap_t)(0x10000000)
223: #define FPE_FLTUND_TRAP (fptrap_t)(0x08000000)
224: #define FPE_FLTDIV_TRAP (fptrap_t)(0x04000000)
225: #define FPE_FLTINEX_TRAP (fptrap_t)(0x02000000)
227: struct { int code_no; char *name; } error_codes[] = {
228: {FPE_FLTOPERR_TRAP ,"IEEE operand error" },
229: { FPE_FLTOVF_TRAP ,"floating point overflow" },
230: { FPE_FLTUND_TRAP ,"floating point underflow" },
231: { FPE_FLTDIV_TRAP ,"floating point divide" },
232: { FPE_FLTINEX_TRAP ,"inexact floating point result" },
233: { 0 ,"unknown error" }
234: } ;
235: #define SIGPC(scp) (0) /* Info MIGHT be in scp->sc_jmpbuf.jmp_context.iar */
236: /*
237: For some reason, scp->sc_jmpbuf does not work on the RS6000, even though
238: it looks like it should from the include definitions. It is probably
239: some strange interaction with the "POSIX_SOURCE" that we require.
240: */
244: void PetscDefaultFPTrap(int sig,int code,struct sigcontext *scp)
245: {
247: int err_ind,j;
248: fp_ctx_t flt_context;
251: fp_sh_trap_info(scp,&flt_context);
252:
253: err_ind = -1 ;
254: for (j = 0 ; error_codes[j].code_no ; j++) {
255: if (error_codes[j].code_no == flt_context.trap) err_ind = j;
256: }
258: if (err_ind >= 0){
259: (*PetscErrorPrintf)("*** %s occurred ***\n",error_codes[err_ind].name);
260: } else{
261: (*PetscErrorPrintf)("*** floating point error 0x%x occurred ***\n",flt_context.trap);
262: }
263: PetscError(0,"User provided function","Unknown file","Unknown directory",PETSC_ERR_FP,1,"floating point error");
264: MPI_Abort(PETSC_COMM_WORLD,0);
265: }
269: PetscErrorCode PetscSetFPTrap(PetscFPTrap on)
270: {
271: int flag;
274: if (on == PETSC_FP_TRAP_ON) {
275: signal(SIGFPE,(void (*)(int))PetscDefaultFPTrap);
276: fp_trap(FP_TRAP_SYNC);
277: fp_enable(TRP_INVALID | TRP_DIV_BY_ZERO | TRP_OVERFLOW);
278: /* fp_enable(mask) for individual traps. Values are:
279: TRP_INVALID
280: TRP_DIV_BY_ZERO
281: TRP_OVERFLOW
282: TRP_UNDERFLOW
283: TRP_INEXACT
284: Can OR then together.
285: fp_enable_all(); for all traps.
286: */
287: } else {
288: signal(SIGFPE,SIG_DFL);
289: fp_disable(TRP_INVALID | TRP_DIV_BY_ZERO | TRP_OVERFLOW);
290: fp_trap(FP_TRAP_OFF);
291: }
292: return(0);
293: }
295: /* -------------------------Default -----------------------------------*/
296: #else
297: struct { int code_no; const char *name; } error_codes[] = {
298: { 0 ,"unknown error" }
299: } ;
303: void PetscDefaultFPTrap(int sig)
304: {
306: (*PetscErrorPrintf)("*** floating point error occurred ***\n");
307: PetscError(0,"User provided function","Unknown file","Unknown directory",PETSC_ERR_FP,1,"floating point error");
308: MPI_Abort(PETSC_COMM_WORLD,0);
309: }
313: PetscErrorCode PetscSetFPTrap(PetscFPTrap on)
314: {
316: if (on == PETSC_FP_TRAP_ON) {
317: if (SIG_ERR == signal(SIGFPE,PetscDefaultFPTrap)) {
318: (*PetscErrorPrintf)("Can't set floatingpoint handler\n");
319: }
320: } else {
321: if (SIG_ERR == signal(SIGFPE,SIG_DFL)) {
322: (*PetscErrorPrintf)("Can't clear floatingpoint handler\n");
323: }
324: }
325: return(0);
326: }
327: #endif