00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #ifdef __linux__
00018 #ifdef __i386__
00019 #include <fpu_control.h>
00020 #endif
00021 #endif
00022
00023
00024 #include "FWCore/Services/src/EnableFloatingPointExceptions.h"
00025 #include "DataFormats/Provenance/interface/ModuleDescription.h"
00026 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00027
00028
00029 using namespace edm::service;
00030
00031
00032
00033
00034
00035
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
00053
00054
00055
00056
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
00067
00068 PSet empty_PSet;
00069 VString empty_VString;
00070
00071 VString moduleNames = iPS.getUntrackedParameter<VString>("moduleNames",empty_VString);
00072
00073
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
00092
00093
00094
00095
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
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
00132
00133 fesetenv( &OSdefault_ );
00134 }
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161 void
00162 EnableFloatingPointExceptions::postEndJob()
00163 {
00164
00165
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
00178
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
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
00212
00213 unsigned short int FE_PRECISION = 1<<5;
00214 unsigned short int suppress;
00215
00216 #ifdef __linux__
00217
00218
00219
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 }