File indexing completed on 2025-01-18 09:58:18
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038 #ifndef G4FPEDetection_hh
0039 #define G4FPEDetection_hh 1
0040
0041 #include <iostream>
0042 #include <stdlib.h> /* abort(), exit() */
0043
0044 #ifdef __linux__
0045 # if(defined(__GNUC__) && !defined(__clang__))
0046 # include <csignal>
0047 # include <features.h>
0048 # include <fenv.h>
0049
0050 # include <cxxabi.h>
0051 # include <execinfo.h>
0052
0053 struct sigaction termaction, oldaction;
0054
0055 static void G4StackBackTrace()
0056 {
0057
0058 # define BSIZE 50
0059 void* buffer[BSIZE];
0060 int nptrs = backtrace(buffer, BSIZE);
0061 char** strings = backtrace_symbols(buffer, nptrs);
0062 if(strings == NULL)
0063 {
0064 perror("backtrace_symbols");
0065 return;
0066 }
0067 std::cerr << std::endl << "Call Stack:" << std::endl;
0068 for(int j = 0; j < nptrs; j++)
0069 {
0070 std::cerr << nptrs - j - 1 << ": ";
0071 char* mangled_start = strchr(strings[j], '(') + 1;
0072 if(mangled_start)
0073 *(mangled_start - 1) = '\0';
0074 char* mangled_end = strchr(mangled_start, '+');
0075 if(mangled_end)
0076 *mangled_end = '\0';
0077 int status = 0;
0078 char* realname = 0;
0079 if(mangled_end && strlen(mangled_start))
0080 realname = abi::__cxa_demangle(mangled_start, 0, 0, &status);
0081 if(realname)
0082 {
0083 std::cerr << strings[j] << " : " << realname << std::endl;
0084 free(realname);
0085 }
0086 else
0087 {
0088 std::cerr << strings[j] << std::endl;
0089 }
0090 }
0091 free(strings);
0092
0093
0094
0095 }
0096
0097 static void TerminationSignalHandler(int sig, siginfo_t* sinfo,
0098 void* )
0099 {
0100 std::cerr << "ERROR: " << sig;
0101 std::string message = "Floating-point exception (FPE).";
0102
0103 if(sinfo)
0104 {
0105 switch(sinfo->si_code)
0106 {
0107 # ifdef FPE_NOOP
0108 case FPE_NOOP:
0109 # endif
0110 case FPE_INTDIV:
0111 message = "Integer divide by zero.";
0112 break;
0113 case FPE_INTOVF:
0114 message = "Integer overflow.";
0115 break;
0116 case FPE_FLTDIV:
0117 message = "Floating point divide by zero.";
0118 break;
0119 case FPE_FLTOVF:
0120 message = "Floating point overflow.";
0121 break;
0122 case FPE_FLTUND:
0123 message = "Floating point underflow.";
0124 break;
0125 case FPE_FLTRES:
0126 message = "Floating point inexact result.";
0127 break;
0128 case FPE_FLTINV:
0129 message = "Floating point invalid operation.";
0130 break;
0131 case FPE_FLTSUB:
0132 message = "Subscript out of range.";
0133 break;
0134 default:
0135 message = "Unknown error.";
0136 break;
0137 }
0138 }
0139 std::cerr << " - " << message << std::endl;
0140 G4StackBackTrace();
0141 ::abort();
0142 }
0143
0144 static void InvalidOperationDetection()
0145 {
0146 std::cout << std::endl
0147 << " "
0148 << "############################################" << std::endl
0149 << " "
0150 << "!!! WARNING - FPE detection is activated !!!" << std::endl
0151 << " "
0152 << "############################################" << std::endl;
0153
0154 (void) feenableexcept(FE_DIVBYZERO);
0155 (void) feenableexcept(FE_INVALID);
0156
0157
0158
0159 sigfillset(&termaction.sa_mask);
0160 sigdelset(&termaction.sa_mask, SIGFPE);
0161 termaction.sa_sigaction = TerminationSignalHandler;
0162 termaction.sa_flags = SA_SIGINFO;
0163 sigaction(SIGFPE, &termaction, &oldaction);
0164 }
0165
0166 # else
0167
0168 static void InvalidOperationDetection() { ; }
0169
0170 # endif
0171
0172 #elif defined(__MACH__)
0173
0174 # include <fenv.h>
0175 # include <signal.h>
0176
0177
0178
0179
0180 # if(defined(__ppc__) || defined(__ppc64__))
0181
0182 # define FE_EXCEPT_SHIFT 22
0183 # define FM_ALL_EXCEPT FE_ALL_EXCEPT >> FE_EXCEPT_SHIFT
0184
0185 static inline int feenableexcept(unsigned int excepts)
0186 {
0187 static fenv_t fenv;
0188 unsigned int new_excepts = (excepts & FE_ALL_EXCEPT) >> FE_EXCEPT_SHIFT,
0189 old_excepts;
0190
0191 if(fegetenv(&fenv))
0192 {
0193 return -1;
0194 }
0195 old_excepts = (fenv & FM_ALL_EXCEPT) << FE_EXCEPT_SHIFT;
0196 fenv = (fenv & ~new_excepts) | new_excepts;
0197
0198 return (fesetenv(&fenv) ? -1 : old_excepts);
0199 }
0200
0201 static inline int fedisableexcept(unsigned int excepts)
0202 {
0203 static fenv_t fenv;
0204 unsigned int still_on = ~((excepts & FE_ALL_EXCEPT) >> FE_EXCEPT_SHIFT),
0205 old_excepts;
0206
0207 if(fegetenv(&fenv))
0208 {
0209 return -1;
0210 }
0211 old_excepts = (fenv & FM_ALL_EXCEPT) << FE_EXCEPT_SHIFT;
0212 fenv &= still_on;
0213
0214 return (fesetenv(&fenv) ? -1 : old_excepts);
0215 }
0216
0217 # elif(defined(__i386__) || defined(__x86_64__))
0218
0219 static inline int feenableexcept(unsigned int excepts)
0220 {
0221 static fenv_t fenv;
0222 unsigned int new_excepts = excepts & FE_ALL_EXCEPT,
0223 old_excepts;
0224
0225 if(fegetenv(&fenv))
0226 {
0227 return -1;
0228 }
0229 old_excepts = fenv.__control & FE_ALL_EXCEPT;
0230
0231
0232
0233 fenv.__control &= ~new_excepts;
0234 fenv.__mxcsr &= ~(new_excepts << 7);
0235
0236 return (fesetenv(&fenv) ? -1 : old_excepts);
0237 }
0238
0239 static inline int fedisableexcept(unsigned int excepts)
0240 {
0241 static fenv_t fenv;
0242 unsigned int new_excepts = excepts & FE_ALL_EXCEPT,
0243 old_excepts;
0244
0245 if(fegetenv(&fenv))
0246 {
0247 return -1;
0248 }
0249 old_excepts = fenv.__control & FE_ALL_EXCEPT;
0250
0251
0252
0253 fenv.__control |= new_excepts;
0254 fenv.__mxcsr |= new_excepts << 7;
0255
0256 return (fesetenv(&fenv) ? -1 : old_excepts);
0257 }
0258
0259 # elif(defined(__arm) || defined(__arm64) || defined(__aarch64__))
0260
0261 # define FE_EXCEPT_SHIFT 22
0262 # define FM_ALL_EXCEPT FE_ALL_EXCEPT >> FE_EXCEPT_SHIFT
0263
0264 static inline int feenableexcept(unsigned int excepts)
0265 {
0266 static fenv_t fenv;
0267 unsigned int new_excepts = (excepts & FE_ALL_EXCEPT) >> FE_EXCEPT_SHIFT,
0268 old_excepts;
0269
0270 if(fegetenv(&fenv))
0271 {
0272 return -1;
0273 }
0274 old_excepts = (fenv.__fpcr & FM_ALL_EXCEPT) << FE_EXCEPT_SHIFT;
0275 fenv.__fpcr = (fenv.__fpcr & ~new_excepts) | new_excepts;
0276
0277 return (fesetenv(&fenv) ? -1 : old_excepts);
0278 }
0279
0280 static inline int fedisableexcept(unsigned int excepts)
0281 {
0282 static fenv_t fenv;
0283 unsigned int still_on = ~((excepts & FE_ALL_EXCEPT) >> FE_EXCEPT_SHIFT),
0284 old_excepts;
0285
0286 if(fegetenv(&fenv))
0287 {
0288 return -1;
0289 }
0290 old_excepts = (fenv.__fpcr & FM_ALL_EXCEPT) << FE_EXCEPT_SHIFT;
0291 fenv.__fpcr = fenv.__fpcr | still_on;
0292
0293 return (fesetenv(&fenv) ? -1 : old_excepts);
0294 }
0295
0296 # endif
0297
0298 static void TerminationSignalHandler(int sig, siginfo_t* sinfo,
0299 void* )
0300 {
0301 std::cerr << "ERROR: " << sig;
0302 std::string message = "Floating-point exception (FPE).";
0303
0304 if(sinfo)
0305 {
0306 switch(sinfo->si_code)
0307 {
0308 # ifdef FPE_NOOP
0309 case FPE_NOOP:
0310 # endif
0311 case FPE_INTDIV:
0312 message = "Integer divide by zero.";
0313 break;
0314 case FPE_INTOVF:
0315 message = "Integer overflow.";
0316 break;
0317 case FPE_FLTDIV:
0318 message = "Floating point divide by zero.";
0319 break;
0320 case FPE_FLTOVF:
0321 message = "Floating point overflow.";
0322 break;
0323 case FPE_FLTUND:
0324 message = "Floating point underflow.";
0325 break;
0326 case FPE_FLTRES:
0327 message = "Floating point inexact result.";
0328 break;
0329 case FPE_FLTINV:
0330 message = "Floating point invalid operation.";
0331 break;
0332 case FPE_FLTSUB:
0333 message = "Subscript out of range.";
0334 break;
0335 default:
0336 message = "Unknown error.";
0337 break;
0338 }
0339 }
0340
0341 std::cerr << " - " << message << std::endl;
0342
0343 ::abort();
0344 }
0345
0346 static void InvalidOperationDetection()
0347 {
0348 struct sigaction termaction, oldaction;
0349
0350 std::cout << std::endl
0351 << " "
0352 << "############################################" << std::endl
0353 << " "
0354 << "!!! WARNING - FPE detection is activated !!!" << std::endl
0355 << " "
0356 << "############################################" << std::endl;
0357
0358 feenableexcept(FE_DIVBYZERO);
0359 feenableexcept(FE_INVALID);
0360
0361
0362
0363 sigfillset(&termaction.sa_mask);
0364 sigdelset(&termaction.sa_mask, SIGFPE);
0365 termaction.sa_sigaction = TerminationSignalHandler;
0366 termaction.sa_flags = SA_SIGINFO;
0367 sigaction(SIGFPE, &termaction, &oldaction);
0368 }
0369
0370 #else
0371
0372 static void InvalidOperationDetection() { ; }
0373
0374 #endif
0375
0376 #endif