并发访问struct成员

时间:2010-08-22 16:32:49

标签: c concurrency embedded microcontroller

我使用的是32位微控制器(STR91x)。我同时访问(来自ISR和主循环)类型枚举的struct成员。访问仅限于写入ISR中的enum字段并检查主循环。枚举的基础类型不大于整数(32位)。 我想确保我没有遗漏任何东西,我可以安全地做到。

6 个答案:

答案 0 :(得分:2)

如果32位读写是原子的,几乎可以肯定的话(你可能想确保你的枚举是单词对齐的)那么你所描述的就好了。

答案 1 :(得分:2)

as paxdiablo& David Knell说,一般来说这很好。即使你的公共汽车是< 32位,很可能指令的多个总线周期不会被中断,并且您将始终读取有效数据。

你所说的,以及我们所知道的,但值得重复的是,这对单作家,N读者的情况来说是好的。如果你有多个作家,除非你有一个保护数据的结构,否则所有的赌注都会被取消。

答案 2 :(得分:2)

如果要确定,请找到生成汇编列表的编译器开关,并检查ISR中的写入和主循环中的读取的程序集。即使您不熟悉ARM程序集,我也相信您可以快速轻松地识别读写是否是原子的。

答案 3 :(得分:1)

ARM支持32位对齐读取,就中断而言是原子的。但是,请确保您的编译器不会尝试将值缓存在寄存器中!要么将其标记为volatile,要么使用显式内存屏障 - 在GCC上可以这样做:

int tmp = yourvariable;
__sync_synchronize(yourvariable);

但是,请注意,当前版本的GCC是__sync_synchronize的完整内存屏障,而不仅仅是一个变量,因此volatile可能更适合您的需求。

此外,请注意您的变量将自动对齐,除非您正在做一些奇怪的事情(即,明确指定结构在内存中的位置,或请求打包的结构)。 ARM上的未对齐变量无法以原子方式读取,因此请确保它已对齐,或在读取时禁用中断。

答案 4 :(得分:0)

嗯,这完全取决于你的硬件,但如果ISR可能被主线程中断,我会感到惊讶。

所以可能你唯一需要注意的是主线程是否可以在读取中途中断(因此它可能会获得旧值的一部分和新部分的一部分)。

应该是一个简单的咨询规范的事情,以确保只在指令之间处理中断(这可能是因为替代方案会非常复杂)并且你的32位负载是单指令。

答案 5 :(得分:0)

对齐的32位访问通常是原子的(除非它是一个特别荒谬的编译器!)。

然而,坚如磐石的解决方案(以及通常也适用于非32位目标的解决方案)是在访问中断之外的数据时暂时禁用中断。最强大的方法是通过访问函数来静态地限定数据,而不是使数据global在那里没有单一访问点,因此无需在需要时强制执行原子访问机制。