On ARM Cortex M3 bare-metal real-time microcontroller application, I need to ensure that function dispatch()
is called exactly once per interrupt. dispatch()
uses global data and is hence not reentrant, so I also need to ensure that it does not get called in an ISR if it is already in the middle of running.
In pseudocode, I can achieve these goals like this:
atomic bool dispatcher_running;
atomic uint dispatch_count;
ISR 0:
flag0 = true;
dispatch_count++;
if (!dispatcher_running)
dispatch();
ISR 1:
flag1 = true;
dispatch_count++;
if (!dispatcher_running)
dispatch();
...
void dispatch() {
if (dispatcher_running) // Line A
return;
dispatcher_running = true; // Line B
while (dispatch_count--) {
// Actual work goes here
}
dispatcher_running = false;
}
The challenge, however, is that dispatch_count
and dispatcher_running
need to be atomic or barriered. Otherwise, race conditions could result. Even pure atomic isn't enough: An ISR could call dispatch()
, which passes the check at Line A, and, before it gets to Line B, another ISR calls dispatch()
; this would result in two instances of dispatch
running simultaneously.
My questions are:
- What type of atomic or barriers do I need to make this work?
- Which ARM instructions (e.g.
DMB
) can be used to achieve them? - Is there a portable std C++ way to do something similar? I don't intend to use e.g.
std::atomic
, as this is bare metal. But I would like to have a similar C++ lib that does the equivalent, as I am prototyping parts of the application on a PC.