【发布时间】:2015-06-03 13:36:13
【问题描述】:
我了解 volatile 做什么和不做什么,以 this question 为例
void waitForSemaphore()
{
volatile uint16_t* semPtr = WELL_KNOWN_SEM_ADDR;/*well known address to my semaphore*/
while ((*semPtr) != IS_OK_FOR_ME_TO_PROCEED);
}
我的问题是:在存在 cpu 缓存的情况下,volatile 不能保证上述工作,因为它只强制 cpu 从内存中读取 smePer,但 cpu 不知道内存是在 RAM 中还是在缓存之一中。因此,如果另一个设备更改了 WELL_KNOWN_SEM_ADDR 的内容,waitForSemaphore 不一定知道。所以必须有其他东西使它起作用。
我已阅读 this 和 this,似乎 volatile 本身不足以保证此类程序正常工作,必须有一些依赖于平台的魔法,要么通过 L1/2/3 缓存或强制刷新它们,我我对吗?如果是这样,是否所有流行平台(例如 x86)都提供此类支持?
【问题讨论】:
-
怎么会这样,volatile只是编译器不缓存cpu寄存器中的变量的指令,它不会造成内存屏障,如何确保读取的值与RAM一致?
-
通常内存映射的硬件是不可缓存的。
-
@user3528438:
volatile普通 RAM 中的变量也用于线程/中断同步。使用 C11,stdatomic.h可能是更好的选择,一旦涉及多个 CPU,volatile几乎无用。 -
@swang 如果硬件的内存模型不能保证一致性(例如 x86 上的 mfence 指令),您需要发出硬件/cpu 特定指令来执行此操作。但不要那样做。要么你在一个低级处理器上工作,你将某些硬件寄存器映射到内存(这是不可缓存的)并在你的 C 程序中使用 volatile,或者使用新 C/C++ 版本的互斥体/信号量或原子特性,或者为您的平台提供经过良好测试的现有原子库。