238 lines
5.6 KiB
NASM
238 lines
5.6 KiB
NASM
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
|