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

Last change on this file since 1340 was 1340, checked in by garnier, 14 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.