Geant4 9.6.0
Toolkit for the simulation of the passage of particles through matter
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
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