So, declaring my int as:
volatile int run;
Would meet the first requirement. |
Strictly speaking it needs to be
volatile sig_action_t or
volatile std::atomic_int as detailed in the link I posted. This is a consequence of the re-entrancy requirement.
However after scouting around a bit on the web, one of the requirements of being re-entrant, is to not use global variables. |
You
can use global variables, with the understanding that reentrant code can be called at almost any point during its own execution.
For example's sake, imagine that
print is atomic; it cannot be interrupted part-way through by a signal. Then
1 2 3 4 5 6 7 8 9 10 11
|
volatile std::sig_action_t global;
void not_reentrant()
{
// because we chose std::sig_action_t
// this function cannot be re-entered during the assignment operation
global = 2;
// but we may be interrupted here
print(global); // might print 4!
global = 4;
}
| |
If we're interrupted immediately before the call to
print then our global variable might be clobbered by
global.
We can only perform atomic operations on global data:
1 2 3 4
|
void reentrant()
{
global = 4;
}
| |
Does this help?
"The volatile qualifier tells the compiler that a variable can have its value altered by agencies other than the program" |
For example: on some small computers (embedded micro-controllers), the real-time status of a connected sensor (a peripheral) can be checked by examining a particular memory location -- whose contents are set
directly by the peripheral (a scheme called
memory-mapped I/O).
When accessing that memory location,
volatile must be used: it prevents the compiler from optimizing under the assumption that the value didn't change "by itself".
With this being said, it is the
kernel which calls the signal handler -- not your program. Therefore data modified in the signal handler must be declared
volatile.