如何解决如何在不阻塞的情况下保护非原子变量不被中断和应用程序代码修改
我希望能够在不阻塞的情况下修改中断上下文或应用程序上下文中的非原子变量。为了防止 ISR 阻塞,我使用原子标志来保护非原子数据。
#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;
}
- 这是否正确保护了数据?
- 是否允许编译器编译出 count_locked 变量或重新排序指令,以便数据在锁之外?
- 我认为没有什么需要标记为 volatile 是否正确?
- 这相当于互斥锁吗?
解决方法
考虑两个线程分别同时调用MyISR
和setCount
:
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;
原子不保护对 count
的写入。
-
没有
-
数据被修改而没有被正确锁定
-
是的。引自 When to use volatile with multi threading?:“volatile 对于平台无关的多线程应用程序编程(几乎)毫无用处。”
-
没有
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。