CMS 3D CMS Logo

EnableFloatingPointExceptions.cc

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 //
00003 // Package:     Services
00004 // Class  :     EnableFloatingPointExceptions
00005 // 
00006 // Implementation:
00007 //     <Notes on implementation>
00008 //
00009 // Original Author:  E. Sexton-Kennedy
00010 //         Created:  Tue Apr 11 13:43:16 CDT 2006
00011 //
00012 // $Id: EnableFloatingPointExceptions.cc,v 1.15 2007/11/08 20:24:44 paterno Exp $
00013 //
00014 
00015 // system include files
00016 
00017 #ifdef __linux__
00018 #ifdef __i386__
00019 #include <fpu_control.h>
00020 #endif
00021 #endif
00022 
00023 // user include files
00024 #include "FWCore/Services/src/EnableFloatingPointExceptions.h"
00025 #include "DataFormats/Provenance/interface/ModuleDescription.h"
00026 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00027 //#include "FWCore/Utilities/interface/Algorithms.h"
00028 
00029 using namespace edm::service;
00030 //
00031 // constants, enums and typedefs
00032 //
00033 
00034 //
00035 // constructors and destructor
00036 //
00037 EnableFloatingPointExceptions::EnableFloatingPointExceptions(const ParameterSet& iPS, ActivityRegistry&iRegistry):
00038 enableDivByZeroEx_(false),
00039 enableInvalidEx_(false),
00040 enableOverFlowEx_(false),
00041 enableUnderFlowEx_(false),
00042 setPrecisionDouble_(true),
00043 reportSettings_(false)
00044 {
00045   iRegistry.watchPostEndJob(this,&EnableFloatingPointExceptions::postEndJob);
00046   iRegistry.watchPreModule(this, &EnableFloatingPointExceptions::preModule);
00047   iRegistry.watchPostModule(this, &EnableFloatingPointExceptions::postModule);
00048 
00049   reportSettings_     = iPS.getUntrackedParameter<bool>("reportSettings",false);
00050   setPrecisionDouble_ = iPS.getUntrackedParameter<bool>("setPrecisionDouble",true);
00051 
00052 // Get the state of the fpu and save it as the "OSdefault" state. The language here
00053 // is a bit odd.  We use "OSdefault" to label the fpu state we inherit from the OS on
00054 // job startup.  By contrast, "default" is the label we use for the fpu state when either
00055 // we or the user has specified a state for modules not appearing in the module list.
00056 // Generally, "OSdefault" and "default" are the same but are not required to be so.
00057 
00058   fegetenv( &fpuState_ );
00059   OSdefault_ = fpuState_;
00060   stateStack_.push(OSdefault_);
00061   if( reportSettings_ )  {
00062     edm::LogVerbatim("FPE_Enable") << "\nSettings for OSdefault";
00063     echoState();
00064   }
00065 
00066 // Then go handle the specific cases as described in the cfg file
00067 
00068   PSet    empty_PSet;
00069   VString empty_VString;
00070 
00071   VString moduleNames = iPS.getUntrackedParameter<VString>("moduleNames",empty_VString);
00072 
00073 // If the module name list is missing or empty, set default values for all parameters
00074 
00075   if( moduleNames.empty() ) {
00076     enableDivByZeroEx_  = false;
00077     enableInvalidEx_    = false;
00078     enableOverFlowEx_   = false;
00079     enableUnderFlowEx_  = false;
00080     setPrecisionDouble_ = true;
00081 
00082     controlFpe();
00083     if( reportSettings_ ) {
00084       edm::LogVerbatim("FPE_Enable") << "\nSettings for default";
00085       echoState();
00086     }
00087     fegetenv( &fpuState_ );
00088     stateMap_["default"] =  fpuState_;
00089   } else {
00090 
00091 // Otherwise, scan the module name list and set per-module values.  Be careful to treat
00092 // any user-specified default first.  If there is one, use it to override our default.
00093 // Then remove it from the list so we don't see it again while handling everything else.
00094 
00095     //VString::iterator pos = find_in_all(moduleNames, "default");
00096     VString::iterator pos = find(moduleNames.begin(),moduleNames.end(), "default");
00097     if( pos != moduleNames.end() ) {
00098       PSet secondary = iPS.getUntrackedParameter<PSet>(*pos, empty_PSet);
00099       enableDivByZeroEx_  = secondary.getUntrackedParameter<bool>("enableDivByZeroEx", false);
00100       enableInvalidEx_    = secondary.getUntrackedParameter<bool>("enableInvalidEx",   false);
00101       enableOverFlowEx_   = secondary.getUntrackedParameter<bool>("enableOverFlowEx",  false);
00102       enableUnderFlowEx_  = secondary.getUntrackedParameter<bool>("enableUnderFlowEx", false);
00103       controlFpe();
00104       if( reportSettings_ ) {
00105         edm::LogVerbatim("FPE_Enable") << "\nSettings for unnamed module";
00106         echoState();
00107       }
00108       fegetenv( &fpuState_ );
00109       stateMap_["default"] =  fpuState_;
00110       moduleNames.erase(pos);
00111     }        
00112 
00113 // Then handle the rest.
00114 
00115     for( VString::const_iterator it(moduleNames.begin()), itEnd=moduleNames.end(); it != itEnd; ++it) {
00116       PSet secondary = iPS.getUntrackedParameter<PSet>(*it, empty_PSet);
00117       enableDivByZeroEx_  = secondary.getUntrackedParameter<bool>("enableDivByZeroEx", false);
00118       enableInvalidEx_    = secondary.getUntrackedParameter<bool>("enableInvalidEx",   false);
00119       enableOverFlowEx_   = secondary.getUntrackedParameter<bool>("enableOverFlowEx",  false);
00120       enableUnderFlowEx_  = secondary.getUntrackedParameter<bool>("enableUnderFlowEx", false);
00121       controlFpe();
00122       if( reportSettings_ ) {
00123         edm::LogVerbatim("FPE_Enable") << "\nSettings for module " << *it;
00124         echoState();
00125       }
00126       fegetenv( &fpuState_ );
00127       stateMap_[*it] =  fpuState_;
00128     }
00129   }
00130 
00131 // And finally, put the state back to the way we found it originally
00132 
00133     fesetenv( &OSdefault_ );
00134 }
00135 
00136 // EnableFloatingPointExceptions::EnableFloatingPointExceptions(const EnableFloatingPointExceptions& rhs)
00137 // {
00138 //    // do actual copying here;
00139 // }
00140 
00141 //EnableFloatingPointExceptions::~EnableFloatingPointExceptions()
00142 //{
00143 //}
00144 
00145 //
00146 // assignment operators
00147 //
00148 // const EnableFloatingPointExceptions& EnableFloatingPointExceptions::operator=(const EnableFloatingPointExceptions& rhs)
00149 // {
00150 //   //An exception safe implementation is
00151 //   EnableFloatingPointExceptions temp(rhs);
00152 //   swap(rhs);
00153 //
00154 //   return *this;
00155 // }
00156 
00157 //
00158 // member functions
00159 //
00160 
00161 void
00162 EnableFloatingPointExceptions::postEndJob()
00163 {
00164 
00165 // At EndJob, put the state of the fpu back to "OSdefault"
00166 
00167   fpuState_ = stateMap_[String("OSdefault")];
00168   fesetenv( &OSdefault_ );
00169   if( reportSettings_ ) edm::LogVerbatim("FPE_Enable") << "\nSettings at end job ";
00170   echoState();
00171 }
00172 
00173 void 
00174 EnableFloatingPointExceptions::preModule(const ModuleDescription& iDescription)
00175 {
00176 
00177 // On entry to a module, find the desired state of the fpu and set it accordingly.
00178 // Note that any module whose label does not appear in our list gets the default settings.
00179 
00180   String modName = iDescription.moduleLabel();
00181   if( stateMap_.find(modName) == stateMap_.end() )  {
00182     fpuState_ = stateMap_[String("default")];
00183   } else {
00184     fpuState_ = stateMap_[modName];
00185   }
00186   fesetenv( &fpuState_ );
00187   stateStack_.push(fpuState_);
00188   if( reportSettings_ ) {
00189     edm::LogVerbatim("FPE_Enable") << "\nSettings at begin module " << modName;
00190     echoState();
00191   }
00192 }
00193 void 
00194 EnableFloatingPointExceptions::postModule(const ModuleDescription& iDescription)
00195 {
00196 
00197 // On exit from a module, set the state of the fpu back to what it was before entry
00198 
00199   stateStack_.pop();
00200   fpuState_ = stateStack_.top();
00201   fesetenv( &fpuState_ );
00202   if( reportSettings_ ) {
00203     edm::LogVerbatim("FPE_Enable") << "\nSettings after end module ";
00204     echoState();
00205   }
00206 }
00207 
00208 void 
00209 EnableFloatingPointExceptions::controlFpe()
00210 {
00211   // Local Declarations
00212 
00213   unsigned short int FE_PRECISION = 1<<5;
00214   unsigned short int suppress;
00215 
00216 #ifdef __linux__
00217 
00218 /*
00219  * NB: We are not letting users control signaling inexact (FE_INEXACT).
00220  */
00221 
00222   suppress = FE_PRECISION;
00223   if ( !enableDivByZeroEx_ ) suppress |= FE_DIVBYZERO;
00224   if ( !enableInvalidEx_ )   suppress |= FE_INVALID;
00225   if ( !enableOverFlowEx_ )  suppress |= FE_OVERFLOW;
00226   if ( !enableUnderFlowEx_ ) suppress |= FE_UNDERFLOW;
00227   fegetenv( &fpuState_ );
00228   fpuState_.__control_word = suppress;
00229   fesetenv( &fpuState_ );
00230 
00231 #ifdef __i386__
00232 
00233   if (setPrecisionDouble_) {
00234     fpu_control_t cw;
00235     _FPU_GETCW(cw);
00236 
00237     cw = (cw & ~_FPU_EXTENDED) | _FPU_DOUBLE;
00238     _FPU_SETCW(cw);
00239   }
00240 #endif
00241 #endif
00242 
00243 }
00244 
00245 void
00246 EnableFloatingPointExceptions::echoState()
00247 {
00248   if( reportSettings_ ) {
00249     int femask = fegetexcept();
00250     edm::LogVerbatim("FPE_Enable") << "Floating point exception mask is " 
00251                                    << std::showbase << std::hex << femask;
00252 
00253     if( femask & FE_DIVBYZERO )
00254       edm::LogVerbatim("FPE_Enable") << "\tDivByZero exception is on";
00255     else
00256       edm::LogVerbatim("FPE_Enable") << "\tDivByZero exception is off";
00257 
00258     if( femask & FE_INVALID )
00259       edm::LogVerbatim("FPE_Enable") << "\tInvalid exception is on";
00260     else
00261       edm::LogVerbatim("FPE_Enable") << "\tInvalid exception is off";
00262 
00263     if( femask & FE_OVERFLOW )
00264       edm::LogVerbatim("FPE_Enable") << "\tOverFlow exception is on";
00265     else
00266       edm::LogVerbatim("FPE_Enable") << "\tOverflow exception is off";
00267 
00268     if( femask & FE_UNDERFLOW )
00269       edm::LogVerbatim("FPE_Enable") << "\tUnderFlow exception is on";
00270     else
00271       edm::LogVerbatim("FPE_Enable") << "\tUnderFlow exception is off";
00272   }
00273 }

Generated on Tue Jun 9 17:36:39 2009 for CMSSW by  doxygen 1.5.4