source: trunk/source/global/management/include/G4FPEDetection.hh

Last change on this file was 1340, checked in by garnier, 15 years ago

update ti head

File size: 8.6 KB
Line 
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: G4FPEDetection.hh,v 1.5 2010/10/14 17:02:52 mkelsey Exp $
28// GEANT4 tag $Name: global-V09-03-22 $
29//
30//
31// -*- C++ -*-
32//
33// -----------------------------------------------------------------------
34// This global method should be used on LINUX or MacOSX platforms with gcc
35// compiler for activating NaN detection and FPE signals, and forcing
36// abortion of the application at the time these are detected.
37// Meant to be used for debug purposes, can be activated by compiling the
38// "run" module with the flag G4FPE_DEBUG set in the environment.
39// -----------------------------------------------------------------------
40
41#ifndef G4FPEDetection_h
42#define G4FPEDetection_h 1
43
44#include <iostream>
45#include <stdlib.h> /* abort(), exit() */
46
47#ifdef __linux__
48#ifdef __GNUC__
49 #include <features.h>
50 #include <fenv.h>
51 #include <csignal>
52
53 struct sigaction termaction, oldaction;
54
55 static void TerminationSignalHandler(int sig, siginfo_t* sinfo, void* /* context */)
56 {
57 std::cerr << "ERROR: " << sig;
58 std::string message = "Floating-point exception (FPE).";
59
60 if (sinfo) {
61 switch (sinfo->si_code) {
62#ifdef FPE_NOOP /* BUG: MacOSX uses this instead of INTDIV */
63 case FPE_NOOP:
64#endif
65 case FPE_INTDIV:
66 message = "Integer divide by zero.";
67 break;
68 case FPE_INTOVF:
69 message = "Integer overflow.";
70 break;
71 case FPE_FLTDIV:
72 message = "Floating point divide by zero.";
73 break;
74 case FPE_FLTOVF:
75 message = "Floating point overflow.";
76 break;
77 case FPE_FLTUND:
78 message = "Floating point underflow.";
79 break;
80 case FPE_FLTRES:
81 message = "Floating point inexact result.";
82 break;
83 case FPE_FLTINV:
84 message = "Floating point invalid operation.";
85 break;
86 case FPE_FLTSUB:
87 message = "Subscript out of range.";
88 break;
89 default:
90 message = "Unknown error.";
91 break;
92 }
93 }
94
95 std::cerr << " - " << message << std::endl;
96
97 ::abort();
98 }
99
100 static void InvalidOperationDetection()
101 {
102 std::cout << std::endl
103 << " "
104 << "############################################" << std::endl
105 << " "
106 << "!!! WARNING - FPE detection is activated !!!" << std::endl
107 << " "
108 << "############################################" << std::endl;
109
110 (void) feenableexcept( FE_DIVBYZERO );
111 (void) feenableexcept( FE_INVALID );
112 //(void) feenableexcept( FE_OVERFLOW );
113 //(void) feenableexcept( FE_UNDERFLOW );
114
115 sigdelset(&termaction.sa_mask,SIGFPE);
116 termaction.sa_sigaction=TerminationSignalHandler;
117 termaction.sa_flags=SA_SIGINFO;
118 sigaction(SIGFPE, &termaction, &oldaction);
119 }
120#endif
121#elif __MACH__ /* MacOSX */
122
123 #include <fenv.h>
124 #include <signal.h>
125
126 #define DEFINED_PPC (defined(__ppc__) || defined(__ppc64__))
127 #define DEFINED_INTEL (defined(__i386__) || defined(__x86_64__))
128
129 #if DEFINED_PPC
130
131 #define FE_EXCEPT_SHIFT 22 // shift flags right to get masks
132 #define FM_ALL_EXCEPT FE_ALL_EXCEPT >> FE_EXCEPT_SHIFT
133
134 static inline int feenableexcept (unsigned int excepts)
135 {
136 static fenv_t fenv;
137 unsigned int new_excepts = (excepts & FE_ALL_EXCEPT) >> FE_EXCEPT_SHIFT,
138 old_excepts; // all previous masks
139
140 if ( fegetenv (&fenv) ) { return -1; }
141 old_excepts = (fenv & FM_ALL_EXCEPT) << FE_EXCEPT_SHIFT;
142 fenv = (fenv & ~new_excepts) | new_excepts;
143
144 return ( fesetenv (&fenv) ? -1 : old_excepts );
145 }
146
147 static inline int fedisableexcept (unsigned int excepts)
148 {
149 static fenv_t fenv;
150 unsigned int still_on = ~((excepts & FE_ALL_EXCEPT) >> FE_EXCEPT_SHIFT),
151 old_excepts; // previous masks
152
153 if ( fegetenv (&fenv) ) { return -1; }
154 old_excepts = (fenv & FM_ALL_EXCEPT) << FE_EXCEPT_SHIFT;
155 fenv &= still_on;
156
157 return ( fesetenv (&fenv) ? -1 : old_excepts );
158 }
159
160 #elif DEFINED_INTEL
161
162 static inline int feenableexcept (unsigned int excepts)
163 {
164 static fenv_t fenv;
165 unsigned int new_excepts = excepts & FE_ALL_EXCEPT,
166 old_excepts; // previous masks
167
168 if ( fegetenv (&fenv) ) { return -1; }
169 old_excepts = fenv.__control & FE_ALL_EXCEPT;
170
171 // unmask
172 //
173 fenv.__control &= ~new_excepts;
174 fenv.__mxcsr &= ~(new_excepts << 7);
175
176 return ( fesetenv (&fenv) ? -1 : old_excepts );
177 }
178
179 static inline int fedisableexcept (unsigned int excepts)
180 {
181 static fenv_t fenv;
182 unsigned int new_excepts = excepts & FE_ALL_EXCEPT,
183 old_excepts; // all previous masks
184
185 if ( fegetenv (&fenv) ) { return -1; }
186 old_excepts = fenv.__control & FE_ALL_EXCEPT;
187
188 // mask
189 //
190 fenv.__control |= new_excepts;
191 fenv.__mxcsr |= new_excepts << 7;
192
193 return ( fesetenv (&fenv) ? -1 : old_excepts );
194 }
195
196 #endif /* PPC or INTEL enabling */
197
198 static void TerminationSignalHandler(int sig, siginfo_t* sinfo, void* /* context */)
199 {
200 std::cerr << "ERROR: " << sig;
201 std::string message = "Floating-point exception (FPE).";
202
203 if (sinfo) {
204 switch (sinfo->si_code) {
205#ifdef FPE_NOOP /* BUG: MacOSX uses this instead of INTDIV */
206 case FPE_NOOP:
207#endif
208 case FPE_INTDIV:
209 message = "Integer divide by zero.";
210 break;
211 case FPE_INTOVF:
212 message = "Integer overflow.";
213 break;
214 case FPE_FLTDIV:
215 message = "Floating point divide by zero.";
216 break;
217 case FPE_FLTOVF:
218 message = "Floating point overflow.";
219 break;
220 case FPE_FLTUND:
221 message = "Floating point underflow.";
222 break;
223 case FPE_FLTRES:
224 message = "Floating point inexact result.";
225 break;
226 case FPE_FLTINV:
227 message = "Floating point invalid operation.";
228 break;
229 case FPE_FLTSUB:
230 message = "Subscript out of range.";
231 break;
232 default:
233 message = "Unknown error.";
234 break;
235 }
236 }
237
238 std::cerr << " - " << message << std::endl;
239
240 ::abort();
241 }
242
243 static void InvalidOperationDetection()
244 {
245 struct sigaction termaction, oldaction;
246
247 std::cout << std::endl
248 << " "
249 << "############################################" << std::endl
250 << " "
251 << "!!! WARNING - FPE detection is activated !!!" << std::endl
252 << " "
253 << "############################################" << std::endl;
254
255 feenableexcept ( FE_DIVBYZERO );
256 feenableexcept ( FE_INVALID );
257 // fedisableexcept( FE_OVERFLOW );
258 // fedisableexcept( FE_UNDERFLOW );
259
260 sigdelset(&termaction.sa_mask,SIGFPE);
261 termaction.sa_sigaction=TerminationSignalHandler;
262 termaction.sa_flags=SA_SIGINFO;
263 sigaction(SIGFPE, &termaction, &oldaction);
264 }
265#else /* Not Linux, nor MacOSX ... */
266
267 static void InvalidOperationDetection() {;}
268
269#endif
270
271#endif
Note: See TracBrowser for help on using the repository browser.