Reputation: 90
I want to be able to modify a non-atomic variable in interrupt context or application context without ever blocking. To prevent the ISR from blocking, I use an atomic flag to guard the non-atomic data.
#include <atomic>
#include <cstdint>
using CountLock = std::atomic<bool>;
static_assert(CountLock::is_always_lock_free, "count lock must be lock free");
#define TARGET_COUNT (1000)
CountLock count_locked{false};
uint64_t count{0}; // non-atomic on 32-bit system
// In interrupt
void MyISR()
{
// Don't modify count if locked
if (count_locked)
return;
++count; // non-atomic
if (count == TARGET_COUNT)
// Do something
}
// Application code (not in interrupt)
void setCount(uint64_t newCount)
{
// lock count while we are setting it
count_locked = true;
count = newCount;
count_locked = false;
}
Upvotes: 0
Views: 332
Reputation: 122830
Consider two threads concurrently calling MyISR
and setCount
respectively:
T1 T2
if (count_locked)
return;
count_locked = true;
++count; /*non-atomic*/ count = newCount; // << data race
if (count == TARGET_COUNT)
// Do something
count_locked = false;
The atomic does not protect writes to count
.
No
The data is modifed without being properly locked anyhow
Yes. Quoting from When to use volatile with multi threading?: "volatile is (nearly) useless for platform-agnostic, multithreaded application programming."
No
Upvotes: 2