- 论坛徽章:
- 0
|
现在 OS 可能大多都是使用 pause 指令的 spin-wait loop 原理实现 spin lock
贴一个在 x64 版 win7's kernel 中发现的 spin lock
nt!ExInterlockedAddLargeInteger:
fffff800`026e69d0 9c pushfq
fffff800`026e69d1 488bc2 mov rax,rdx
fffff800`026e69d4 fa cli
fffff800`026e69d5 f0490fba2800 lock bts qword ptr [r8],0
fffff800`026e69db 731e jae nt!ExInterlockedAddLargeInteger+0x2b (fffff800`026e69fb)
nt!ExInterlockedAddLargeInteger+0xd:
fffff800`026e69dd f7042400020000 test dword ptr [rsp],200h
fffff800`026e69e4 7401 je nt!ExInterlockedAddLargeInteger+0x17 (fffff800`026e69e7)
nt!ExInterlockedAddLargeInteger+0x16:
fffff800`026e69e6 fb sti
nt!ExInterlockedAddLargeInteger+0x17:
fffff800`026e69e7 f390 pause
fffff800`026e69e9 49f70001000000 test qword ptr [r8],1
fffff800`026e69f0 75f5 jne nt!ExInterlockedAddLargeInteger+0x17 (fffff800`026e69e7)
nt!ExInterlockedAddLargeInteger+0x22:
fffff800`026e69f2 fa cli
fffff800`026e69f3 f0490fba2800 lock bts qword ptr [r8],0
fffff800`026e69f9 72e2 jb nt!ExInterlockedAddLargeInteger+0xd (fffff800`026e69dd)
nt!ExInterlockedAddLargeInteger+0x2b:
fffff800`026e69fb 480fc101 xadd qword ptr [rcx],rax
fffff800`026e69ff f049832000 lock and qword ptr [r8],0
fffff800`026e6a04 f7042400020000 test dword ptr [rsp],200h
fffff800`026e6a0b 7401 je nt!ExInterlockedAddLargeInteger+0x3e (fffff800`026e6a0e)
nt!ExInterlockedAddLargeInteger+0x3d:
fffff800`026e6a0d fb sti
nt!ExInterlockedAddLargeInteger+0x3e:
fffff800`026e6a0e 4883c408 add rsp,8
fffff800`026e6a12 c3 ret |
nt!ExInterlockedAddLargeInteger+0x17:
fffff800`026e69e7 f390 pause
fffff800`026e69e9 49f70001000000 test qword ptr [r8],1
fffff800`026e69f0 75f5 jne nt!ExInterlockedAddLargeInteger+0x17 (fffff800`026e69e7)
这是一个 spin-wait loop
整个 nt!ExInterlockedAddLargeInteger() 大致如下:
LargeInteger
nt!ExInterlockedAddLargeInteger(LargeInteger *pLI, long n, int * synchronization)
{
if (*synchronization == 0) {
*synchronization = 1;
} else
while (*synchronization) {
/* spin-wait loop */
}
LargeInteger LI = *pLI;
*pLI = *pLI + n;
*synchronization = 0;
return LI;
} |
这个 spin-wait loop 在等待系统中另一个线程对 synchronization 变量进行修改为 0,也就是等待某个条件(释放资源)
pause 指令是构成 spin-wait loop 的关键,它将消耗 CPU 时间,但它可以降低功耗!
Intel 手册说可以改进 loop 的性能。 大概主要的对 CPU 流水线有某个细微的影响。 |
|