Robert Love说" set_task_state(task,state)将给定任务设置为给定状态。如果适用,它还提供内存屏障以强制在其他处理器上进行排序(这仅在SMP系统上需要)否则它相当于 task-> state = state
我的问题是: 内存屏障如何强制在其他处理器上进行排序?
罗伯特的爱意味着什么 - 为什么需要这个? 他可能会谈论这个顺序是什么?他在这里谈论调度队列吗?
如果是这样,SMP中的每个处理器都有不同的调度队列吗? 我很困惑
答案 0 :(得分:2)
为了挤出额外的性能,你的CPU执行Out of Order Execution,它可以按照与代码中给出的顺序不同的顺序运行操作。优化编译器可以更改操作的顺序以使代码更快。编译器编写者/内核类型必须注意不要改变期望(或至少符合规范,以便他们可以说你的期望是不对的)
这是一个例子
1: CPU1: task->state = someModifiedStuff
2: CPU1: changed = 1;
3: CPU2: if (changed)
4: CPU2: ...
如果我们没有设置状态的障碍,我们可以重新排序1和2。 由于两者都没有引用另一个,因此单线程实现不会发现任何差异。但是,在SMP情况下,我们重新排序1和2行3可以看到改变但不是状态改变。例如, 如果CPU1运行第2行(但不是1)然后CPU2运行第3行和第4行,则CPU2将以旧状态运行,如果随后清除已更改,则CPU1刚刚进行的更改将丢失。
屏障告诉系统,在某些时候,在1到2之间,它必须使事情保持一致才能继续前进。
搜索内存障碍',您会找到一些好帖子:Memory Barriers Are Like Source Control Operations
答案 1 :(得分:1)
内存障碍是必需的,因为当前的CPU执行大量乱序执行:如果它们之间没有依赖关系,它们一次加载许多指令并以非确定性顺序执行它们。
为了避免由于编译器优化而重新排序,volatile
关键字就足够了(在这里谈到C ++)。因此,同步原语(例如lock
)通过正确使用volatile
和某种汇编程序fence
指令来实现(其中有许多指令,或多或少强大:见7.5节)。 5 {in http://www.intel.com/content/www/us/en/architecture-and-technology/64-ia-32-architectures-optimization-manual.html)
x = 0;
thread 1: thread 2:
a.lock(); a.lock();
x++; x++;
a.unlock(); a.unlock();
x
将导致2
正确无误。现在假设不能保证执行这两个线程的指令的顺序。如果执行的指令是(a和x是独立的,那么如果lock()
没有用内存屏障正确实现,那么将允许无序执行):
x = 0;
thread 1: thread 2:
x++; x++;
a.lock(); a.lock();
a.unlock(); a.unlock();
x
可能会等同于2
或1
。