[英]What is processor Lock# signal and how it works?
我正在阅读一本关于汇编(中级)的书,它提到像xchg
这样的一些指令会自动断言处理器 LOCK# 信号。 在网上搜索它发现它赋予处理器任何共享 memory 的专有权,但没有具体细节。 这让我想知道这项权利是如何运作的。
基本问题是有些指令读取memory,修改读取的值,然后写入新的值; 如果 memory 的内容在读取和写入之间发生变化,(某些)并行代码可能会导致 state 不一致。
一个很好的例子是一个 CPU 执行inc dword [foo]
而另一个 CPU 执行dec dword [foo]
。 两条指令(在两个 CPU 上)都执行后,值应与原来相同; 但是两个 CPU 都可以读取旧值,然后两个 CPU 都可以修改它,然后两个 CPU 都可以写入它们的新值; 导致该值比您预期的高 1 或低 1。
解决方案是使用#lock
信号来防止其他任何东西同时访问同一块 memory。 例如,第一个 CPU 将断言#lock
然后执行它的读取/修改/写入,然后取消断言#lock
; 并且其他任何东西都会看到#lock
被断言并且必须等到#lock
被取消断言才能执行任何memory访问。 换句话说,它是一种简单的互斥形式(如自旋锁,但在硬件中)。
当然,“其他一切都必须等待”有性能成本; 所以它主要只在软件明确请求时完成(例如lock inc dword [foo]
而不是inc dword [foo]
),但在少数情况下它是隐式完成的 - 当操作数使用 memory 时的xchg
指令,并更新到dirty/ CPU 使用的某些表中的已访问/忙碌标志(用于分页和 GDT/LDT/IDT 条目)。 还; 后来(我认为是 Pentium Pro?),该行为被优化为与缓存一致性协议一起使用,因此如果缓存行可以放在专用的#lock
中,则不会断言 #lock 。
注意:过去有 2 个 CPU 错误(Intel Pentium "0xF00F" 错误和 Cyrix "Coma" 错误),其中一个 CPU 可以被欺骗断言#lock
信号并且从不取消断言; 导致整个系统锁定,因为没有任何东西可以访问任何 memory。
- 这是否意味着任何其他计算机设备(例如 GPU 或其他设备)都无法访问 memory。 实际上,其他设备可以直接与 RAM 对话,而无需先通过 CPU。
是的。 如果#lock
被断言(不包括较新的 CPU 可以将缓存线放入独占 state 的情况); 任何访问 memory 的东西都必须等待#lock
被取消断言。
注意:大多数现代设备可以/确实直接访问 memory(在不使用 CPU 传输数据的情况下将数据传输到 RAM 或从 RAM 传输数据)。
- 处理器如何知道它在这个锁定的 state 中是否保存在控制或 rflags 寄存器中,或者因为我看不到在拥有多核 CPU 时这个操作是如何工作的。
它不保存在任何寄存器的内容中。 它实际上是公共汽车或链路上的电子信号。 举一个极其简单的例子; 假设总线有 32 条“地址”线,32 条“数据”线,加上#lock
线; 其中“断言#lock
”表示该#lock
线上的电压从0 伏到3.3 伏。 当任何东西想要读取或写入 memory(在尝试更改“地址”线或“数据”线上的电压之前)时,它会检查#lock
线上的电压是否为 0 伏。
注意:真正的总线要复杂得多,需要一些其他信号(例如传输方向、避免冲突、“I/O 端口或物理内存”等); 现代公共汽车使用串行通道而不是并行线; 现代系统使用“点对点链接”而不是“所有事物共享的公共总线”。
- 我访问的网站说锁定任何共享的 memory。 这是否意味着在此锁定期间整个 RAM 被锁定或仅锁定执行指令的 memory 页面(或 memory 的一部分而不是全部)。
不如说公交车上锁了; 一切都必须使用总线来访问 memory (当总线被锁定时,没有其他东西可以使用总线,即使其他东西试图将总线用于与 memory 无关的事情 - 例如发送一个 IRQ 到CPU)。
当然(由于积极的性能优化 - 主要是“如果缓存行可以放在专有的 state 中”优化)更好的是说硬件可以做任何感觉只要结果表现得好像有被锁定的共享总线(即使没有共享总线并且实际上没有任何东西被锁定)。
注意:80x86 支持未对齐的访问(例如,您可以lock inc dword [address]
,其中访问可以跨越边界),如果 memory 访问确实跨越边界,则 CPU 需要组合 2 个或更多片段(例如,从一个高速缓存行的结尾和从下一个高速缓存行开始的几个字节)。 现代虚拟 memory 意味着如果虚拟地址跨越页面边界,则 CPU 需要访问 2 个不同的虚拟页面,这些页面可能具有“极其不相关”的物理地址。 如果理论上的 CPU 尝试实现独立锁(每个 memory 区域的不同锁),那么它还需要支持断言多个锁信号。 这可能会导致死锁——例如,一个 CPU 锁定“内存页面 1”,然后尝试锁定“内存页面 2”(并且不能因为它被锁定); 而另一个 CPU 锁定“内存页面 2”然后尝试锁定“内存页面 1”(并且不能因为它被锁定)。 要解决这个问题,理论上的 CPU 必须使用“全局锁排序”——始终以特定顺序断言锁。 最终结果将是大量的复杂性(增加的复杂性可能会花费更多的性能而不是节省的性能)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.