|
|
TITLE "Fast Mutex Support" ;++ ; ; Copyright (c) 1994 Microsoft Corporation ; ; Module Name: ; ; fmutex.asm ; ; Abstract: ; ; This module implements teh code necessary to acquire and release fast ; mutexes without raising or lowering IRQL. ; ; Author: ; ; David N. Cutler (davec) 26-May-1994 ; ; Environment: ; ; Kernel mode only. ; ; Revision History: ; ;--
.386p .xlist include ks386.inc include callconv.inc ; calling convention macros include mac386.inc .list
EXTRNP _KeSetEventBoostPriority, 2 EXTRNP _KeWaitForSingleObject, 5 if DBG EXTRNP _KeGetCurrentIrql,0,IMPORT EXTRNP ___KeGetCurrentThread,0 EXTRNP _KeBugCheckEx,5 endif
ifdef NT_UP LOCK_ADD equ add LOCK_DEC equ dec else LOCK_ADD equ lock add LOCK_DEC equ lock dec endif
_TEXT$00 SEGMENT DWORD PUBLIC 'CODE' ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
;++ ; ; VOID ; FASTCALL ; ExAcquireFastMutexUnsafe ( ; IN PFAST_MUTEX FastMutex ; ) ; ; Routine description: ; ; This function acquires ownership of a fast mutex, but does not raise ; IRQL to APC level. ; ; Arguments: ; ; (ecx) = FastMutex - Supplies a pointer to a fast mutex. ; ; Return Value: ; ; None. ; ;--
cPublicFastCall ExAcquireFastMutexUnsafe,1 cPublicFpo 0,0
if DBG push ecx stdCall _KeGetCurrentIrql pop ecx ; ; Caller must already be at APC_LEVEL or have APCs blocked. ;
cmp al, APC_LEVEL mov eax,PCR[PcPrcbData+PbCurrentThread] ; grab the current thread 1st je short afm09 ; APCs disabled, this is ok
cmp dword ptr [eax]+ThKernelApcDisable, 0 jne short afm09 ; APCs disabled, this is ok
cmp dword ptr [eax]+ThTeb, 0 je short afm09 ; No TEB ==> system thread, this is ok
test dword ptr [eax]+ThTeb, 080000000h jnz short afm09 ; TEB in system space, this is ok
jmp short afm20 ; APCs not disabled --> fatal
afm09: cmp [ecx].FmOwner, eax ; Already owned by this thread? je short afm21 ; Yes, error
endif
LOCK_DEC dword ptr [ecx].FmCount ; decrement lock count jz short afm_ret ; The owner? Yes, Done
inc dword ptr [ecx].FmContention ; increment contention count
if DBG push eax endif push ecx add ecx, FmEvent ; wait for ownership event stdCall _KeWaitForSingleObject,<ecx,WrExecutive,0,0,0> ; pop ecx
if DBG pop eax endif
afm_ret:
; ; Leave a notion of owner behind. ; ; Note: if you change this, change ExAcquireFastMutex. ; if DBG mov [ecx].FmOwner, eax ; Save in Fast Mutex else ; ; Use esp to track the owning thread for debugging purposes. ; !thread from kd will find the owning thread. Note that the ; owner isn't cleared on release, check if the mutex is owned ; first. ;
mov [ecx].FmOwner, esp endif
fstRet ExAcquireFastMutexUnsafe ; return
if DBG afm20: stdCall _KeBugCheckEx,<IRQL_NOT_GREATER_OR_EQUAL,ecx,eax,039h,0> afm21: stdCall _KeBugCheckEx,<IRQL_NOT_GREATER_OR_EQUAL,ecx,eax,040h,0> endif
int 3
fstENDP ExAcquireFastMutexUnsafe
;++ ; ; VOID ; FASTCALL ; ExReleaseFastMutexUnsafe ( ; IN PFAST_MUTEX FastMutex ; ) ; ; Routine description: ; ; This function releases ownership of a fast mutex, and does not ; restore IRQL to its previous value. ; ; Arguments: ; ; (ecx) = FastMutex - Supplies a pointer to a fast mutex. ; ; Return Value: ; ; None. ; ;--
cPublicFastCall ExReleaseFastMutexUnsafe,1 cPublicFpo 0,0
if DBG push ecx stdCall _KeGetCurrentIrql pop ecx
; ; Caller must already be at APC_LEVEL or have APCs blocked. ;
cmp al, APC_LEVEL mov eax,PCR[PcPrcbData+PbCurrentThread] ; grab the current thread 1st je short rfm09 ; APCs disabled, this is ok
cmp dword ptr [eax]+ThKernelApcDisable, 0 jne short rfm09 ; APCs disabled, this is ok
cmp dword ptr [eax]+ThTeb, 0 je short rfm09 ; No TEB ==> system thread, this is ok
test dword ptr [eax]+ThTeb, 080000000h jnz short rfm09 ; TEB in system space, this is ok
jmp short rfm20 ; APCs not disabled --> fatal
rfm09: cmp [ecx].FmOwner, eax ; Owner == CurrentThread? jne short rfm_threaderror ; No, bugcheck
or byte ptr [ecx].FmOwner, 1 ; not the owner anymore endif
LOCK_ADD dword ptr [ecx].FmCount, 1 ; increment ownership count jng short rfm10 ; if ng, waiter present
fstRet ExReleaseFastMutexUnsafe ; return
rfm10: add ecx, FmEvent ; compute event address stdCall _KeSetEventBoostPriority,<ecx, 0> ; set ownerhsip event fstRet ExReleaseFastMutexUnsafe ; return
if DBG rfm20: stdCall _KeBugCheckEx,<IRQL_NOT_GREATER_OR_EQUAL,ecx,eax,03ah,0> rfm_threaderror: stdCall _KeBugCheckEx,<IRQL_NOT_GREATER_OR_EQUAL,ecx,eax,03bh,0> endif
int 3
fstENDP ExReleaseFastMutexUnsafe
_TEXT$00 ends
end
|