ATLAS Offline Software
Toggle main menu visibility
Loading...
Searching...
No Matches
Control
AthenaServices
src
FPEControlSvc.cxx
Go to the documentation of this file.
1
/*
2
Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3
*/
10
11
#include "
FPEControlSvc.h
"
12
#include "
AthenaKernel/errorcheck.h
"
13
#include <fenv.h>
14
#include <cstring>
15
16
22
FPEControlSvc::FPEControlSvc
(
const
std::string& name, ISvcLocator* svc )
23
:
AthService
( name, svc ),
24
m_toolSvc
(
"ToolSvc"
, name),
25
m_env
(),
26
m_haveEnv
(false),
27
m_enabled
(0),
28
m_disabled
(0),
29
m_removeInFinalize
(false),
30
m_feSetRounding
(
""
)
31
{
32
declareProperty(
"Exceptions"
,
m_exceptions
);
33
declareProperty(
"ToolSvc"
,
m_toolSvc
);
34
declareProperty(
"FERoundingMode"
,
m_feSetRounding
);
35
m_exceptions
.declareUpdateHandler (&
FPEControlSvc::prophand
,
this
);
36
37
// Set up the default exceptions.
38
std::vector<std::string> defexc;
39
defexc.push_back (
"invalid"
);
40
defexc.push_back (
"divbyzero"
);
41
defexc.push_back (
"overflow"
);
42
m_exceptions
= defexc;
43
}
44
45
49
StatusCode
FPEControlSvc::initialize
()
50
{
51
// And change the exception mask.
52
prophand
(
m_exceptions
);
53
54
// Add ourself as an observer.
55
CHECK
(
m_toolSvc
.retrieve() );
56
m_toolSvc
->registerObserver (
this
);
57
58
if
(
m_feSetRounding
!=
""
)
59
{
60
REPORT_MESSAGE
(MSG::INFO) <<
"FE Rounding mode "
<<
m_feSetRounding
<<
" requested"
;
61
if
(
m_feSetRounding
==
"FE_TONEAREST"
)
62
{
63
if
( fesetround(FE_TONEAREST) )
64
REPORT_MESSAGE
(MSG::WARNING) <<
"Couldn't change FE Rounding to mode FE_TONEAREST !"
;
65
}
66
else
if
(
m_feSetRounding
==
"FE_UPWARD"
)
67
{
68
if
( fesetround(FE_UPWARD) )
69
REPORT_MESSAGE
(MSG::WARNING) <<
"Couldn't change FE Rounding to mode FE_UPWARD !"
;
70
}
71
else
if
(
m_feSetRounding
==
"FE_DOWNWARD"
)
72
{
73
if
( fesetround(FE_DOWNWARD) )
74
REPORT_MESSAGE
(MSG::WARNING) <<
"Couldn't change FE Rounding to mode FE_DOWNWARD !"
;
75
}
76
else
if
(
m_feSetRounding
==
"FE_TOWARDZERO"
)
77
{
78
if
( fesetround(FE_TOWARDZERO) )
79
REPORT_MESSAGE
(MSG::WARNING) <<
"Couldn't change FE Rounding to mode FE_TOWARDZERO !"
;
80
}
81
else
82
REPORT_MESSAGE
(MSG::WARNING) <<
"Don't know FE Rounding to mode "
<<
m_feSetRounding
;
83
}
84
85
return
StatusCode::SUCCESS;
86
}
87
88
92
StatusCode
FPEControlSvc::finalize
()
93
{
94
// remove only if requested
95
if
(
m_removeInFinalize
)
96
{
97
// Restore the FP environment to what is was before we ran.
98
fesetenv (&
m_env
);
99
}
100
101
return
StatusCode::SUCCESS;
102
}
103
104
115
void
FPEControlSvc::onCreate
(
const
IAlgTool*)
116
{
117
setFPU
();
118
}
119
120
121
namespace
{
122
123
128
std::string mask_to_string (
int
mask)
129
{
130
std::string out;
131
if
(mask & FE_INEXACT)
132
out +=
"inexact "
;
133
if
(mask & FE_DIVBYZERO)
134
out +=
"divbyzero "
;
135
if
(mask & FE_UNDERFLOW)
136
out +=
"underflow "
;
137
if
(mask & FE_OVERFLOW)
138
out +=
"overflow "
;
139
if
(mask & FE_INVALID)
140
out +=
"invalid "
;
141
if
(out.size() == 0)
142
out =
"(none) "
;
143
return
out;
144
}
145
146
147
}
// anonymous namespace
148
149
153
void
FPEControlSvc::prophand
(Gaudi::Details::PropertyBase&
/*prop*/
)
154
{
155
if
(!
m_haveEnv
) {
156
// Save the current FP environment.
157
fegetenv (&
m_env
);
158
m_haveEnv
=
true
;
159
}
160
else
{
161
// Reset to the FP environment before we started.
162
fesetenv (&
m_env
);
163
}
164
165
// Figure out which exceptions to enable/disable.
166
m_enabled
= 0;
167
m_disabled
= 0;
168
const
std::vector<std::string>& v =
m_exceptions
.value();
169
for
(
size_t
i = 0; i < v.size(); i++) {
170
bool
onoff =
true
;
171
const
char
* s = v[i].c_str();
172
if
(!s)
continue
;
173
if
(s[0] ==
'!'
) {
174
onoff =
false
;
175
++s;
176
}
177
int
thisexc = 0;
178
if
(strcasecmp (s,
"inexact"
) == 0)
179
thisexc = FE_INEXACT;
180
else
if
(strcasecmp (s,
"divbyzero"
) == 0)
181
thisexc = FE_DIVBYZERO;
182
else
if
(strcasecmp (s,
"underflow"
) == 0)
183
thisexc = FE_UNDERFLOW;
184
else
if
(strcasecmp (s,
"overflow"
) == 0)
185
thisexc = FE_OVERFLOW;
186
else
if
(strcasecmp (s,
"invalid"
) == 0)
187
thisexc = FE_INVALID;
188
else
{
189
REPORT_MESSAGE
(MSG::INFO)
190
<<
"Unknown exception name: "
<< v[i];
191
continue
;
192
}
193
194
if
(onoff) {
195
m_enabled
|= thisexc;
196
m_disabled
&= ~thisexc;
197
}
198
else
{
199
m_disabled
|= thisexc;
200
m_enabled
&= ~thisexc;
201
}
202
}
203
204
// Say what we're doing, and change the masks.
205
REPORT_MESSAGE
(MSG::INFO)
206
<<
"Enable: "
<< mask_to_string (
m_enabled
)
207
<<
"Disable: "
<< mask_to_string (
m_disabled
);
208
209
setFPU
();
210
}
211
212
216
void
FPEControlSvc::setFPU
()
217
{
218
feclearexcept (
m_enabled
);
219
#ifdef __GLIBC__
220
feenableexcept (
m_enabled
);
221
fedisableexcept (
m_disabled
);
222
#elif defined __APPLE__
223
#include "
CxxUtils/excepts.h
"
224
feenableexcept (
m_enabled
);
225
fedisableexcept (
m_disabled
);
226
#else
227
// The functions above are gnu-specific.
228
// Without GNU, we do it the harder way.
229
fenv_t newval;
230
fegetenv(&newval);
231
232
// CSR bit on means that the exception is masked.
233
234
newval.__control_word &=
~m_enabled
;
235
newval.__control_word |=
m_disabled
;
236
# ifdef __x86_64
237
// SSE floating point uses separate exception masks.
238
newval.__mxcsr &= (
~m_enabled
) << 7;
239
newval.__mxcsr |= (
m_disabled
) << 7;
240
# endif
241
fesetenv(&newval);
242
#endif
243
}
errorcheck.h
Helpers for checking error return status codes and reporting errors.
REPORT_MESSAGE
#define REPORT_MESSAGE(LVL)
Report a message.
Definition
Control/AthenaKernel/AthenaKernel/errorcheck.h:365
CHECK
#define CHECK(...)
Evaluate an expression and check for errors.
Definition
Control/AthenaKernel/AthenaKernel/errorcheck.h:422
FPEControlSvc.h
Service to enable or disable floating-point exceptions.
AthService::AthService
AthService()
FPEControlSvc::m_toolSvc
ServiceHandle< IToolSvc > m_toolSvc
Tool service.
Definition
FPEControlSvc.h:80
FPEControlSvc::m_disabled
int m_disabled
Mask of disabled exceptions.
Definition
FPEControlSvc.h:92
FPEControlSvc::m_haveEnv
bool m_haveEnv
Flag that we've retrieved the environment.
Definition
FPEControlSvc.h:86
FPEControlSvc::m_feSetRounding
std::string m_feSetRounding
flag to decide on rounding mode (for stability tests)
Definition
FPEControlSvc.h:98
FPEControlSvc::setFPU
void setFPU()
Set the FPU exception masks from m_enabled and m_disabled.
Definition
FPEControlSvc.cxx:216
FPEControlSvc::prophand
void prophand(Gaudi::Details::PropertyBase &prop)
Property change handler.
Definition
FPEControlSvc.cxx:153
FPEControlSvc::m_removeInFinalize
bool m_removeInFinalize
boolean to decide to (not) remove the observer in finalize
Definition
FPEControlSvc.h:95
FPEControlSvc::m_exceptions
StringArrayProperty m_exceptions
Property specifying the desired exception mask.
Definition
FPEControlSvc.h:77
FPEControlSvc::m_enabled
int m_enabled
Mask of enabled exceptions.
Definition
FPEControlSvc.h:89
FPEControlSvc::finalize
virtual StatusCode finalize()
Standard finalize method.
Definition
FPEControlSvc.cxx:92
FPEControlSvc::FPEControlSvc
FPEControlSvc(const std::string &name, ISvcLocator *svcloc)
Constructor.
Definition
FPEControlSvc.cxx:22
FPEControlSvc::onCreate
virtual void onCreate(const IAlgTool *)
Called after each tool has been created.
Definition
FPEControlSvc.cxx:115
FPEControlSvc::initialize
virtual StatusCode initialize()
Standard initialize method.
Definition
FPEControlSvc.cxx:49
FPEControlSvc::m_env
fenv_t m_env
The FP environment before we initialize.
Definition
FPEControlSvc.h:83
excepts.h
Declarations of feenableexcept()/fedisableexcept() functions for MacOSX.
Generated on
for ATLAS Offline Software by
1.17.0