Geant4 9.6.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4FPEDetection.hh
Go to the documentation of this file.
1//
2// ********************************************************************
3// * License and Disclaimer *
4// * *
5// * The Geant4 software is copyright of the Copyright Holders of *
6// * the Geant4 Collaboration. It is provided under the terms and *
7// * conditions of the Geant4 Software License, included in the file *
8// * LICENSE and available at http://cern.ch/geant4/license . These *
9// * include a list of copyright holders. *
10// * *
11// * Neither the authors of this software system, nor their employing *
12// * institutes,nor the agencies providing financial support for this *
13// * work make any representation or warranty, express or implied, *
14// * regarding this software system or assume any liability for its *
15// * use. Please see the license in the file LICENSE and URL above *
16// * for the full disclaimer and the limitation of liability. *
17// * *
18// * This code implementation is the result of the scientific and *
19// * technical work of the GEANT4 collaboration. *
20// * By using, copying, modifying or distributing the software (or *
21// * any work based on the software) you agree to acknowledge its *
22// * use in resulting scientific publications, and indicate your *
23// * acceptance of all terms of the Geant4 Software license. *
24// ********************************************************************
25//
26//
27// $Id$
28//
29//
30// -*- C++ -*-
31//
32// -----------------------------------------------------------------------
33// This global method should be used on LINUX or MacOSX platforms with gcc
34// compiler for activating NaN detection and FPE signals, and forcing
35// abortion of the application at the time these are detected.
36// Meant to be used for debug purposes, can be activated by compiling the
37// "run" module with the flag G4FPE_DEBUG set in the environment.
38// -----------------------------------------------------------------------
39
40#ifndef G4FPEDetection_h
41#define G4FPEDetection_h 1
42
43#include <iostream>
44#include <stdlib.h> /* abort(), exit() */
45
46#ifdef __linux__
47#ifdef __GNUC__
48 #include <features.h>
49 #include <fenv.h>
50 #include <csignal>
51
52 struct sigaction termaction, oldaction;
53
54 static void TerminationSignalHandler(int sig, siginfo_t* sinfo, void* /* context */)
55 {
56 std::cerr << "ERROR: " << sig;
57 std::string message = "Floating-point exception (FPE).";
58
59 if (sinfo) {
60 switch (sinfo->si_code) {
61#ifdef FPE_NOOP /* BUG: MacOSX uses this instead of INTDIV */
62 case FPE_NOOP:
63#endif
64 case FPE_INTDIV:
65 message = "Integer divide by zero.";
66 break;
67 case FPE_INTOVF:
68 message = "Integer overflow.";
69 break;
70 case FPE_FLTDIV:
71 message = "Floating point divide by zero.";
72 break;
73 case FPE_FLTOVF:
74 message = "Floating point overflow.";
75 break;
76 case FPE_FLTUND:
77 message = "Floating point underflow.";
78 break;
79 case FPE_FLTRES:
80 message = "Floating point inexact result.";
81 break;
82 case FPE_FLTINV:
83 message = "Floating point invalid operation.";
84 break;
85 case FPE_FLTSUB:
86 message = "Subscript out of range.";
87 break;
88 default:
89 message = "Unknown error.";
90 break;
91 }
92 }
93
94 std::cerr << " - " << message << std::endl;
95
96 ::abort();
97 }
98
99 static void InvalidOperationDetection()
100 {
101 std::cout << std::endl
102 << " "
103 << "############################################" << std::endl
104 << " "
105 << "!!! WARNING - FPE detection is activated !!!" << std::endl
106 << " "
107 << "############################################" << std::endl;
108
109 (void) feenableexcept( FE_DIVBYZERO );
110 (void) feenableexcept( FE_INVALID );
111 //(void) feenableexcept( FE_OVERFLOW );
112 //(void) feenableexcept( FE_UNDERFLOW );
113
114 sigdelset(&termaction.sa_mask,SIGFPE);
115 termaction.sa_sigaction=TerminationSignalHandler;
116 termaction.sa_flags=SA_SIGINFO;
117 sigaction(SIGFPE, &termaction, &oldaction);
118 }
119#endif
120#elif __MACH__ /* MacOSX */
121
122 #include <fenv.h>
123 #include <signal.h>
124
125 #define DEFINED_PPC (defined(__ppc__) || defined(__ppc64__))
126 #define DEFINED_INTEL (defined(__i386__) || defined(__x86_64__))
127
128 #if DEFINED_PPC
129
130 #define FE_EXCEPT_SHIFT 22 // shift flags right to get masks
131 #define FM_ALL_EXCEPT FE_ALL_EXCEPT >> FE_EXCEPT_SHIFT
132
133 static inline int feenableexcept (unsigned int excepts)
134 {
135 static fenv_t fenv;
136 unsigned int new_excepts = (excepts & FE_ALL_EXCEPT) >> FE_EXCEPT_SHIFT,
137 old_excepts; // all previous masks
138
139 if ( fegetenv (&fenv) ) { return -1; }
140 old_excepts = (fenv & FM_ALL_EXCEPT) << FE_EXCEPT_SHIFT;
141 fenv = (fenv & ~new_excepts) | new_excepts;
142
143 return ( fesetenv (&fenv) ? -1 : old_excepts );
144 }
145
146 static inline int fedisableexcept (unsigned int excepts)
147 {
148 static fenv_t fenv;
149 unsigned int still_on = ~((excepts & FE_ALL_EXCEPT) >> FE_EXCEPT_SHIFT),
150 old_excepts; // previous masks
151
152 if ( fegetenv (&fenv) ) { return -1; }
153 old_excepts = (fenv & FM_ALL_EXCEPT) << FE_EXCEPT_SHIFT;
154 fenv &= still_on;
155
156 return ( fesetenv (&fenv) ? -1 : old_excepts );
157 }
158
159 #elif DEFINED_INTEL
160
161 static inline int feenableexcept (unsigned int excepts)
162 {
163 static fenv_t fenv;
164 unsigned int new_excepts = excepts & FE_ALL_EXCEPT,
165 old_excepts; // previous masks
166
167 if ( fegetenv (&fenv) ) { return -1; }
168 old_excepts = fenv.__control & FE_ALL_EXCEPT;
169
170 // unmask
171 //
172 fenv.__control &= ~new_excepts;
173 fenv.__mxcsr &= ~(new_excepts << 7);
174
175 return ( fesetenv (&fenv) ? -1 : old_excepts );
176 }
177
178 static inline int fedisableexcept (unsigned int excepts)
179 {
180 static fenv_t fenv;
181 unsigned int new_excepts = excepts & FE_ALL_EXCEPT,
182 old_excepts; // all previous masks
183
184 if ( fegetenv (&fenv) ) { return -1; }
185 old_excepts = fenv.__control & FE_ALL_EXCEPT;
186
187 // mask
188 //
189 fenv.__control |= new_excepts;
190 fenv.__mxcsr |= new_excepts << 7;
191
192 return ( fesetenv (&fenv) ? -1 : old_excepts );
193 }
194
195 #endif /* PPC or INTEL enabling */
196
197 static void TerminationSignalHandler(int sig, siginfo_t* sinfo, void* /* context */)
198 {
199 std::cerr << "ERROR: " << sig;
200 std::string message = "Floating-point exception (FPE).";
201
202 if (sinfo) {
203 switch (sinfo->si_code) {
204#ifdef FPE_NOOP /* BUG: MacOSX uses this instead of INTDIV */
205 case FPE_NOOP:
206#endif
207 case FPE_INTDIV:
208 message = "Integer divide by zero.";
209 break;
210 case FPE_INTOVF:
211 message = "Integer overflow.";
212 break;
213 case FPE_FLTDIV:
214 message = "Floating point divide by zero.";
215 break;
216 case FPE_FLTOVF:
217 message = "Floating point overflow.";
218 break;
219 case FPE_FLTUND:
220 message = "Floating point underflow.";
221 break;
222 case FPE_FLTRES:
223 message = "Floating point inexact result.";
224 break;
225 case FPE_FLTINV:
226 message = "Floating point invalid operation.";
227 break;
228 case FPE_FLTSUB:
229 message = "Subscript out of range.";
230 break;
231 default:
232 message = "Unknown error.";
233 break;
234 }
235 }
236
237 std::cerr << " - " << message << std::endl;
238
239 ::abort();
240 }
241
242 static void InvalidOperationDetection()
243 {
244 struct sigaction termaction, oldaction;
245
246 std::cout << std::endl
247 << " "
248 << "############################################" << std::endl
249 << " "
250 << "!!! WARNING - FPE detection is activated !!!" << std::endl
251 << " "
252 << "############################################" << std::endl;
253
254 feenableexcept ( FE_DIVBYZERO );
255 feenableexcept ( FE_INVALID );
256 // fedisableexcept( FE_OVERFLOW );
257 // fedisableexcept( FE_UNDERFLOW );
258
259 sigdelset(&termaction.sa_mask,SIGFPE);
260 termaction.sa_sigaction=TerminationSignalHandler;
261 termaction.sa_flags=SA_SIGINFO;
262 sigaction(SIGFPE, &termaction, &oldaction);
263 }
264#else /* Not Linux, nor MacOSX ... */
265
266 static void InvalidOperationDetection() {;}
267
268#endif
269
270#endif