'ARM real-time - How to avoid race conditions in interrupt service routines
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.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
