3 KeAcquireSpinLockAtDpcLevel的实现机制
MSDN上说明调用KeAcquireSpinLockAtDpcLevel的程序必须运行在DISPATCH_LEVEL上。
在多核处理器(Windows2003)下
先来查看一下KeAcquireSpinLockAtDpcLevel的汇编代码
nt!KeAcquireSpinLockAtDpcLevel:
mov ecx,dword ptr [esp+4]
nt!KeAcquireSpinLockAtDpcLevel+0x4
lock bts dword ptr[ecx],0
jb nt!KeAcquireSpinLockAtDpcLevel+0xe
ret 4
nt!KeAcquireSpinLockAtDpcLevel+0xe:
test dwordptr [ecx],1
je nt!KeAcquireSpinLockAtDpcLevel+0x4
pause
jmp nt!KeAcquireSpinLockAtDpcLevel+0xe
将KeAcquireSpinLockAtDpcLevel翻译成伪代码:
KeAcquireSpinLockAtDpcLevel (SpinLock){
while(TRUE) {
//独占处理器和相关存储空间执行下面代码
lastbit=SpinLock.lastbit;
SpinLock.lastbit=1;
//释放独占
if(lastbit ==1){
while(SpinLock.lastbit ==1) ;
}
elsebreak;
}
}
对比一下KfAcquireSpinLock,KeAcquireSpinLockAtDpcLevel除了不提升IRQL到DISPATCH_LEVEL,其他都是一样的,KeAcquireSpinLockAtDpcLevel的运行环境已经在DISPATCH_LEVEL上了,确实也不要提升。
KefReleaseSpinLockFromDpcLevel的实现
nt!KefReleaseSpinLockFromDpcLevel:
lock and byte ptr [ecx],0
ret
KefReleaseSpinLockFromDpcLevel就是简单实用lock指令把Spinlock的值置成0释放。
在单核处理器(WindowsXP)下
在单核处理器下KfAcquireSpinLock所作的工作就是简单提升一下IRQL到DISPATCH_LEVEL,那么KeAcquireSpinLockAtDpcLevel已经在DISPATCH_LEVEL,还需要做什么工作呢?是不是什么工作都不需要做了?
实际上观察KeAcquireSpinLockAtDpcLevel在单核处理器下的实现,发现确实什么也没做,直接返回了。
KefReleaseSpinLockFromDpcLevel也是一样,直接返回了。
分析:
关于KeAcquireSpinLockAtDpcLevel在MSDN上有这样一段文字:
当IRQL=DISPATCH_LEVEL时,驱动调用KeAcquireSpinLockAtDpcLevel比调用KeAcquireSpinLock有更好的性能。当IRQL<DISPATCH_LEVEL时,驱动必须调用KeAcquireSpinLock。
其实观察具体实现,KeAcquireSpinLockAtDpcLevel“更好的性能”体现在多核状态下少运行了两条MOV指令,单核状态下少运行了三条MOV指令和一条SHR指令,不得不感叹下Windows的惜指令如金。