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 include irqli386.inc .list EXTRNP _KeSetEventBoostPriority, 2 EXTRNP _KeWaitForSingleObject, 5 if DBG 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 CurrentIrql 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]+ThCombinedApcDisable, 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 jnz short afm10 ; The owner? No, go wait ; ; 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 afm10: inc dword ptr [ecx].FmContention ; increment contention count if DBG push eax endif push ecx add ecx, FmEvent ; wait for ownership event stdCall _KeWaitForSingleObject, ; pop ecx if DBG pop eax endif ; ; 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, afm21: stdCall _KeBugCheckEx, 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 CurrentIrql 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]+ThCombinedApcDisable, 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, ; set ownerhsip event fstRet ExReleaseFastMutexUnsafe ; return if DBG rfm20: stdCall _KeBugCheckEx, rfm_threaderror: stdCall _KeBugCheckEx, endif int 3 fstENDP ExReleaseFastMutexUnsafe _TEXT$00 ends end