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
|