mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
737 lines
15 KiB
737 lines
15 KiB
// TITLE("Fast Mutex")
|
|
//++
|
|
//
|
|
// Copyright (c) 1995 Microsoft Corporation
|
|
//
|
|
// Module Name:
|
|
//
|
|
// mutexs.s
|
|
//
|
|
// Abstract:
|
|
//
|
|
// This code implements CompareAndSwap used for locking objects
|
|
//
|
|
// Author:
|
|
//
|
|
// 28-May-1995 -by- Mark Enstrom [marke]
|
|
//
|
|
// Environment:
|
|
//
|
|
// kernel mode
|
|
//
|
|
// Revision History:
|
|
//
|
|
//--
|
|
|
|
#include "ksppc.h"
|
|
#include "gdippc.h"
|
|
|
|
//SBTTL("InterlockedCompareAndSwap")
|
|
|
|
//*++
|
|
//
|
|
// BOOL
|
|
// HmgInterlockedCompareAndSwap(
|
|
// PULONG pDst,
|
|
// ULONG OldValue
|
|
// ULONG NewValue
|
|
// )
|
|
//
|
|
//Routine Description:
|
|
//
|
|
// This routine reads the value of memory at pDst, and if this is equal
|
|
// to OldValue, the memory location is assigned NewValue. This all
|
|
// happens under an interlock
|
|
//
|
|
//Arguments
|
|
//
|
|
// pDst - Destination memory location
|
|
// OldValue - Old value of memory must match this
|
|
// NewValue - New value written to memory if compare succedes
|
|
//
|
|
//Return Value
|
|
//
|
|
// TRUE if memory written, FALSE if not
|
|
//
|
|
//--*/
|
|
|
|
LEAF_ENTRY(HmgInterlockedCompareAndSwap)
|
|
|
|
lwarx r6,0,r3 // get current value
|
|
cmpw r6,r4 // check current value
|
|
bne- icasFail // if ne, skip stwcx and return FALSE
|
|
|
|
stwcx. r5,0,r3 // conditionally store lock value
|
|
bne- icasFail // if ne, store conditional failed
|
|
|
|
li r3,1 // success
|
|
blr // return
|
|
|
|
icasFail:
|
|
li r3,0 // failed
|
|
LEAF_EXIT(HmgInterlockedCompareAndSwap) // return
|
|
|
|
#if 0
|
|
//*++
|
|
//
|
|
// VOID
|
|
// IncrementShareedReferenceCount
|
|
// PULONG pDst,
|
|
// )
|
|
//
|
|
//Routine Description:
|
|
//
|
|
// Use an InterlockedCompareAndSwap to increment the shared reference
|
|
// count of the lock at pDst
|
|
//
|
|
//Arguments
|
|
//
|
|
// pDst - Pointer to Lock variable
|
|
//
|
|
//Return Value
|
|
//
|
|
// NONE, function must eventually increment lock value
|
|
//
|
|
//--*/
|
|
|
|
LEAF_ENTRY(HmgIncrementShareReferenceCount)
|
|
isrc:
|
|
lwz r4,0(r3) // read initial value
|
|
mr r5,r4 // make copy of lock variable
|
|
addi r4,r4,1 // increment shared ref count
|
|
rlwimi r4,r5,0,0xffff0000 // insert exc ref count
|
|
|
|
lwarx r6,0,r3 // get current value
|
|
cmpw r6,r5 // same as previous value?
|
|
bne- isrc // if not equal, repeat from original load
|
|
stwcx r4,0,r3 // conditionally store lock value
|
|
bne isrc // if eq, store conditional failed,
|
|
// repeat from initial load
|
|
|
|
LEAF_EXIT(HmgIncrementShareReferenceCount) // return
|
|
|
|
//*++
|
|
//
|
|
// VOID
|
|
// DecrementShareeReferenceCount
|
|
// PULONG pDst,
|
|
// )
|
|
//
|
|
//Routine Description:
|
|
//
|
|
// Use an InterlockedCompareAndSwap to decrement the shared reference
|
|
// count of the lock at pDst
|
|
//
|
|
//Arguments
|
|
//
|
|
// pDst - Pointer to Lock variable
|
|
//
|
|
//Return Value
|
|
//
|
|
// NONE, fundtion must eventually invrement lock value
|
|
//
|
|
//--*/
|
|
|
|
LEAF_ENTRY(HmgDecrementShareReferenceCount)
|
|
|
|
10:
|
|
lh t1,0(a0) // read initial value
|
|
lw t0,0(a0) // read old exc and share lock
|
|
sub t1,t1,1 // decrement shared ref count
|
|
and t1,t1,0x00007fff // mask low 16
|
|
and t2,t0,0xffff8000 // mask high 16
|
|
or t1,t1,t2 // combine exc count
|
|
|
|
//
|
|
// t0 = old lock count
|
|
// t1 = new lock count
|
|
//
|
|
|
|
ll t2,0(a0) // get current value
|
|
bne t2,t0,10b // if not equal, repeat from original load
|
|
|
|
sc t1,0(a0) // conditionally store lock value
|
|
beq zero,t1,10b // if eq, store conditional failed,
|
|
// repeat from initial load
|
|
j ra // return
|
|
|
|
.end HmgDecrementShareReferenceCount
|
|
|
|
//*++
|
|
//
|
|
// VOID
|
|
// HmgLockAsm
|
|
// HOBJ,
|
|
// OBJECT-TYPE,
|
|
// PID,
|
|
// TID
|
|
// )
|
|
//
|
|
//Routine Description:
|
|
//
|
|
// Acquire exclusive lock on object hobj
|
|
//
|
|
//Arguments
|
|
//
|
|
// a0 = handle
|
|
// a1 = objt
|
|
// a2 = CurrentPID
|
|
// a3 = CurrentTID
|
|
//
|
|
//Return Value
|
|
//
|
|
// NONE, fundtion must eventually invrement lock value
|
|
//
|
|
//--*/
|
|
|
|
|
|
SBTTL("HmgLockAsm")
|
|
|
|
NESTED_ENTRY(HmgLockAsm,HmFrameLength,zero)
|
|
|
|
subu sp,sp,HmFrameLength
|
|
|
|
PROLOGUE_END
|
|
|
|
//
|
|
// check index
|
|
//
|
|
|
|
la t1,gcMaxHmgr
|
|
lw t1,0(t1)
|
|
and t0,a0,INDEX_MASK
|
|
bgt t0,t1,HmgLockAsm_Bad_Index
|
|
|
|
//
|
|
// calc entry address
|
|
//
|
|
|
|
la t1,gpentHmgr
|
|
lw t1,0(t1)
|
|
sll t2,t0,4
|
|
add t1,t1,t2
|
|
|
|
HmgLockAsm_StartCompare:
|
|
|
|
lw v0,entry_ObjectOwner(t1)
|
|
|
|
//
|
|
// compare PID for public
|
|
//
|
|
|
|
srl t2,v0,16
|
|
beq t2,OBJECT_OWNER_PUBLIC,10f
|
|
|
|
//
|
|
// compare PID
|
|
//
|
|
|
|
bne t2,a2,HmgLockAsm_BadPID
|
|
10:
|
|
|
|
//
|
|
// check handle lock
|
|
//
|
|
|
|
sll t2,v0,16
|
|
bltz t2,HmgLockAsm_Wait
|
|
|
|
//
|
|
// set lock bit and do compare_and_swap
|
|
//
|
|
|
|
or v1,v0,zero
|
|
or v1,0x00008000
|
|
|
|
.set noreorder
|
|
|
|
ll t3,entry_ObjectOwner(t1)
|
|
bne t3,v0, HmgLockAsm_StartCompare
|
|
nop
|
|
sc v1,entry_ObjectOwner(t1)
|
|
beq v1,zero,HmgLockAsm_StartCompare
|
|
nop
|
|
|
|
.set reorder
|
|
|
|
//
|
|
// check objt and unique
|
|
//
|
|
|
|
lbu t3,entry_Objt(t1)
|
|
bne t3,a1,HmgLockAsm_BadObjt
|
|
|
|
lhu t3,entry_FullUnique(t1)
|
|
srl t4,a0,16
|
|
bne t3,t4,HmgLockAsm_Unique
|
|
|
|
//
|
|
// load entry
|
|
//
|
|
|
|
lw t5,entry_einfo(t1)
|
|
|
|
//
|
|
// check exclusive
|
|
//
|
|
|
|
lw t3,object_cExclusiveLock(t5)
|
|
|
|
beq t3,zero,10f
|
|
lw t4,object_Tid(t5)
|
|
bne t4,a3,HmgLockAsm_BadTid
|
|
10:
|
|
//
|
|
// inc exclusive count and set Tid
|
|
//
|
|
|
|
add t3,t3,1
|
|
sw t3,object_cExclusiveLock(t5)
|
|
sw a3,object_Tid(t5)
|
|
|
|
//
|
|
// unlockHandle
|
|
//
|
|
|
|
sw v0,entry_ObjectOwner(t1)
|
|
or v0,t5,zero
|
|
addu sp,sp,HmFrameLength
|
|
j ra
|
|
|
|
HmgLockAsm_BadTid:
|
|
HmgLockAsm_BadObjt:
|
|
HmgLockAsm_Unique:
|
|
|
|
//
|
|
// unlock handle
|
|
//
|
|
|
|
sw v0,entry_ObjectOwner(t1)
|
|
|
|
HmgLockAsm_Bad_Index:
|
|
HmgLockAsm_BadPID:
|
|
|
|
or v0,zero,zero
|
|
addu sp,sp,HmFrameLength
|
|
j ra
|
|
|
|
HmgLockAsm_Wait:
|
|
|
|
//
|
|
// handle locked, sleep then try again
|
|
//
|
|
// BUGBUG: CALL NtDelayExecutionThread (ohoh)
|
|
// Must save and restore registers
|
|
//
|
|
|
|
sw ra,HmRa(sp)
|
|
sw v0,HmV0(sp)
|
|
sw v1,HmV1(sp)
|
|
sw t0,HmT0(sp)
|
|
sw t1,HmT1(sp)
|
|
sw t2,HmT2(sp)
|
|
sw t3,HmT3(sp)
|
|
sw t4,HmT4(sp)
|
|
sw t5,HmT5(sp)
|
|
sw a0,HmA0(sp)
|
|
sw a1,HmA1(sp)
|
|
sw a2,HmA2(sp)
|
|
sw a3,HmA3(sp)
|
|
|
|
la a2,HmDelay(sp)
|
|
sw zero,0(a2)
|
|
li t0,0xa96
|
|
sw t0,4(a2)
|
|
or a0,zero,zero
|
|
or a1,zero,zero
|
|
jal KeDelayExecutionThread
|
|
|
|
lw ra,HmRa(sp)
|
|
lw v0,HmV0(sp)
|
|
lw v1,HmV1(sp)
|
|
lw t0,HmT0(sp)
|
|
lw t1,HmT1(sp)
|
|
lw t2,HmT2(sp)
|
|
lw t3,HmT3(sp)
|
|
lw t4,HmT4(sp)
|
|
lw t5,HmT5(sp)
|
|
lw a0,HmA0(sp)
|
|
lw a1,HmA1(sp)
|
|
lw a2,HmA2(sp)
|
|
lw a3,HmA3(sp)
|
|
|
|
beq zero,zero,HmgLockAsm_StartCompare
|
|
|
|
.end HmgLockAsm
|
|
|
|
//*++
|
|
//
|
|
// VOID
|
|
// HmgShareCheckLockAsm
|
|
// HOBJ,
|
|
// OBJECT-TYPE,
|
|
// PID,
|
|
// TID
|
|
// )
|
|
//
|
|
//Routine Description:
|
|
//
|
|
// Acquire shared lock on object hobj, PID must be checked
|
|
//
|
|
//Arguments
|
|
//
|
|
// a0 = handle
|
|
// a1 = objt
|
|
// a2 = CurrentPID
|
|
//
|
|
//Return Value
|
|
//
|
|
// NONE, fundtion must eventually invrement lock value
|
|
//
|
|
//--*/
|
|
|
|
|
|
SBTTL("HmgLockAsm")
|
|
|
|
NESTED_ENTRY(HmgShareCheckLockAsm,HmFrameLength,zero)
|
|
|
|
subu sp,sp,HmFrameLength
|
|
|
|
PROLOGUE_END
|
|
|
|
//
|
|
// check index
|
|
//
|
|
|
|
la t1,gcMaxHmgr
|
|
lw t1,0(t1)
|
|
and t0,a0,INDEX_MASK
|
|
bgt t0,t1,HmgShareCheckLockAsm_Bad_Index
|
|
|
|
//
|
|
// calc entry address
|
|
//
|
|
|
|
la t1,gpentHmgr
|
|
lw t1,0(t1)
|
|
sll t2,t0,4
|
|
add t1,t1,t2
|
|
|
|
HmgShareCheckLockAsm_StartCompare:
|
|
|
|
lw v0,entry_ObjectOwner(t1)
|
|
|
|
//
|
|
// compare PID for public
|
|
//
|
|
|
|
srl t2,v0,16
|
|
beq t2,OBJECT_OWNER_PUBLIC,10f
|
|
|
|
//
|
|
// compare PID
|
|
//
|
|
|
|
bne t2,a2,HmgShareCheckLockAsm_BadPID
|
|
10:
|
|
|
|
//
|
|
// check handle lock
|
|
//
|
|
|
|
sll t2,v0,16
|
|
bltz t2,HmgShareCheckLockAsm_Wait
|
|
|
|
//
|
|
// set lock bit and do compare_and_swap
|
|
//
|
|
|
|
or v1,v0,zero
|
|
or v1,0x00008000
|
|
|
|
.set noreorder
|
|
|
|
ll t3,entry_ObjectOwner(t1)
|
|
bne t3,v0, HmgShareCheckLockAsm_StartCompare
|
|
nop
|
|
sc v1,entry_ObjectOwner(t1)
|
|
beq v1,zero,HmgShareCheckLockAsm_StartCompare
|
|
nop
|
|
|
|
.set reorder
|
|
|
|
//
|
|
// check objt and unique
|
|
//
|
|
|
|
lbu t3,entry_Objt(t1)
|
|
bne t3,a1,HmgShareCheckLockAsm_BadObjt
|
|
|
|
lhu t3,entry_FullUnique(t1)
|
|
srl t4,a0,16
|
|
bne t3,t4,HmgShareCheckLockAsm_Unique
|
|
|
|
//
|
|
// load entry
|
|
//
|
|
|
|
lw t5,entry_einfo(t1)
|
|
|
|
//
|
|
// inc Share count (v0) (assumes share count >=0 and < 0x7fff)
|
|
//
|
|
|
|
add v0,v0,1
|
|
|
|
//
|
|
// unlockHandle
|
|
//
|
|
|
|
sw v0,entry_ObjectOwner(t1)
|
|
or v0,t5,zero
|
|
addu sp,sp,HmFrameLength
|
|
j ra
|
|
|
|
HmgShareCheckLockAsm_BadObjt:
|
|
HmgShareCheckLockAsm_Unique:
|
|
|
|
//
|
|
// unlock handle
|
|
//
|
|
|
|
sw v0,entry_ObjectOwner(t1)
|
|
|
|
HmgShareCheckLockAsm_Bad_Index:
|
|
HmgShareCheckLockAsm_BadPID:
|
|
|
|
or v0,zero,zero
|
|
addu sp,sp,HmFrameLength
|
|
j ra
|
|
|
|
HmgShareCheckLockAsm_Wait:
|
|
|
|
//
|
|
// handle locked, sleep then try again
|
|
//
|
|
// BUGBUG: CALL NtDelayExecutionThread (ohoh)
|
|
// Must save and restore registers
|
|
//
|
|
|
|
sw ra,HmRa(sp)
|
|
sw v0,HmV0(sp)
|
|
sw v1,HmV1(sp)
|
|
sw t0,HmT0(sp)
|
|
sw t1,HmT1(sp)
|
|
sw t2,HmT2(sp)
|
|
sw t3,HmT3(sp)
|
|
sw t4,HmT4(sp)
|
|
sw t5,HmT5(sp)
|
|
sw a0,HmA0(sp)
|
|
sw a1,HmA1(sp)
|
|
sw a2,HmA2(sp)
|
|
sw a3,HmA3(sp)
|
|
|
|
la a2,HmDelay(sp)
|
|
sw zero,0(a2)
|
|
li t0,0xa96
|
|
sw t0,4(a2)
|
|
or a0,zero,zero
|
|
or a1,zero,zero
|
|
jal KeDelayExecutionThread
|
|
|
|
lw ra,HmRa(sp)
|
|
lw v0,HmV0(sp)
|
|
lw v1,HmV1(sp)
|
|
lw t0,HmT0(sp)
|
|
lw t1,HmT1(sp)
|
|
lw t2,HmT2(sp)
|
|
lw t3,HmT3(sp)
|
|
lw t4,HmT4(sp)
|
|
lw t5,HmT5(sp)
|
|
lw a0,HmA0(sp)
|
|
lw a1,HmA1(sp)
|
|
lw a2,HmA2(sp)
|
|
lw a3,HmA3(sp)
|
|
|
|
beq zero,zero,HmgShareCheckLockAsm_StartCompare
|
|
|
|
.end HmgShareCheckLockAsm
|
|
|
|
//*++
|
|
//
|
|
// VOID
|
|
// HmgShareLockAsm
|
|
// HOBJ,
|
|
// OBJECT-TYPE,
|
|
// PID,
|
|
// TID
|
|
// )
|
|
//
|
|
//Routine Description:
|
|
//
|
|
// Acquire shared lock on object hobj
|
|
//
|
|
//Arguments
|
|
//
|
|
// a0 = handle
|
|
// a1 = objt
|
|
//
|
|
//Return Value
|
|
//
|
|
// NONE, fundtion must eventually invrement lock value
|
|
//
|
|
//--*/
|
|
|
|
|
|
SBTTL("HmgLockAsm")
|
|
|
|
NESTED_ENTRY(HmgShareLockAsm,HmFrameLength,zero)
|
|
|
|
subu sp,sp,HmFrameLength
|
|
|
|
PROLOGUE_END
|
|
|
|
//
|
|
// check index
|
|
//
|
|
|
|
la t1,gcMaxHmgr
|
|
lw t1,0(t1)
|
|
and t0,a0,INDEX_MASK
|
|
bgt t0,t1,HmgShareLockAsm_Bad_Index
|
|
|
|
//
|
|
// calc entry address
|
|
//
|
|
|
|
la t1,gpentHmgr
|
|
lw t1,0(t1)
|
|
sll t2,t0,4
|
|
add t1,t1,t2
|
|
|
|
HmgShareLockAsm_StartCompare:
|
|
|
|
lw v0,entry_ObjectOwner(t1)
|
|
|
|
//
|
|
// check handle lock
|
|
//
|
|
|
|
sll t2,v0,16
|
|
bltz t2,HmgShareLockAsm_Wait
|
|
|
|
//
|
|
// set lock bit and do compare_and_swap
|
|
//
|
|
|
|
or v1,v0,zero
|
|
or v1,0x00008000
|
|
|
|
.set noreorder
|
|
|
|
ll t3,entry_ObjectOwner(t1)
|
|
bne t3,v0, HmgShareLockAsm_StartCompare
|
|
nop
|
|
sc v1,entry_ObjectOwner(t1)
|
|
beq v1,zero,HmgShareLockAsm_StartCompare
|
|
nop
|
|
|
|
.set reorder
|
|
|
|
//
|
|
// check objt and unique
|
|
//
|
|
|
|
lbu t3,entry_Objt(t1)
|
|
bne t3,a1,HmgShareLockAsm_BadObjt
|
|
|
|
lhu t3,entry_FullUnique(t1)
|
|
srl t4,a0,16
|
|
bne t3,t4,HmgShareLockAsm_Unique
|
|
|
|
//
|
|
// load entry
|
|
//
|
|
|
|
lw t5,entry_einfo(t1)
|
|
|
|
//
|
|
// inc Share count (v0) (assumes share count >=0 and < 0x7fff)
|
|
//
|
|
|
|
add v0,v0,1
|
|
|
|
//
|
|
// unlockHandle
|
|
//
|
|
|
|
sw v0,entry_ObjectOwner(t1)
|
|
or v0,t5,zero
|
|
addu sp,sp,HmFrameLength
|
|
j ra
|
|
|
|
HmgShareLockAsm_BadObjt:
|
|
HmgShareLockAsm_Unique:
|
|
|
|
//
|
|
// unlock handle
|
|
//
|
|
|
|
sw v0,entry_ObjectOwner(t1)
|
|
|
|
HmgShareLockAsm_Bad_Index:
|
|
HmgShareLockAsm_BadPID:
|
|
|
|
or v0,zero,zero
|
|
addu sp,sp,HmFrameLength
|
|
j ra
|
|
|
|
HmgShareLockAsm_Wait:
|
|
|
|
//
|
|
// handle locked, sleep then try again
|
|
//
|
|
// BUGBUG: CALL NtDelayExecutionThread (ohoh)
|
|
// Must save and restore registers
|
|
//
|
|
|
|
sw ra,HmRa(sp)
|
|
sw v0,HmV0(sp)
|
|
sw v1,HmV1(sp)
|
|
sw t0,HmT0(sp)
|
|
sw t1,HmT1(sp)
|
|
sw t2,HmT2(sp)
|
|
sw t3,HmT3(sp)
|
|
sw t4,HmT4(sp)
|
|
sw t5,HmT5(sp)
|
|
sw a0,HmA0(sp)
|
|
sw a1,HmA1(sp)
|
|
sw a2,HmA2(sp)
|
|
sw a3,HmA3(sp)
|
|
|
|
la a2,HmDelay(sp)
|
|
sw zero,0(a2)
|
|
li t0,0xa96
|
|
sw t0,4(a2)
|
|
or a0,zero,zero
|
|
or a1,zero,zero
|
|
jal KeDelayExecutionThread
|
|
|
|
lw ra,HmRa(sp)
|
|
lw v0,HmV0(sp)
|
|
lw v1,HmV1(sp)
|
|
lw t0,HmT0(sp)
|
|
lw t1,HmT1(sp)
|
|
lw t2,HmT2(sp)
|
|
lw t3,HmT3(sp)
|
|
lw t4,HmT4(sp)
|
|
lw t5,HmT5(sp)
|
|
lw a0,HmA0(sp)
|
|
lw a1,HmA1(sp)
|
|
lw a2,HmA2(sp)
|
|
lw a3,HmA3(sp)
|
|
|
|
beq zero,zero,HmgShareLockAsm_StartCompare
|
|
|
|
.end HmgShareLockAsm
|
|
#endif
|