- 论坛徽章:
- 11
|
本帖最后由 zylthinking 于 2011-11-01 17:25 编辑
事隔多日, 又在这里开始弄不清楚了:
内存屏障似乎不影响编译器怎么编译吧;
那么如果一下伪码:
int a = 0;
mov eax, a
-------------------> 发生切换
mb();
-------------------> 或者这里发生切换
test eax, ebx
在另一个线程中
a = 10;
wmb();
那么执行 test eax, ebx 中, eax 中能保证为 10 吗?
内存屏障影响的是高速缓存, 那么影响已经 load 进 CPU 寄存器中的值吗?
我的理解:
在单CPU下, 寄存器中的值在切换时会被保存到内存, 切换回后再次从内存中恢复
多CPU下, CPU1 发出的 invalid request 影响的是高速缓存, 但进入寄存器中的值怎么知道自己对应的内存已经变了? 不可能为每一个寄存器中的值保留一份相对应的内存地址吧
那么, 执行到 test eax, ebx 中, 说不定这个还真是 0
也就是说, 内存屏障影响的是 mov eax, a, 如果 wmb() 执行了, 那么CPU高速缓存中的数据保证失效, 从而读内存, wmb 同时保证内存中已经是新值了, 从而可以保证完整性;
但如果执行到 mov eax, a 之后再发生 a = 10, wmb(), 那么只会导致CPU 高速缓存失效, 内存被更新; 但 test eax, ebx 确实寄存器间的操作, 会不会导致数据错误???
而 voaltile, 正是约束编译器的, 也就是说它在编译层面保证 mov eax, a test eax, ebx 不会被编译为2条指令, 而时编译为 test *(&a), ebx???
现在再接着推理:
1。 在UP下, a = 10;
wmb();
执行时, int a = 0;
mov eax, a
-------------------> 发生切换
mb();
-------------------> 或者这里发生切换
test eax, ebx
中所有的寄存器内容其实都保存在 task 相关结构中, 那么 wmb时, CPU作为操作系统下层, 肯定没能力自己去找 task结构做更新; 因此, 等很久以后执行 test eax, ebx 时, 我基本肯定 eax中是 旧值了
2。 在SMP下, 假设两个CPU分贝同时在执行以下代码
int a = 0;
CPU1: CPU2:
a += 1; a += 2;
wb(); wb();
如果发生了这种情况, 两个CPU在相同的时间内执行了不同的赋值语句, 那么 CPU1 和 CPU2谁向谁同步呢???
估计是个随机情况了吧??? |
|