525 lines
14 KiB
ArmAsm
525 lines
14 KiB
ArmAsm
|
// TITLE("Alpha 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:
|
|||
|
//
|
|||
|
// John Vert (jvert) 14-Apr-1994
|
|||
|
//
|
|||
|
// Environment:
|
|||
|
//
|
|||
|
// Kernel mode only.
|
|||
|
//
|
|||
|
// Revision History:
|
|||
|
//
|
|||
|
//--
|
|||
|
|
|||
|
#include "ksalpha.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
|
|||
|
FmA0: .space 8 // saved fast mutex address
|
|||
|
FmIrql: .space 4 // old IRQL value
|
|||
|
.space 4 // fill
|
|||
|
FmRa: .space 8 // saved return address
|
|||
|
.space 8 // fill
|
|||
|
FastMutexFrameLength: // frame length
|
|||
|
|
|||
|
NESTED_ENTRY(ExAcquireFastMutex, FastMutexFrameLength, zero)
|
|||
|
|
|||
|
lda sp, -FastMutexFrameLength(sp) // allocate stack frame
|
|||
|
stq ra, FmRa(sp) // save return address
|
|||
|
|
|||
|
PROLOGUE_END
|
|||
|
|
|||
|
//
|
|||
|
// Raise IRQL to APC_LEVEL
|
|||
|
//
|
|||
|
|
|||
|
bis a0, zero, t0 // save address of fast mutex
|
|||
|
bis zero, APC_LEVEL, a0 // set new IRQL level
|
|||
|
|
|||
|
SWAP_IRQL // raise IRQL
|
|||
|
|
|||
|
//
|
|||
|
// Decrement ownership count.
|
|||
|
//
|
|||
|
|
|||
|
10: ldl_l t4, FmCount(t0) // get ownership count
|
|||
|
subl t4, 1, t5 // decrement ownership count
|
|||
|
stl_c t5, FmCount(t0) // conditionally store ownership count
|
|||
|
beq t5, 15f // if eq, conditional store failed
|
|||
|
ble t4, 20f // if le, mutex is already owned
|
|||
|
|
|||
|
#if !defined(NT_UP)
|
|||
|
|
|||
|
mb // synchronize memory access
|
|||
|
|
|||
|
#endif
|
|||
|
|
|||
|
stl v0, FmOldIrql(t0) // save previous IRQL
|
|||
|
|
|||
|
GET_CURRENT_THREAD // get current thread address
|
|||
|
|
|||
|
STP v0, FmOwner(t0) // set owner thread address
|
|||
|
lda sp, FastMutexFrameLength(sp) // deallocate stack frame
|
|||
|
ret zero, (ra) // return
|
|||
|
|
|||
|
//
|
|||
|
// Store conditional attempt failed.
|
|||
|
//
|
|||
|
|
|||
|
15: br zero, 10b // retry
|
|||
|
|
|||
|
//
|
|||
|
// Fast mutex is currently owned by another thread. Increment the contention
|
|||
|
// count and wait for ownership.
|
|||
|
//
|
|||
|
|
|||
|
20: stl v0, FmIrql(sp) // save previous IRQL
|
|||
|
STP t0, FmA0(sp) // save address of fast mutex
|
|||
|
ldl t1, FmContention(t0) // increment contention count
|
|||
|
addl t1, 1, t2 //
|
|||
|
stl t2, FmContention(t0) //
|
|||
|
bis zero, zero, a4 // set NULL timeout pointer
|
|||
|
bis zero, FALSE, a3 // set nonalertable wait
|
|||
|
bis zero, KernelMode, a2 // set mode of wait
|
|||
|
bis zero, Executive, a1 // set reason for wait
|
|||
|
ADDP t0, FmEvent, a0 // compute address of event
|
|||
|
bsr ra, KeWaitForSingleObject // wait for ownership
|
|||
|
LDP t0, FmA0(sp) // get address of fast mutex
|
|||
|
ldl a1, FmIrql(sp) // get old IRQL value
|
|||
|
stl a1, FmOldIrql(t0) // save old IRQL value in fast mutex
|
|||
|
|
|||
|
GET_CURRENT_THREAD // get current thread address
|
|||
|
|
|||
|
STP v0, FmOwner(t0) // set owner thread address
|
|||
|
ldq ra, FmRa(sp) // restore return address
|
|||
|
lda sp, FastMutexFrameLength(sp) // deallocate stack frame
|
|||
|
ret zero, (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)
|
|||
|
|
|||
|
lda sp, -FastMutexFrameLength(sp) // allocate stack frame
|
|||
|
stq ra, FmRa(sp) // save return address
|
|||
|
|
|||
|
PROLOGUE_END
|
|||
|
|
|||
|
ldl a1, FmOldIrql(a0) // get old IRQL value
|
|||
|
STP zero, FmOwner(a0) // clear owner thread address
|
|||
|
//
|
|||
|
// Synchronize all previous writes before the mutex is released.
|
|||
|
//
|
|||
|
|
|||
|
#if !defined(NT_UP)
|
|||
|
|
|||
|
mb // synchronize memory access
|
|||
|
|
|||
|
#endif
|
|||
|
|
|||
|
//
|
|||
|
// Increment ownership count and release waiter if contention.
|
|||
|
//
|
|||
|
|
|||
|
10: ldl_l t0, FmCount(a0) // get ownership count
|
|||
|
addl t0, 1, t1 // increment ownership count
|
|||
|
stl_c t1, FmCount(a0) // conditionally store ownership count
|
|||
|
beq t1, 15f // if eq, store conditional failed
|
|||
|
bne t0, 30f // if ne, a waiter is present
|
|||
|
|
|||
|
//
|
|||
|
// Lower IRQL to its previous value.
|
|||
|
//
|
|||
|
|
|||
|
bis a1, zero, a0 // set IRQL level
|
|||
|
|
|||
|
20: SWAP_IRQL // lower IRQL
|
|||
|
|
|||
|
lda sp, FastMutexFrameLength(sp) // deallocate stack frame
|
|||
|
ret zero, (ra) // return
|
|||
|
|
|||
|
//
|
|||
|
// There is contention for the fast mutex. Wake up a waiting thread and
|
|||
|
// boost its priority to the priority of the current thread.
|
|||
|
//
|
|||
|
|
|||
|
30: stl a1, FmIrql(sp) // save old IRQL value
|
|||
|
ADDP a0, FmEvent, a0 // compute address of event
|
|||
|
bis zero, zero, a1 // set optional parameter
|
|||
|
bsr ra, KeSetEventBoostPriority // set event and boost priority
|
|||
|
ldl a0, FmIrql(sp) // restore old IRQL value
|
|||
|
ldq ra, FmRa(sp) // restore return address
|
|||
|
br zero, 20b // lower IRQL and return
|
|||
|
|
|||
|
//
|
|||
|
// Conditional store attempt failed.
|
|||
|
//
|
|||
|
|
|||
|
15: br zero, 10b // retry
|
|||
|
|
|||
|
.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 successfully acquired, then a value of TRUE
|
|||
|
// is returned as the function value. Otherwise, a valye of FALSE is
|
|||
|
// returned.
|
|||
|
//
|
|||
|
//--
|
|||
|
|
|||
|
LEAF_ENTRY(ExTryToAcquireFastMutex)
|
|||
|
|
|||
|
//
|
|||
|
// Raise IRQL to APC_LEVEL.
|
|||
|
//
|
|||
|
|
|||
|
bis a0, zero, t0 // save fast mutex address
|
|||
|
bis zero, APC_LEVEL, a0 // set new IRQL level
|
|||
|
|
|||
|
SWAP_IRQL // raise IRQL
|
|||
|
|
|||
|
bis v0, zero, a0 // save previous IRQL
|
|||
|
|
|||
|
//
|
|||
|
// Decrement ownership count if and only if fast mutex is not currently
|
|||
|
// owned.
|
|||
|
//
|
|||
|
|
|||
|
10: ldl_l t4, FmCount(t0) // get ownership count
|
|||
|
subl t4, 1, v0 // decrement ownership count
|
|||
|
ble t4, 20f // if le, mutex is already owned
|
|||
|
stl_c v0, FmCount(t0) // conditionally store ownership count
|
|||
|
beq v0, 15f // if ne, conditional store failed
|
|||
|
|
|||
|
#if !defined(NT_UP)
|
|||
|
|
|||
|
mb // synchronize memory access
|
|||
|
|
|||
|
#endif
|
|||
|
|
|||
|
stl a0, FmOldIrql(t0) // set previous IRQL
|
|||
|
|
|||
|
GET_CURRENT_THREAD // get current thread address
|
|||
|
|
|||
|
STP v0, FmOwner(t0) // set owner thread address
|
|||
|
bis zero, TRUE, v0 // set return value
|
|||
|
ret zero, (ra) // return
|
|||
|
|
|||
|
//
|
|||
|
// Conditional store attempt failed.
|
|||
|
//
|
|||
|
|
|||
|
15: br zero, 10b // retry
|
|||
|
|
|||
|
//
|
|||
|
// Fast mutex is currently owned by another thread. Restore IRQL to its
|
|||
|
// previous valye and return false.
|
|||
|
//
|
|||
|
|
|||
|
20: SWAP_IRQL // lower IRQL
|
|||
|
|
|||
|
bis zero, zero, v0 // set return value
|
|||
|
ret zero, (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)
|
|||
|
|
|||
|
lda sp, -FastMutexFrameLength(sp) // allocate stack frame
|
|||
|
stq ra, FmRa(sp) // save return address
|
|||
|
|
|||
|
PROLOGUE_END
|
|||
|
|
|||
|
//
|
|||
|
// Decrement ownership count.
|
|||
|
//
|
|||
|
|
|||
|
bis a0, zero, t0 // save fast mutex address
|
|||
|
10: ldl_l t4, FmCount(t0) // get ownership count
|
|||
|
subl t4, 1, t5 // decrement ownership count
|
|||
|
stl_c t5, FmCount(t0) // conditionally store ownership count
|
|||
|
beq t5, 15f // if eq, conditional store failed
|
|||
|
ble t4, 20f // if le zero, mutex is already owned
|
|||
|
|
|||
|
#if !defined(NT_UP)
|
|||
|
|
|||
|
mb // synchronize memory access
|
|||
|
|
|||
|
#endif
|
|||
|
|
|||
|
GET_CURRENT_THREAD // get current thread address
|
|||
|
|
|||
|
STP v0, FmOwner(t0) // store owning thread
|
|||
|
lda sp, FastMutexFrameLength(sp) // deallocate stack frame
|
|||
|
ret zero, (ra) // return
|
|||
|
|
|||
|
//
|
|||
|
// Conditional store attempt failed.
|
|||
|
//
|
|||
|
|
|||
|
15: br zero, 10b // retry
|
|||
|
|
|||
|
//
|
|||
|
// Fast mutex is currently owned by another thread. Increment the contention
|
|||
|
// count and wait for ownership.
|
|||
|
//
|
|||
|
|
|||
|
20: STP t0, FmA0(sp) // save address of fast mutex
|
|||
|
ldl t1, FmContention(t0) // increment contention count
|
|||
|
addl t1, 1, t2 //
|
|||
|
stl t2, FmContention(t0) //
|
|||
|
bis zero, zero, a4 // set NULL timeout pointer
|
|||
|
bis zero, FALSE, a3 // set nonalertable wait
|
|||
|
bis zero, KernelMode, a2 // set mode of wait
|
|||
|
bis zero, Executive, a1 // set reason for wait
|
|||
|
ADDP t0, FmEvent, a0 // compute address of event
|
|||
|
bsr ra, KeWaitForSingleObject // wait for ownership
|
|||
|
LDP t0, FmA0(sp) // get address of fast mutex
|
|||
|
|
|||
|
GET_CURRENT_THREAD // get current thread address
|
|||
|
|
|||
|
STP v0, FmOwner(t0) // set owner thread address
|
|||
|
ldq ra, FmRa(sp) // restore return address
|
|||
|
lda sp, FastMutexFrameLength(sp) // deallocate stack frame
|
|||
|
ret zero, (ra) //
|
|||
|
|
|||
|
.end ExAcquireFastMutexUnsafe
|
|||
|
|
|||
|
SBTTL("Release Fast Mutex Unsafe")
|
|||
|
//++
|
|||
|
//
|
|||
|
// VOID
|
|||
|
// ExReleaseFastMutexUnsafe (
|
|||
|
// IN PFAST_MUTEX FastMutex
|
|||
|
// )
|
|||
|
//
|
|||
|
// Routine Description:
|
|||
|
//
|
|||
|
// This function releases ownership to a fast mutex, and does not
|
|||
|
// restore IRQL to its previous level.
|
|||
|
//
|
|||
|
// Arguments:
|
|||
|
//
|
|||
|
// FastMutex (a0) - Supplies a pointer to a fast mutex.
|
|||
|
//
|
|||
|
// Return Value:
|
|||
|
//
|
|||
|
// None.
|
|||
|
//
|
|||
|
//--
|
|||
|
|
|||
|
NESTED_ENTRY(ExReleaseFastMutexUnsafe, FastMutexFrameLength, zero)
|
|||
|
|
|||
|
lda sp, -FastMutexFrameLength(sp) // allocate stack frame
|
|||
|
stq ra, FmRa(sp) // save return address
|
|||
|
|
|||
|
PROLOGUE_END
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Synchronize all previous writes before the mutex is released.
|
|||
|
//
|
|||
|
|
|||
|
#if !defined(NT_UP)
|
|||
|
|
|||
|
mb // synchronize memory access
|
|||
|
|
|||
|
#endif
|
|||
|
|
|||
|
//
|
|||
|
// Increment ownership count and release waiter if contention.
|
|||
|
//
|
|||
|
|
|||
|
STP zero, FmOwner(a0) // clear owner thread address
|
|||
|
10: ldl_l t0, FmCount(a0) // get ownership count
|
|||
|
addl t0, 1, t1 // increment ownership count
|
|||
|
stl_c t1, FmCount(a0) // conditionally store ownership count
|
|||
|
beq t1, 15f // if eq, store conditional failed
|
|||
|
beq t0, 20f // if ne, a 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.
|
|||
|
//
|
|||
|
|
|||
|
ADDP a0, FmEvent, a0 // compute address of event
|
|||
|
bis zero, zero, a1 // set optional parameter
|
|||
|
bsr ra, KeSetEventBoostPriority // set event and boost priority
|
|||
|
ldq ra, FmRa(sp) // restore return address
|
|||
|
20: lda sp, FastMutexFrameLength(sp) // deallocate stack frame
|
|||
|
ret zero, (ra) // return
|
|||
|
|
|||
|
//
|
|||
|
// Conditional store attempt failed.
|
|||
|
|
|||
|
15: br zero, 10b // retry
|
|||
|
|
|||
|
.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 successfully acquired, then a value of TRUE
|
|||
|
// is returned as the function value. Otherwise, a valye of FALSE is
|
|||
|
// returned.
|
|||
|
//
|
|||
|
//--
|
|||
|
|
|||
|
#if 0
|
|||
|
|
|||
|
LEAF_ENTRY(ExTryToAcquireFastMutexUnsafe)
|
|||
|
|
|||
|
//
|
|||
|
// Decrement ownership count if and only if fast mutex is not currently
|
|||
|
// owned.
|
|||
|
//
|
|||
|
|
|||
|
bis a0, zero, t0 // save fast mutex address
|
|||
|
10: ldl_l t4, FmCount(t0) // get ownership count
|
|||
|
subl t4, 1, v0 // decrement ownership count
|
|||
|
ble t4, 20f // if le zero, mutex is already owned
|
|||
|
stl_c v0, FmCount(t0) // conditionally store ownership count
|
|||
|
beq v0, 15f // if eq, conditional store failed
|
|||
|
|
|||
|
#if !defined(NT_UP)
|
|||
|
|
|||
|
mb // synchronize memory access
|
|||
|
|
|||
|
#endif
|
|||
|
|
|||
|
GET_CURRENT_THREAD // get current thread address
|
|||
|
|
|||
|
STP v0, FmOwner(t0) // set owner thread address
|
|||
|
ret zero, (ra) // return
|
|||
|
|
|||
|
//
|
|||
|
// Conditional store attempt failed.
|
|||
|
|
|||
|
15: br zero, 10b // retry
|
|||
|
|
|||
|
//
|
|||
|
// Fast mutex is currently owned by another thread. Restore IRQL to its
|
|||
|
// previous value and return false.
|
|||
|
//
|
|||
|
|
|||
|
20: bis zero, zero, v0 // set return value
|
|||
|
ret zero, (ra) // return
|
|||
|
|
|||
|
.end ExTrytoAcquireFastMutexUnsafe
|
|||
|
|
|||
|
#endif
|