#include "Spin.h"
void
AcquireQueuedSpinLock(PSPIN_LOCK_QUEUE
pSpinLockQueue)
{
_asm
{
push eax
push ebx
push ecx
push edx
mov edx, pSpinLockQueue ; pSpinLockQueue_edx
mov ecx, dword ptr [edx+4] ; pSpinLock_ecx
mov eax, edx ; pSpinLockQueueOld_eax
= pSpinLockQueueOld_edx
xchg edx, dword ptr [ecx] ; pSpinLockQueue_edx
<--> *(pSpinLock_ecx)
cmp edx, 0 ; if(pSpinLockQueue_edx != 0)
jne label_owned ; goto label_owned
;
; else
or ecx, 2 ; pSpinLock_ecx
|= 2
mov dword ptr [eax+4], ecx ; *(&pSpinLockQueue_eax->Lock) = pSpinLock_ecx
jmp l_r ; return
label_owned:
or ecx, 1 ; pSpinLock_ecx
|= 1
mov dword ptr [eax+4], ecx ; *(&pSpinLockQueue_eax->Lock) = pSpinLock_ecx
mov dword ptr [edx], eax ; pSpinLockQueue_edx->Next = &pSpinLockQueue_eax
label_test:
;
test dword ptr [eax+4], 1
; while( *(&pSpinLockQueue_eax->Lock) & 1 )
je l_r ;
pause ;
jmp label_test ;
l_r:
pop edx
pop ecx
pop ebx
pop eax
jmp label_ret
}
label_ret:
return;
}
void
ReleaseQueuedSpinLock(PSPIN_LOCK_QUEUE pSpinLockQueue)
{
_asm
{
push eax
push ebx
push ecx
push edx
mov eax, pSpinLockQueue ; PSPIN_LOCK_QUEUE
pSpinLockQueue_eax
mov ebx, dword ptr [eax] ; PSPIN_LOCK_QUEUE
ebx = pSpinLockQueueNext
= pSpinLockQueue->Next
mov ecx, dword ptr [eax+4] ; PSPIN_LOCK
ecx = pSpinLock
= pSpinLockQueue->Lock
test ebx, ebx ;
btr ecx, 1 ; bit test and reset
;
(ecx & 1) -> CF
flag
;
clear bit 1
;
pSpinLock & 0xFFFFFFFE
;
pSpinLock & ~0x1
mov dword ptr [eax+4], ecx ; pSpinLockQueue->Lock = pSpinLock
jne l_1 ; if( pSpinLockQueueNext
!= 0 )
; goto l_1
push eax
lock cmpxchg dword ptr [ecx], ebx ; if( *(pSpinLock) == pSpinLockQueueNext )
; *(pSpinLock)
= pSpinLockQueueNext;
; <ZF
is set>
; goto
l_2;
;
else
; pSpinLockQueueNext
= *(pSpinLock);
pop eax ; return;
jne l_2
jmp la_ret
l_1:
xor dword ptr [ebx+4], 3 ; pSpinLockQueueNext->Lock ^= 3
mov dword ptr [eax], 0 ; pSpinLockQueue->Next = 0
jmp la_ret ; return
l_2:
mov ebx, dword ptr [eax]
; pSpinLockQueueNext = pSpinLockQueue->Next
test ebx, eax ; if( pSpinLockQueueNext
== NULL)
jne l_1 ; goto l_1;
pause ; else
jmp l_2 ; goto l_2;
la_ret:
pop edx
pop ecx
pop ebx
pop eax
jmp l_ret
}
l_ret:
return;
}
VOID
AcquireSpinLock(IN PSPIN_LOCK
SpinLock)
{
_asm
{
;lea
ecx, [ebp+8]
mov
ecx, SpinLock
label1:
; test
and set SpinLock, in multiprocessor environment
; lock
insures that the processor has exclusive use of
; any
shared memory
while the signal is asserted
lock
bts dword ptr[ecx], 0
; SpinLock
owned, wait
jc label2
; OK, acquired
;ret
jmp ll_ret;
label2:
; was
cleared?
test
dword ptr[ecx], 1
; yes,
SpinLock is free
jz label1
; no
pause
jmp
label2
}
ll_ret:
return;
}
VOID
ReleaseSpinLock(IN PSPIN_LOCK
SpinLock)
{
_asm
{
mov
ecx, SpinLock
lock
and dword ptr[ecx], 0
}
return;
}