summaryrefslogtreecommitdiffstats
path: root/private/ntos/nthals/halx86/i386/ixlock.asm
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/nthals/halx86/i386/ixlock.asm
downloadNT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip
Diffstat (limited to 'private/ntos/nthals/halx86/i386/ixlock.asm')
-rw-r--r--private/ntos/nthals/halx86/i386/ixlock.asm475
1 files changed, 475 insertions, 0 deletions
diff --git a/private/ntos/nthals/halx86/i386/ixlock.asm b/private/ntos/nthals/halx86/i386/ixlock.asm
new file mode 100644
index 000000000..98cf9c425
--- /dev/null
+++ b/private/ntos/nthals/halx86/i386/ixlock.asm
@@ -0,0 +1,475 @@
+ title "Irql Processing"
+;++
+;
+; Copyright (c) 1989 Microsoft Corporation
+;
+; Module Name:
+;
+; ixlock.asm
+;
+; Abstract:
+;
+; This module implements various locking functions optimized for this hal.
+;
+; Author:
+;
+; Ken Reneris (kenr) 21-April-1994
+;
+; Environment:
+;
+; Kernel mode only.
+;
+; Revision History:
+;
+;--
+
+.386p
+ .xlist
+include hal386.inc
+include callconv.inc ; calling convention macros
+include i386\ix8259.inc
+include i386\kimacro.inc
+include mac386.inc
+ .list
+
+ EXTRNP _KeBugCheck,1,IMPORT
+ EXTRNP _KeSetEventBoostPriority, 2, IMPORT
+ EXTRNP _KeWaitForSingleObject,5, IMPORT
+
+ extrn FindHigherIrqlMask:DWORD
+ extrn SWInterruptHandlerTable:DWORD
+
+ EXTRNP _KeRaiseIrql,2
+ EXTRNP _KeLowerIrql,1
+
+ifdef NT_UP
+ LOCK_ADD equ add
+ LOCK_DEC equ dec
+else
+ LOCK_ADD equ lock add
+ LOCK_DEC equ lock dec
+endif
+
+ page ,132
+ subttl "AcquireSpinLock"
+
+_TEXT$01 SEGMENT PARA PUBLIC 'CODE'
+ ASSUME DS:FLAT, ES:FLAT, SS:FLAT, FS:NOTHING, GS:NOTHING
+
+;++
+;
+; KIRQL
+; KfAcquireSpinLock (
+; IN PKSPIN_LOCK SpinLock
+; )
+;
+; Routine Description:
+;
+; This function raises to DISPATCH_LEVEL and then acquires a the
+; kernel spin lock.
+;
+; In a UP hal spinlock serialization is accomplished by raising the
+; IRQL to DISPATCH_LEVEL. The SpinLock is not used; however, for
+; debugging purposes if the UP hal is compiled with the NT_UP flag
+; not set (ie, MP) we take the SpinLock.
+;
+; Arguments:
+;
+; (ecx) = SpinLock Supplies a pointer to an kernel spin lock.
+;
+; Return Value:
+;
+; OldIrql
+;
+;--
+
+cPublicFastCall KfAcquireSpinLock,1
+cPublicFpo 0,0
+
+ xor eax, eax ; Eliminate partial stall on return to caller
+ mov al, PCR[PcIrql] ; (al) = Old Irql
+ mov byte ptr PCR[PcIrql], DISPATCH_LEVEL ; set new irql
+
+ifndef NT_UP
+asl10: ACQUIRE_SPINLOCK ecx,<short asl20>
+endif
+
+ifdef IRQL_METRICS
+ inc HalRaiseIrqlCount
+endif
+if DBG
+ cmp al, DISPATCH_LEVEL ; old > new?
+ ja short asl99 ; yes, go bugcheck
+endif
+ fstRET KfAcquireSpinLock
+
+ifndef NT_UP
+asl20: SPIN_ON_SPINLOCK ecx,<short asl10>
+endif
+
+if DBG
+cPublicFpo 2,1
+asl99: movzx eax, al
+ push eax ; put old irql where we can find it
+ stdCall _KeBugCheck, <IRQL_NOT_GREATER_OR_EQUAL> ; never return
+endif
+ fstRET KfAcquireSpinLock
+fstENDP KfAcquireSpinLock
+
+;++
+;
+; KIRQL
+; KeAcquireSpinLockRaiseToSynch (
+; IN PKSPIN_LOCK SpinLock
+; )
+;
+; Routine Description:
+;
+; This function acquires the SpinLock at SYNCH_LEVEL. The function
+; is optmized for hoter locks (the lock is tested before acquired.
+; Any spin should occur at OldIrql; however, since this is a UP hal
+; we don't have the code for it)
+;
+; In a UP hal spinlock serialization is accomplished by raising the
+; IRQL to SYNCH_LEVEL. The SpinLock is not used; however, for
+; debugging purposes if the UP hal is compiled with the NT_UP flag
+; not set (ie, MP) we take the SpinLock.
+;
+; Arguments:
+;
+; (ecx) = SpinLock Supplies a pointer to an kernel spin lock.
+;
+; Return Value:
+;
+; OldIrql
+;
+;--
+
+cPublicFastCall KeAcquireSpinLockRaiseToSynch,1
+cPublicFpo 0,0
+
+ mov al, PCR[PcIrql] ; (al) = Old Irql
+ mov byte ptr PCR[PcIrql], SYNCH_LEVEL ; set new irql
+
+ifndef NT_UP
+asls10: ACQUIRE_SPINLOCK ecx,<short asls20>
+endif
+
+ifdef IRQL_METRICS
+ inc HalRaiseIrqlCount
+endif
+if DBG
+ cmp al, SYNCH_LEVEL ; old > new?
+ ja short asls99 ; yes, go bugcheck
+endif
+ fstRET KeAcquireSpinLockRaiseToSynch
+
+ifndef NT_UP
+asls20: SPIN_ON_SPINLOCK ecx,<short asls10>
+endif
+
+if DBG
+cPublicFpo 2,1
+asls99: movzx eax, al
+ push eax ; put old irql where we can find it
+ stdCall _KeBugCheck, <IRQL_NOT_GREATER_OR_EQUAL> ; never return
+endif
+ fstRET KeAcquireSpinLockRaiseToSynch
+fstENDP KeAcquireSpinLockRaiseToSynch
+
+ PAGE
+ SUBTTL "Release Kernel Spin Lock"
+
+;++
+;
+; VOID
+; KfReleaseSpinLock (
+; IN PKSPIN_LOCK SpinLock,
+; IN KIRQL NewIrql
+; )
+;
+; Routine Description:
+;
+; This function releases a kernel spin lock and lowers to the new irql
+;
+; In a UP hal spinlock serialization is accomplished by raising the
+; IRQL to DISPATCH_LEVEL. The SpinLock is not used; however, for
+; debugging purposes if the UP hal is compiled with the NT_UP flag
+; not set (ie, MP) we use the SpinLock.
+;
+; Arguments:
+;
+; (ecx) = SpinLock Supplies a pointer to an executive spin lock.
+; (dl) = NewIrql New irql value to set
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+align 16
+cPublicFastCall KfReleaseSpinLock ,2
+cPublicFpo 0,0
+ifndef NT_UP
+ RELEASE_SPINLOCK ecx ; release it
+endif
+ xor ecx, ecx
+if DBG
+ cmp dl, PCR[PcIrql]
+ ja short rsl99
+endif
+ pushfd
+ cli
+ mov PCR[PcIrql], dl ; store old irql
+ mov cl, dl ; (ecx) = 32bit extended OldIrql
+ mov edx, PCR[PcIRR]
+ and edx, FindHigherIrqlMask[ecx*4] ; (edx) is the bitmask of
+ ; pending interrupts we need to
+ jne short rsl20 ; dispatch now.
+
+ popfd
+ fstRet KfReleaseSpinLock ; all done
+
+if DBG
+rsl99: stdCall _KeBugCheck, <IRQL_NOT_LESS_OR_EQUAL> ; never return
+endif
+
+cPublicFpo 0,1
+rsl20: bsr ecx, edx ; (ecx) = Pending irq level
+ cmp ecx, DISPATCH_LEVEL
+ jle short rsl40
+
+ mov eax, PCR[PcIDR] ; Clear all the interrupt
+ SET_8259_MASK ; masks
+rsl40:
+ mov edx, 1
+ shl edx, cl
+ xor PCR[PcIRR], edx ; clear bit in IRR
+ call SWInterruptHandlerTable[ecx*4] ; Dispatch the pending int.
+ popfd
+
+cPublicFpo 0, 0
+ fstRet KfReleaseSpinLock ; all done
+
+fstENDP KfReleaseSpinLock
+
+;++
+;
+; VOID
+; FASTCALL
+; ExAcquireFastMutex (
+; IN PFAST_MUTEX FastMutex
+; )
+;
+; Routine description:
+;
+; This function acquire ownership of the FastMutex
+;
+; Arguments:
+;
+; (ecx) = FastMutex - Supplies a pointer to the fast mutex
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+cPublicFastCall ExAcquireFastMutex,1
+cPublicFpo 0,0
+ mov al, PCR[PcIrql] ; (cl) = OldIrql
+if DBG
+ cmp al, APC_LEVEL ; Is OldIrql > NewIrql?
+ ja short afm99 ; Yes, bugcheck
+
+ mov edx, PCR[PcPrcb]
+ mov edx, [edx].PbCurrentThread ; (edx) = Current Thread
+ cmp [ecx].FmOwner, edx ; Already owned by this thread?
+ je short afm98 ; Yes, error
+endif
+
+ mov byte ptr PCR[PcIrql], APC_LEVEL ; Set NewIrql
+ LOCK_DEC dword ptr [ecx].FmCount ; Get count
+ jz short afm_ret ; The owner? Yes, Done
+
+ inc dword ptr [ecx].FmContention
+
+cPublicFpo 0,2
+ push eax ; save OldIrql
+ push ecx ; Save FAST_MUTEX
+ add ecx, FmEvent ; Wait on Event
+
+ stdCall _KeWaitForSingleObject,<ecx,WrExecutive,0,0,0>
+
+ pop ecx ; (ecx) = FAST_MUTEX
+ pop eax ; (al) = OldIrql
+
+cPublicFpo 1,0
+afm_ret:
+
+if DBG
+ cli
+ mov edx, PCR[PcPrcb]
+ mov edx, [edx].PbCurrentThread ; (edx) = Current Thread
+ sti
+ mov [ecx].FmOwner, edx ; Save in Fast Mutex
+endif
+ mov byte ptr [ecx].FmOldIrql, al
+ fstRet ExAcquireFastMutex
+
+if DBG
+afm98: stdCall _KeBugCheck, <eax> ; never return
+afm99: stdCall _KeBugCheck, <IRQL_NOT_LESS_OR_EQUAL> ; never return
+ fstRet ExAcquireFastMutex
+endif
+
+fstENDP ExAcquireFastMutex
+
+
+;++
+;
+; VOID
+; FASTCALL
+; ExReleaseFastMutex (
+; IN PFAST_MUTEX FastMutex
+; )
+;
+; Routine description:
+;
+; This function releases ownership of the FastMutex
+;
+; Arguments:
+;
+; (ecx) = FastMutex - Supplies a pointer to the fast mutex
+;
+; Return Value:
+;
+; None.
+;
+;--
+
+cPublicFastCall ExReleaseFastMutex,1
+cPublicFpo 0,0
+ xor eax, eax
+if DBG
+ cli
+ mov edx, PCR[PcPrcb]
+ mov edx, [edx].PbCurrentThread ; (edx) = CurrentThread
+ sti
+ cmp [ecx].FmOwner, edx ; Owner == CurrentThread?
+ jne short rfm_threaderror ; No, bugcheck
+endif
+ or byte ptr [ecx].FmOwner, 1 ; not the owner anymore
+
+ mov al, byte ptr [ecx].FmOldIrql ; (eax) = OldIrql
+ LOCK_ADD dword ptr [ecx].FmCount, 1 ; Remove our count
+ js short rfm05 ; if < 0, set event
+ jnz short rfm10 ; if != 0, don't set event
+
+rfm05:
+cPublicFpo 0,2
+ push eax ; Save OldIrql
+ add ecx, FmEvent
+ stdCall _KeSetEventBoostPriority, <ecx, 0>
+ pop eax
+
+cPublicFpo 0,0
+rfm10:
+ cli
+ mov PCR[PcIrql], eax
+ mov edx, PCR[PcIRR]
+ and edx, FindHigherIrqlMask[eax*4] ; (edx) is the bitmask of
+ ; pending interrupts we need to
+ jne short rfm20 ; dispatch now.
+
+ sti
+ fstRet ExReleaseFastMutex ; all done
+if DBG
+rfm_threaderror:
+ stdCall _KeBugCheck, <eax>
+endif
+
+rfm20: bsr ecx, edx ; (ecx) = Pending irq level
+ cmp ecx, DISPATCH_LEVEL
+ jle short rfm40
+
+ mov eax, PCR[PcIDR] ; Clear all the interrupt
+ SET_8259_MASK ; masks
+rfm40:
+ mov edx, 1
+ shl edx, cl
+ xor PCR[PcIRR], edx ; clear bit in IRR
+ call SWInterruptHandlerTable[ecx*4] ; Dispatch the pending int.
+ sti
+ fstRet ExReleaseFastMutex ; all done
+fstENDP ExReleaseFastMutex
+
+;++
+;
+; BOOLEAN
+; FASTCALL
+; ExTryToAcquireFastMutex (
+; IN PFAST_MUTEX FastMutex
+; )
+;
+; Routine description:
+;
+; This function acquire ownership of the FastMutex
+;
+; Arguments:
+;
+; (ecx) = FastMutex - Supplies a pointer to the fast mutex
+;
+; Return Value:
+;
+; Returns TRUE if the FAST_MUTEX was acquired; otherwise false
+;
+;--
+
+cPublicFastCall ExTryToAcquireFastMutex,1
+cPublicFpo 0,0
+ mov al, PCR[PcIrql] ; (al) = OldIrql
+
+if DBG
+ cmp al, APC_LEVEL ; Is OldIrql > NewIrql?
+ ja short tam99 ; Yes, bugcheck
+endif
+
+;
+; Try to acquire - but needs to support 386s.
+; *** Warning: This code is NOT MP safe ***
+; But, we know that this hal really only runs on UP machines
+;
+ cli
+ cmp dword ptr [ecx].FmCount, 1 ; Busy?
+ jne short tam20 ; Yes, abort
+
+ mov dword ptr [ecx].FmCount, 0 ; acquire count
+
+if DBG
+ mov edx, PCR[PcPrcb]
+ mov edx, [edx].PbCurrentThread ; (edx) = Current Thread
+ mov [ecx].FmOwner, edx ; Save in Fast Mutex
+endif
+ mov PCR[PcIrql], APC_LEVEL
+ sti
+ mov byte ptr [ecx].FmOldIrql, al
+ mov eax, 1 ; return TRUE
+ fstRet ExTryToAcquireFastMutex
+
+tam20: sti
+ xor eax, eax ; return FALSE
+ fstRet ExTryToAcquireFastMutex ; all done
+
+if DBG
+tam99: stdCall _KeBugCheck, <IRQL_NOT_LESS_OR_EQUAL> ; never return
+ xor eax, eax ; return FALSE
+ fstRet ExTryToAcquireFastMutex
+endif
+
+fstENDP ExTryToAcquireFastMutex
+
+_TEXT$01 ends
+
+ end