我是否在C中使用volatile特性需要特殊的硬件支持才能工作?

时间:2015-06-03 13:36:14

标签: c++ c caching volatile

我从this question

中了解示例,了解volatile的作用和不做的事情。
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从内存中读取sme​​Per但是cpu不知道内存是在RAM中还是其中一个缓存。因此,如果另一台设备更改了WELL_KNOWN_SEM_ADDR的内容,则waitForSemaphore不一定知道。所以必须有其他东西让它发挥作用。

我已阅读thisthis,看来volatile本身并不足以保证此类程序的正常工作,必须有一些平台相关的魔法可以通过传递L1 / 2/3缓存或强制冲他们,对吗?如果可以在所有流行的平台上提供此类支持,例如x86?

3 个答案:

答案 0 :(得分:4)

volatile禁止编译器优化对这些变量的访问,或者对所有volatile变量重新排序此类访问(仅限!)。实际语义可能是实现定义(但必须由编译器指定)。

对于硬件:是的,高速缓存和总线缓冲区(例如"写入缓冲区")仍然可以重新排序,而不是说CPU。 volatile并不意味着围栏/障碍。因此,底层硬件必须将这样的存储区域标记为"(强烈)有序"至少。如果涉及外部硬件,则还必须标记区域"未缓存",因此每次访问都将直接进入硬件。除非有某种" snooping"系统中的硬件(每个CPU在另一个CPU中的缓存更改时得到通知)。

C11提供stdatomic.h(可选)。这更适合线程/中断同步。如果多个CPU,volatile无论如何都接近无用。但是,它仍然具有硬件应用程序(可能需要额外的互斥锁或对外围设备的隐式独占访问)。

答案 1 :(得分:1)

volatile本身只告诉编译器"假设当你存储到易失性对象时,有人可能会注意到,所以你不能优化商店"和"假设当你读取一个易失性对象时,结果可能与你存储的内容不同,有人可能会注意到你读了易失性对象,所以你不能优化读取,你必须使用读取的值,而不是你认为应该存储在那里的值#34;。

例如,如果你写

int x = 0 * (*p);

编译器不能说"无论* p是什么,我都会将x设置为0,所以我不会'需要费心阅读* p"。如果* p是易变的,那就错了。

在C11中有一些新功能可以帮助您,或者您可能希望使用正确的OS功能。

答案 2 :(得分:0)

  1. 不,易失性因此不需要硬件支持才能工作。有关详细信息,请参阅gnaster729的回答。

  2. 缓存同步问题与所谓的"内存模型" (https://en.wikipedia.org/wiki/Memory_ordering);如果描述得很短 - 没有"如果另一个设备改变了变量" (从阅读方面看不到它),只有一个东西"如果另一个设备变量变量早于变量b" - 这是可观察的。处理它,所谓的记忆围栏" a.k.a."记忆障碍"使用(https://en.wikipedia.org/wiki/Memory_barrierhttps://www.kernel.org/doc/Documentation/memory-barriers.txt),如果我没有弄错的话,在C ++ 11中有特殊的支持。在x86上,内存栅栏隐含在CAS指令中;人们普遍认为x86符合所谓的TSO(总存储顺序)内存模型,这种模型非常严格,也是最容易处理的内存模型之一(尽管如上面的kernel.org中所述,处理它是完全可行的) 任何内存模型下的正确性。)