Sus*_*ush 3 c x86 multithreading memory-barriers
我正在运行x86,我想看到我的机器上无序执行导致的错误.根据这篇维基文章,我尝试写一篇,但我总是看到"x的值是33":
#include<stdio.h>
#include<pthread.h>
#include <sys/types.h>
int x, f;
void *handler(void *ptr) {
while (f == 0);
// Expectation: Sometimes, this should print 11 due to out-of-order exec
printf("value of x is %d \n", x);
return NULL;
}
int main() {
pthread_t thread1;
while(1) {
x = 11; f = 0;
pthread_create(&thread1, NULL, handler, NULL);
x = 33;
f = 1;
pthread_join(thread1, NULL);
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
什么是最简单的c程序可以说明乱序执行错误?为什么这有时不打印"x的值是11"?
您尝试创建的效果不依赖于无序执行.这只是可以创建内存重新排序的事情之一.此外,现代x86执行无序执行,但使用其内存顺序缓冲区来确保存储提交到L1d /在程序顺序中变为全局可见.(因为x86的内存模型只允许StoreLoad重新排序,而不是StoreStore.)
内存重新排序与指令执行重新排序是分开的,因为即使有序CPU也使用存储缓冲区来避免在缓存未命中存储上停滞.
在有序ARM CPU上的AC实现可以打印11或33,如果x并且f最终在不同的高速缓存行中.
我假设您编译时已禁用优化,因此您的编译器会有效地处理所有变量volatile,即volatile int x,f.否则while(f==0);循环将编译为if(f==0) { infloop; },只检查f一次.(非原子变量的数据竞争UB允许编译器从环路中提升负载,但volatile必须始终进行负载 .https://electronics.stackexchange.com/questions/387181/mcu-programming-c-o2-优化 - 循环中断#387478).
生成的asm/machine代码中的商店将以C源顺序显示.
您正在编译x86,它具有强大的内存模型:x86存储是发布存储,x86负载是获取负载.您没有获得顺序一致性,但您可以免费获得acq_rel.(对于未经优化的代码,即使您不要求它也会发生.)
因此,在没有针对x86进行优化的情况下编译时,您的程序就相当于
_Atomic int x, f;
int main(){
...
pthread_create
atomic_store_explicit(&x, 33, memory_order_release);
atomic_store_explicit(&f, 1, memory_order_release);
...
}
Run Code Online (Sandbox Code Playgroud)
同样对于负载方面.这while(f==0){}是x86上的一个获取负载,所以让读取端等到它看到非零f保证它也看到了x==33.
但是如果您为ARM或PowerPC这样的弱有序ISA编译,那么asm级别的内存排序可以确保允许StoreStore和LoadLoad重新排序,因此11如果编译时没有优化,您的程序就可以打印.
另请参见https://preshing.com/20120930/weak-vs-strong-memory-models/
| 归档时间: |
|
| 查看次数: |
282 次 |
| 最近记录: |