windows-nt/Source/XPSP1/NT/base/ntos/ex/i386/fmutex.asm
2020-09-26 16:20:57 +08:00

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