467 lines
15 KiB
ArmAsm
467 lines
15 KiB
ArmAsm
|
// TITLE("Fast Mutex Support")
|
|||
|
//++
|
|||
|
//
|
|||
|
// Copyright (c) 1994 Microsoft Corporation
|
|||
|
//
|
|||
|
// Module Name:
|
|||
|
//
|
|||
|
// fmutex.s
|
|||
|
//
|
|||
|
// Abstract:
|
|||
|
//
|
|||
|
// This module implements the code necessary to acquire and release fast
|
|||
|
// mutxes.
|
|||
|
//
|
|||
|
//
|
|||
|
// Author:
|
|||
|
//
|
|||
|
// David N. Cutler (davec) 13-Apr-1994
|
|||
|
//
|
|||
|
// Environment:
|
|||
|
//
|
|||
|
// Kernel mode only.
|
|||
|
//
|
|||
|
// Revision History:
|
|||
|
//
|
|||
|
//--
|
|||
|
|
|||
|
#include "ksmips.h"
|
|||
|
|
|||
|
SBTTL("Acquire Fast Mutex")
|
|||
|
//++
|
|||
|
//
|
|||
|
// VOID
|
|||
|
// ExAcquireFastMutex (
|
|||
|
// IN PFAST_MUTEX FastMutex
|
|||
|
// )
|
|||
|
//
|
|||
|
// Routine Description:
|
|||
|
//
|
|||
|
// This function acquires ownership of a fast mutex and raises IRQL to
|
|||
|
// APC level.
|
|||
|
//
|
|||
|
// Arguments:
|
|||
|
//
|
|||
|
// FastMutex (a0) - Supplies a pointer to a fast mutex.
|
|||
|
//
|
|||
|
// Return Value:
|
|||
|
//
|
|||
|
// None.
|
|||
|
//
|
|||
|
//--
|
|||
|
|
|||
|
.struct 0
|
|||
|
.space 4 * 4 // argment save area
|
|||
|
FmTime: .space 4 // wait timeout pointer
|
|||
|
FmA0: .space 4 // saved fast mutex address
|
|||
|
FmIrql: .space 4 // old IRQL value
|
|||
|
FmRa: .space 4 // saved return address
|
|||
|
FastMutexFrameLength: // frame length
|
|||
|
|
|||
|
NESTED_ENTRY(ExAcquireFastMutex, FastMutexFrameLength, zero)
|
|||
|
|
|||
|
subu sp,sp,FastMutexFrameLength // allocate stack frame
|
|||
|
sw ra,FmRa(sp) // save return address
|
|||
|
|
|||
|
PROLOGUE_END
|
|||
|
|
|||
|
//
|
|||
|
// Raise IRQL to APC_LEVEL.
|
|||
|
//
|
|||
|
|
|||
|
li a1,APC_LEVEL // set new IRQL level
|
|||
|
lbu t0,KiPcr + PcIrqlTable(a1) // get translation table entry value
|
|||
|
li t1,~(0xff << PSR_INTMASK) // get interrupt enable mask
|
|||
|
sll t0,t0,PSR_INTMASK // shift table entry into position
|
|||
|
lbu t2,KiPcr + PcCurrentIrql(zero) // get current IRQL
|
|||
|
|
|||
|
DISABLE_INTERRUPTS(t3) // disable interrupts
|
|||
|
|
|||
|
and t3,t3,t1 // clear current interrupt enables
|
|||
|
or t3,t3,t0 // set new interrupt enables
|
|||
|
sb a1,KiPcr + PcCurrentIrql(zero) // set new IRQL
|
|||
|
|
|||
|
ENABLE_INTERRUPTS(t3) // enable interrupts
|
|||
|
|
|||
|
//
|
|||
|
// Decrement ownership count.
|
|||
|
//
|
|||
|
|
|||
|
lw t6,KiPcr + PcCurrentThread(zero) // get current thread address
|
|||
|
10: ll t4,FmCount(a0) // get ownership count
|
|||
|
subu t5,t4,1 // decrement ownership count
|
|||
|
sc t5,FmCount(a0) // conditionally store ownership count
|
|||
|
beq zero,t5,10b // if eq, store conditional failed
|
|||
|
blez t4,20f // if lez, mutex is already owned
|
|||
|
sb t2,FmOldIrql(a0) // store old IRQL
|
|||
|
sw t6,FmOwner(a0) // set owner thread address
|
|||
|
addu sp,sp,FastMutexFrameLength // deallocate stack frame
|
|||
|
j ra // return
|
|||
|
|
|||
|
//
|
|||
|
// Fast mutex is currently owned by another thread. Increment the contention
|
|||
|
// count and wait for ownership.
|
|||
|
//
|
|||
|
|
|||
|
20: sb t2,FmIrql(sp) // save old IRQL
|
|||
|
sw a0,FmA0(sp) // save address of fast mutex
|
|||
|
lw t0,FmContention(a0) // increment contention count
|
|||
|
addu t0,t0,1 //
|
|||
|
sw t0,FmContention(a0) //
|
|||
|
|
|||
|
#if DBG
|
|||
|
|
|||
|
lw t0,FmOwner(a0) // get owner thread address
|
|||
|
bne t0,t6,30f // if ne, thread not owner
|
|||
|
jal DbgBreakPoint // break
|
|||
|
|
|||
|
#endif
|
|||
|
|
|||
|
30: sw zero,FmTime(sp) // set NULL timeout pointer
|
|||
|
li a3,FALSE // set nonalertable wait
|
|||
|
li a2,KernelMode // set mode of wait
|
|||
|
li a1,Executive // set reason for wait
|
|||
|
addu a0,a0,FmEvent // compute address of event
|
|||
|
jal KeWaitForSingleObject // wait for ownership
|
|||
|
lw a0,FmA0(sp) // get address of fast mutex
|
|||
|
lbu a1,FmIrql(sp) // get old IRQL value
|
|||
|
lw a2,KiPcr + PcCurrentThread(zero) // get current thread address
|
|||
|
sb a1,FmOldIrql(a0) // save old IRQL in fast mutex
|
|||
|
sw a2,FmOwner(a0) // set owner thread address
|
|||
|
lw ra,FmRa(sp) // restore return address
|
|||
|
addu sp,sp,FastMutexFrameLength // deallocate stack frame
|
|||
|
j ra // return
|
|||
|
|
|||
|
.end ExAcquireFastMutex
|
|||
|
|
|||
|
SBTTL("Release Fast Mutex")
|
|||
|
//++
|
|||
|
//
|
|||
|
// VOID
|
|||
|
// ExReleaseFastMutex (
|
|||
|
// IN PFAST_MUTEX FastMutex
|
|||
|
// )
|
|||
|
//
|
|||
|
// Routine Description:
|
|||
|
//
|
|||
|
// This function releases ownership to a fast mutex and lowers IRQL to
|
|||
|
// its previous level.
|
|||
|
//
|
|||
|
// Arguments:
|
|||
|
//
|
|||
|
// FastMutex (a0) - Supplies a pointer to a fast mutex.
|
|||
|
//
|
|||
|
// Return Value:
|
|||
|
//
|
|||
|
// None.
|
|||
|
//
|
|||
|
//--
|
|||
|
|
|||
|
NESTED_ENTRY(ExReleaseFastMutex, FastMutexFrameLength, zero)
|
|||
|
|
|||
|
subu sp,sp,FastMutexFrameLength // allocate stack frame
|
|||
|
sw ra,FmRa(sp) // save return address
|
|||
|
|
|||
|
PROLOGUE_END
|
|||
|
|
|||
|
//
|
|||
|
// Increment ownership count and release waiter if contention.
|
|||
|
//
|
|||
|
|
|||
|
lbu a1,FmOldIrql(a0) // get old IRQL value
|
|||
|
sw zero,FmOwner(a0) // clear owner thread address
|
|||
|
10: ll t0,FmCount(a0) // get ownership count
|
|||
|
addu t1,t0,1 // increment ownership count
|
|||
|
sc t1,FmCount(a0) // conditionally store ownership count
|
|||
|
beq zero,t1,10b // if eq, store conditional failed
|
|||
|
beq zero,t0,20f // if eq, no waiter is present
|
|||
|
|
|||
|
//
|
|||
|
// There is contention for the fast mutex. Wake up a waiting thread and
|
|||
|
// boost its priority to the priority of the current thread.
|
|||
|
//
|
|||
|
|
|||
|
sw a0,FmA0(sp) // save address of fast mutex
|
|||
|
sb a1,FmIrql(sp) // save old IRQL value
|
|||
|
addu a1,a0,FmOwner // compute address to store owner
|
|||
|
addu a0,a0,FmEvent // compute address of event
|
|||
|
jal KeSetEventBoostPriority // set event and boost priority
|
|||
|
lw a0,FmA0(sp) // restore fast mutex address
|
|||
|
lbu a1,FmIrql(sp) // restore old IRQL value
|
|||
|
lw ra,FmRa(sp) // restore return address
|
|||
|
|
|||
|
//
|
|||
|
// Lower IRQL to its previous value.
|
|||
|
//
|
|||
|
|
|||
|
20: lbu t0,KiPcr + PcIrqlTable(a1) // get translation table entry value
|
|||
|
li t1,~(0xff << PSR_INTMASK) // get interrupt enable mask
|
|||
|
sll t0,t0,PSR_INTMASK // shift table entry into position
|
|||
|
|
|||
|
DISABLE_INTERRUPTS(t2) // disable interrupts
|
|||
|
|
|||
|
and t2,t2,t1 // clear current interrupt enables
|
|||
|
or t2,t2,t0 // set new interrupt enables
|
|||
|
sb a1,KiPcr + PcCurrentIrql(zero) // set new IRQL
|
|||
|
|
|||
|
ENABLE_INTERRUPTS(t2) // enable interrupts
|
|||
|
|
|||
|
addu sp,sp,FastMutexFrameLength // deallocate stack frame
|
|||
|
j ra // return
|
|||
|
|
|||
|
.end ExReleaseFastMutex
|
|||
|
|
|||
|
SBTTL("Try To Acquire Fast Mutex")
|
|||
|
//++
|
|||
|
//
|
|||
|
// BOOLEAN
|
|||
|
// ExTryToAcquireFastMutex (
|
|||
|
// IN PFAST_MUTEX FastMutex
|
|||
|
// )
|
|||
|
//
|
|||
|
// Routine Description:
|
|||
|
//
|
|||
|
// This function attempts to acquire ownership of a fast mutex, and if
|
|||
|
// successful, raises IRQL to APC level.
|
|||
|
//
|
|||
|
// Arguments:
|
|||
|
//
|
|||
|
// FastMutex (a0) - Supplies a pointer to a fast mutex.
|
|||
|
//
|
|||
|
// Return Value:
|
|||
|
//
|
|||
|
// If the fast mutex was successfuly acquired, then a value of TRUE
|
|||
|
// is returned as the function vlaue. Otherwise, a value of FALSE is
|
|||
|
// returned.
|
|||
|
//
|
|||
|
//--
|
|||
|
|
|||
|
LEAF_ENTRY(ExTryToAcquireFastMutex)
|
|||
|
|
|||
|
li a1,APC_LEVEL // set new IRQL level
|
|||
|
lbu t0,KiPcr + PcIrqlTable(a1) // get translation table entry value
|
|||
|
li t1,~(0xff << PSR_INTMASK) // get interrupt enable mask
|
|||
|
sll t0,t0,PSR_INTMASK // shift table entry into position
|
|||
|
lbu t2,KiPcr + PcCurrentIrql(zero) // get current IRQL
|
|||
|
|
|||
|
DISABLE_INTERRUPTS(t3) // disable interrupts
|
|||
|
|
|||
|
//
|
|||
|
// Decrement ownership count if and only if the fast mutex is not currently
|
|||
|
// owned.
|
|||
|
//
|
|||
|
|
|||
|
lw t5,KiPcr + PcCurrentThread(zero) // get current thread address
|
|||
|
10: ll t4,FmCount(a0) // get ownership count
|
|||
|
subu v0,t4,1 // decrement ownership count
|
|||
|
blez t4,20f // if lez, mutex is already owned
|
|||
|
sc v0,FmCount(a0) // conditionally store ownership count
|
|||
|
beq zero,v0,10b // if eq, store conditional failed
|
|||
|
and t3,t3,t1 // clear current interrupt enables
|
|||
|
or t3,t3,t0 // set new interrupt enables
|
|||
|
sb a1,KiPcr + PcCurrentIrql(zero) // set new IRQL
|
|||
|
|
|||
|
ENABLE_INTERRUPTS(t3) // enable interrupts
|
|||
|
|
|||
|
sb t2,FmOldIrql(a0) // store old IRQL
|
|||
|
sw t5,FmOwner(a0) // set owner thread address
|
|||
|
j ra // return
|
|||
|
|
|||
|
//
|
|||
|
// Fast mutex is currently owned by another thread. Enable interrupts and
|
|||
|
// return FALSE.
|
|||
|
//
|
|||
|
|
|||
|
20: ENABLE_INTERRUPTS(t3) // enable interrupts
|
|||
|
|
|||
|
li v0,FALSE // set return value
|
|||
|
j ra // return
|
|||
|
|
|||
|
.end ExTryToAcquireFastMutex
|
|||
|
|
|||
|
SBTTL("Acquire Fast Mutex Unsafe")
|
|||
|
//++
|
|||
|
//
|
|||
|
// VOID
|
|||
|
// ExAcquireFastMutexUnsafe (
|
|||
|
// IN PFAST_MUTEX FastMutex
|
|||
|
// )
|
|||
|
//
|
|||
|
// Routine Description:
|
|||
|
//
|
|||
|
// This function acquires ownership of a fast mutex, but does not raise
|
|||
|
// IRQL to APC level.
|
|||
|
//
|
|||
|
// Arguments:
|
|||
|
//
|
|||
|
// FastMutex (a0) - Supplies a pointer to a fast mutex.
|
|||
|
//
|
|||
|
// Return Value:
|
|||
|
//
|
|||
|
// None.
|
|||
|
//
|
|||
|
//--
|
|||
|
|
|||
|
NESTED_ENTRY(ExAcquireFastMutexUnsafe, FastMutexFrameLength, zero)
|
|||
|
|
|||
|
subu sp,sp,FastMutexFrameLength // allocate stack frame
|
|||
|
sw ra,FmRa(sp) // save return address
|
|||
|
|
|||
|
PROLOGUE_END
|
|||
|
|
|||
|
//
|
|||
|
// Decrement ownership count.
|
|||
|
//
|
|||
|
|
|||
|
lw t0,KiPcr + PcCurrentThread(zero) // get current thread address
|
|||
|
10: ll t1,FmCount(a0) // get ownership count
|
|||
|
subu t2,t1,1 // decrement ownership count
|
|||
|
sc t2,FmCount(a0) // conditionally store ownership count
|
|||
|
beq zero,t2,10b // if eq, store conditional failed
|
|||
|
blez t1,20f // if lez, mutex is already owned
|
|||
|
sw t0,FmOwner(a0) // set owner thread address
|
|||
|
addu sp,sp,FastMutexFrameLength // deallocate stack frame
|
|||
|
j ra // return
|
|||
|
|
|||
|
//
|
|||
|
// Fast mutex is currently owned by another thread. Increment the contention
|
|||
|
// count and wait for ownership.
|
|||
|
//
|
|||
|
|
|||
|
20: sw a0,FmA0(sp) // save address of fast mutex
|
|||
|
lw t1,FmContention(a0) // increment contention count
|
|||
|
addu t1,t1,1 //
|
|||
|
sw t1,FmContention(a0) //
|
|||
|
|
|||
|
#if DBG
|
|||
|
|
|||
|
lw t1,FmOwner(a0) // get owner thread address
|
|||
|
bne t0,t1,30f // if ne, thread not owner
|
|||
|
jal DbgBreakPoint // break
|
|||
|
|
|||
|
#endif
|
|||
|
|
|||
|
30: sw zero,FmTime(sp) // set NULL timeout pointer
|
|||
|
li a3,FALSE // set nonalertable wait
|
|||
|
li a2,KernelMode // set mode of wait
|
|||
|
li a1,Executive // set reason for wait
|
|||
|
addu a0,a0,FmEvent // compute address of event
|
|||
|
jal KeWaitForSingleObject // wait for ownership
|
|||
|
lw a0,FmA0(sp) // get address of fast mutex
|
|||
|
lw a1,KiPcr + PcCurrentThread(zero) // get current thread address
|
|||
|
sw a1,FmOwner(a0) // set owner thread address
|
|||
|
lw ra,FmRa(sp) // restore return address
|
|||
|
addu sp,sp,FastMutexFrameLength // deallocate stack frame
|
|||
|
j ra // return
|
|||
|
|
|||
|
.end ExAcquireFastMutexUnsafe
|
|||
|
|
|||
|
SBTTL("Release Fast Mutex Unsafe")
|
|||
|
//++
|
|||
|
//
|
|||
|
// VOID
|
|||
|
// 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:
|
|||
|
//
|
|||
|
// FastMutex (a0) - Supplies a pointer to a fast mutex.
|
|||
|
//
|
|||
|
// Return Value:
|
|||
|
//
|
|||
|
// None.
|
|||
|
//
|
|||
|
//--
|
|||
|
|
|||
|
NESTED_ENTRY(ExReleaseFastMutexUnsafe, FastMutexFrameLength, zero)
|
|||
|
|
|||
|
subu sp,sp,FastMutexFrameLength // allocate stack frame
|
|||
|
sw ra,FmRa(sp) // save return address
|
|||
|
|
|||
|
PROLOGUE_END
|
|||
|
|
|||
|
//
|
|||
|
// Increment ownership count and release waiter if contention.
|
|||
|
//
|
|||
|
|
|||
|
sw zero,FmOwner(a0) // clear owner thread address
|
|||
|
10: ll t0,FmCount(a0) // get ownership count
|
|||
|
addu t1,t0,1 // increment ownership count
|
|||
|
sc t1,FmCount(a0) // conditionally store ownership count
|
|||
|
beq zero,t1,10b // if eq, store conditional failed
|
|||
|
beq zero,t0,20f // if eq, no waiter is present
|
|||
|
|
|||
|
//
|
|||
|
// There is contention for the fast mutex. Wake up a waiting thread and
|
|||
|
// boost its priority to the priority of the current thread.
|
|||
|
//
|
|||
|
|
|||
|
addu a1,a0,FmOwner // compute address to store owner
|
|||
|
addu a0,a0,FmEvent // compute address of event
|
|||
|
jal KeSetEventBoostPriority // set event and boost priority
|
|||
|
lw ra,FmRa(sp) // restore return address
|
|||
|
20: addu sp,sp,FastMutexFrameLength // deallocate stack frame
|
|||
|
j ra // return
|
|||
|
|
|||
|
.end ExReleaseFastMutexUnsafe
|
|||
|
|
|||
|
SBTTL("Try To Acquire Fast Mutex Unsafe")
|
|||
|
//++
|
|||
|
//
|
|||
|
// BOOLEAN
|
|||
|
// ExTryToAcquireFastMutexUnsafe (
|
|||
|
// IN PFAST_MUTEX FastMutex
|
|||
|
// )
|
|||
|
//
|
|||
|
// Routine Description:
|
|||
|
//
|
|||
|
// This function attempts to acquire ownership of a fast mutex, and if
|
|||
|
// successful, does not raise IRQL to APC level.
|
|||
|
//
|
|||
|
// Arguments:
|
|||
|
//
|
|||
|
// FastMutex (a0) - Supplies a pointer to a fast mutex.
|
|||
|
//
|
|||
|
// Return Value:
|
|||
|
//
|
|||
|
// If the fast mutex was successfuly acquired, then a value of TRUE
|
|||
|
// is returned as the function vlaue. Otherwise, a value of FALSE is
|
|||
|
// returned.
|
|||
|
//
|
|||
|
//--
|
|||
|
|
|||
|
#if 0
|
|||
|
|
|||
|
LEAF_ENTRY(ExTryToAcquireFastMutexUnsafe)
|
|||
|
|
|||
|
//
|
|||
|
// Decrement ownership count if and only if the fast mutex is not currently
|
|||
|
// owned.
|
|||
|
//
|
|||
|
|
|||
|
lw t0,KiPcr + PcCurrentThread(zero) // get current thread address
|
|||
|
10: ll t1,FmCount(a0) // get ownership count
|
|||
|
subu v0,t1,1 // decrement ownership count
|
|||
|
blez t1,20f // if lez, mutex is already owned
|
|||
|
sc v0,FmCount(a0) // conditionally store ownership count
|
|||
|
beq zero,v0,10b // if eq, store conditional failed
|
|||
|
sw t0,FmOwner(a0) // set owner thread address
|
|||
|
j ra // return
|
|||
|
|
|||
|
//
|
|||
|
// Fast mutex is currently owned by another thread.
|
|||
|
//
|
|||
|
|
|||
|
20: li v0,FALSE // set return value
|
|||
|
j ra // return
|
|||
|
|
|||
|
.end ExTryToAcquireFastMutexUnsafe
|
|||
|
|
|||
|
#endif
|