330 lines
7.1 KiB
PHP
330 lines
7.1 KiB
PHP
|
;++
|
||
|
;
|
||
|
; Copyright (c) 1989 Microsoft Corporation
|
||
|
;
|
||
|
; Module Name:
|
||
|
;
|
||
|
; mac386.inc - 386 machine specific assembler macros
|
||
|
;
|
||
|
; Abstract:
|
||
|
;
|
||
|
; This module contains 386 machine specific (assembler) macros
|
||
|
; applicable to code outside the kernel. Note that
|
||
|
; ACQUIRE_SPINLOCK_DIRECT assumes the PCR is handy, so it won't
|
||
|
; work in user mode (with debugging turned on.)
|
||
|
;
|
||
|
; Author:
|
||
|
;
|
||
|
; Bryan Willman (bryanwi) 1 Aug 90
|
||
|
;
|
||
|
|
||
|
;++
|
||
|
;
|
||
|
; YIELD
|
||
|
;
|
||
|
; Macro Description:
|
||
|
;
|
||
|
; This macro implements the yield instruction
|
||
|
;--
|
||
|
|
||
|
|
||
|
IFDEF _CAPKERN
|
||
|
extrn _CAP_Log_NInt:PROC
|
||
|
ENDIF
|
||
|
|
||
|
YIELD macro
|
||
|
ifndef NT_UP
|
||
|
db 0f3h
|
||
|
db 090h
|
||
|
endif
|
||
|
endm
|
||
|
|
||
|
|
||
|
if NT_INST
|
||
|
else
|
||
|
|
||
|
;++
|
||
|
;
|
||
|
; ACQUIRE_SPINLOCK LockAddress, SpinLabel
|
||
|
;
|
||
|
; Macro Description:
|
||
|
;
|
||
|
; This macro acquires a kernel spin lock.
|
||
|
;
|
||
|
; N.B. This macro assumes that the current IRQL is set properly.
|
||
|
; It neither raises nor lowers IRQL.
|
||
|
;
|
||
|
; Arguments:
|
||
|
;
|
||
|
; (KSPIN_LOCK) LockAddress - address of SpinLock value
|
||
|
; SpinLabel - if acquire spinlock fail, the label to perform the
|
||
|
; spin checking. It could be simply a "label" or
|
||
|
; "short label" which means the label is within 128
|
||
|
; bytes in distant.
|
||
|
;
|
||
|
; NoChecking - Not blank, if no debugging code should be generated.
|
||
|
;--
|
||
|
|
||
|
ACQUIRE_SPINLOCK macro LockAddress, SpinLabel, NoChecking
|
||
|
|
||
|
.errb <LockAddress>
|
||
|
.errb <SpinLabel>
|
||
|
|
||
|
ifndef NT_UP
|
||
|
|
||
|
;
|
||
|
; Attempt to assert the lock
|
||
|
;
|
||
|
|
||
|
ifdef CAPKERN_SYNCH_POINTS
|
||
|
push LockAddress
|
||
|
push 000010101h ; 1 Dword, Timestamp, Subcode = 1
|
||
|
call _CAP_Log_NInt
|
||
|
add esp, 8
|
||
|
endif
|
||
|
|
||
|
lock bts dword ptr [LockAddress], 0 ; test and set the spinlock
|
||
|
jc SpinLabel ; spinlock owned, go SpinLabe
|
||
|
|
||
|
if DBG
|
||
|
ifb <NoChecking>
|
||
|
push edi ; save edi
|
||
|
mov edi,fs:PcPrcb
|
||
|
mov edi, [edi].PbCurrentThread
|
||
|
or edi, 1 ; spinlock owned
|
||
|
mov [LockAddress], edi ; remember current thread
|
||
|
pop edi ; restore edi
|
||
|
endif ; NoChecking
|
||
|
endif ; DBG
|
||
|
endif ; NT_UP
|
||
|
|
||
|
endm
|
||
|
|
||
|
;++
|
||
|
;
|
||
|
; SPIN_ON_SPINLOCK LockAddress, AcquireLabel
|
||
|
;
|
||
|
; Macro Description:
|
||
|
;
|
||
|
; This macro spins on a kernel spin lock.
|
||
|
;
|
||
|
; N.B. This macro assumes that the current IRQL is set properly.
|
||
|
; It neither raises nor lowers IRQL.
|
||
|
;
|
||
|
; Arguments:
|
||
|
;
|
||
|
; (KSPIN_LOCK) LockAddress - address of a SpinLock value
|
||
|
;
|
||
|
; SpinLabel - if the test on cleared spinlock sucess, the label
|
||
|
; to assert the spin lock. It could be simply a
|
||
|
; "label" or "short label" which means the label is
|
||
|
; within 128 bytes in distance.
|
||
|
;
|
||
|
; NoChecking - Not blank, if no debugging code should be generated.
|
||
|
;--
|
||
|
|
||
|
SPIN_ON_SPINLOCK macro LockAddress, AcquireLabel, NoChecking, PollDebugger, NoTimeout
|
||
|
|
||
|
local a,b,flag ; define a local label
|
||
|
|
||
|
.errb <LockAddress>
|
||
|
.errb <AcquireLabel>
|
||
|
|
||
|
ifndef NT_UP
|
||
|
if DBG
|
||
|
|
||
|
EXTRNP Kii386SpinOnSpinLock,2
|
||
|
flag = 0
|
||
|
|
||
|
ifb <NoChecking>
|
||
|
flag = flag + 1
|
||
|
endif
|
||
|
|
||
|
ifnb <Polldebugger>
|
||
|
flag = flag + 2
|
||
|
endif
|
||
|
|
||
|
ifb <NoTimeout>
|
||
|
flag = flag + 4
|
||
|
endif
|
||
|
stdCall Kii386SpinOnSpinLock,<LockAddress,flag>
|
||
|
jmp AcquireLabel
|
||
|
|
||
|
else ; DBG
|
||
|
|
||
|
;
|
||
|
; Non-Debug version
|
||
|
;
|
||
|
|
||
|
ifdef CAPKERN_SYNCH_POINTS
|
||
|
|
||
|
push eax
|
||
|
push ebx
|
||
|
mov eax, LockAddress
|
||
|
xor ebx, ebx
|
||
|
a: inc ebx
|
||
|
test dword ptr [eax], 1 ; Was spinlock cleared?
|
||
|
jz short b ; Yes, go get it
|
||
|
YIELD
|
||
|
jmp short a
|
||
|
|
||
|
b:
|
||
|
push eax
|
||
|
push ebx
|
||
|
push 000020102h ; 2 Dwords, Timestamp, Subcode = 2
|
||
|
call _CAP_Log_NInt
|
||
|
add esp, 12
|
||
|
pop ebx
|
||
|
pop eax
|
||
|
jmp AcquireLabel
|
||
|
|
||
|
else
|
||
|
|
||
|
a: test dword ptr [LockAddress], 1 ; Was spinlock cleared?
|
||
|
jz AcquireLabel ; Yes, go get it
|
||
|
YIELD
|
||
|
jmp short a
|
||
|
|
||
|
endif
|
||
|
|
||
|
endif ; DBG
|
||
|
endif ; NT_UP
|
||
|
|
||
|
endm
|
||
|
|
||
|
|
||
|
;++
|
||
|
;
|
||
|
; TEST_SPINLOCK LockAddress, BusyLabel
|
||
|
;
|
||
|
; Macro Description:
|
||
|
;
|
||
|
; This macro tests a kernel spin lock to see if it's busy.
|
||
|
; If it's not busy, ACQUIRE_SPINLOCK still needs to be called
|
||
|
; to obtain the spinlock in a locked manner.
|
||
|
;
|
||
|
; Arguments:
|
||
|
;
|
||
|
; (KSPIN_LOCK) LockAddress - address of a SpinLock value
|
||
|
|
||
|
|
||
|
TEST_SPINLOCK macro LockAddress, BusyLabel
|
||
|
test dword ptr [LockAddress], 1 ; spinlock clear?
|
||
|
jnz BusyLabel ; No, then busy
|
||
|
endm
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
;++
|
||
|
;
|
||
|
; RELEASE_SPINLOCK LockAddress
|
||
|
;
|
||
|
; Macro Description:
|
||
|
;
|
||
|
; This macro releases a kernel spin lock.
|
||
|
;
|
||
|
; N.B. This macro assumes that the current IRQL is set properly.
|
||
|
; It neither raises nor lowers IRQL.
|
||
|
;
|
||
|
; Arguments:
|
||
|
;
|
||
|
; (KSPIN_LOCK) LockAddress - Supplies an address to a spin lock value
|
||
|
; NoChecking - Not blank, if no debugging code should be generated.
|
||
|
;--
|
||
|
|
||
|
RELEASE_SPINLOCK macro LockAddress, NoChecking
|
||
|
local a
|
||
|
.errb <LockAddress>
|
||
|
ifndef NT_UP
|
||
|
if DBG
|
||
|
ifb <NoChecking>
|
||
|
EXTRNP _KeBugCheckEx,5
|
||
|
|
||
|
push edi ; save edi
|
||
|
mov edi,fs:PcPrcb
|
||
|
mov edi,[edi].PbCurrentThread
|
||
|
or edi, 1 ; assume current thread owns the lock
|
||
|
cmp edi, [LockAddress] ; Does current thread own the lock?
|
||
|
pop edi ; restore edi
|
||
|
jz short a ; if z, yes, goto a and release lock
|
||
|
stdCall _KeBugCheckEx,<SPIN_LOCK_NOT_OWNED,LockAddress,0,0,0>
|
||
|
a:
|
||
|
endif
|
||
|
lock and dword ptr [LockAddress], 0
|
||
|
else
|
||
|
lock and byte ptr [LockAddress], 0
|
||
|
|
||
|
endif ; DBG
|
||
|
ifdef CAPKERN_SYNCH_POINTS
|
||
|
push LockAddress
|
||
|
push 000010107h ; 1 Dword, Timestamp, Subcode = 7
|
||
|
call _CAP_Log_NInt
|
||
|
add esp, 8
|
||
|
endif
|
||
|
endif ; NT_UP
|
||
|
endm
|
||
|
|
||
|
|
||
|
endif
|
||
|
if NT_INST
|
||
|
|
||
|
;
|
||
|
; These are the instrumentation version of the above functions.
|
||
|
; internal use only
|
||
|
;
|
||
|
|
||
|
ACQUIRE_SPINLOCK macro LockAddress, SpinLabel, NoChecking
|
||
|
EXTRNP KiInst_AcquireSpinLock,0
|
||
|
ifidni <&LockAddress>, <eax>
|
||
|
stdCall KiInst_AcquireSpinLock
|
||
|
else
|
||
|
push eax
|
||
|
mov eax, LockAddress
|
||
|
stdCall KiInst_AcquireSpinLock
|
||
|
pop eax
|
||
|
endif
|
||
|
jc SpinLabel
|
||
|
endm
|
||
|
|
||
|
SPIN_ON_SPINLOCK macro LockAddress, AcquireLabel, NoChecking, PollDebugger
|
||
|
EXTRNP KiInst_SpinOnSpinLock,0
|
||
|
ifidni <&LockAddress>, <eax>
|
||
|
stdCall KiInst_SpinOnSpinLock
|
||
|
else
|
||
|
push eax
|
||
|
mov eax, LockAddress
|
||
|
stdCall KiInst_SpinOnSpinLock
|
||
|
pop eax
|
||
|
endif
|
||
|
jmp AcquireLabel
|
||
|
endm
|
||
|
|
||
|
TEST_SPINLOCK macro LockAddress, BusyLabel
|
||
|
EXTRNP KiInst_TestSpinLock,0
|
||
|
ifidni <&LockAddress>, <eax>
|
||
|
stdCall KiInst_TestSpinLock
|
||
|
else
|
||
|
push eax
|
||
|
mov eax, LockAddress
|
||
|
stdCall KiInst_TestSpinLock
|
||
|
pop eax
|
||
|
endif
|
||
|
jnc AcquireLabel
|
||
|
endm
|
||
|
|
||
|
RELEASE_SPINLOCK macro LockAddress, NoChecking
|
||
|
EXTRNP KiInst_ReleaseSpinLock,0
|
||
|
ifidni <&LockAddress>, <eax>
|
||
|
stdCall KiInst_ReleaseSpinLock
|
||
|
else
|
||
|
push eax
|
||
|
mov eax, LockAddress
|
||
|
stdCall KiInst_ReleaseSpinLock
|
||
|
pop eax
|
||
|
endif
|
||
|
endm
|
||
|
|
||
|
endif
|
||
|
|