mirror of https://github.com/tongzx/nt5src
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.
401 lines
9.9 KiB
401 lines
9.9 KiB
// TITLE("Fast Mutex Support")
|
|
//++
|
|
//
|
|
// Module Name:
|
|
//
|
|
// fmutex.s
|
|
//
|
|
// Abstract:
|
|
//
|
|
// This module implements the code necessary to acquire and release fast
|
|
// mutxes.
|
|
//
|
|
//
|
|
// Author:
|
|
//
|
|
// William K. Cheung (wcheung) 02-Oct-1995
|
|
//
|
|
// Environment:
|
|
//
|
|
// Kernel mode only.
|
|
//
|
|
// Revision History:
|
|
//
|
|
// 08-Feb-96 Updated to EAS2.1
|
|
//
|
|
//--
|
|
|
|
#include "ksia64.h"
|
|
|
|
.file "fmutex.s"
|
|
|
|
PublicFunction(KeWaitForSingleObject)
|
|
PublicFunction(KeSetEventBoostPriority)
|
|
PublicFunction(KiCheckForSoftwareInterrupt)
|
|
|
|
//++
|
|
//
|
|
// VOID
|
|
// ExAcquireFastMutex (
|
|
// IN PFAST_MUTEX FastMutex
|
|
// )
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// This function acquires ownership of a fast mutex and raises IRQL to
|
|
// APC Level. Must be called at IRQL < DISPATCH_LEVEL.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// FastMutex (a0) - Supplies a pointer to a fast mutex.
|
|
//
|
|
// Return Value:
|
|
//
|
|
// None.
|
|
//
|
|
//--
|
|
|
|
//
|
|
// t0 -- Original value of Fmutex.FmCount
|
|
// t1 -- Address of Fmutex.FmCount
|
|
// t2 -- Address of Fmutex.FmOldIrql
|
|
// t3 -- Address of KiPcr
|
|
// t4 -- Address of Fmutex.FmContention
|
|
// t8 -- Address of KiPcr.PcCurrentThread
|
|
// r35 -- old IRQL
|
|
//
|
|
// t5 -- temp
|
|
//
|
|
|
|
NESTED_ENTRY(ExAcquireFastMutex)
|
|
|
|
.regstk 1, 4, 5, 0
|
|
.prologue 0xC, savedpfs
|
|
|
|
alloc savedpfs = ar.pfs, 1, 4, 5, 0
|
|
add loc3 = FmOwner, a0
|
|
mov savedbrp = brp
|
|
GET_IRQL (loc2) // Get old IRQL
|
|
|
|
PROLOGUE_END
|
|
|
|
mov t4 = APC_LEVEL
|
|
add t1 = FmCount, a0
|
|
add t2 = FmOldIrql, a0
|
|
;;
|
|
SET_IRQL (t4) // change IRQL to APC_LEVEL
|
|
;;
|
|
|
|
//
|
|
// synchronize subsequent reads
|
|
//
|
|
|
|
fetchadd4.acq t0 = [t1], -1 // decrement mutex count
|
|
add t4 = FmContention, a0
|
|
add out0 = FmEvent, a0
|
|
|
|
mov out1 = Executive // set reason for wait
|
|
mov out2 = KernelMode // set mode of wait
|
|
;;
|
|
|
|
cmp4.le pt7, pt8 = t0, zero // if le, mutex acq failed
|
|
mov out3 = FALSE // set nonalertable wait
|
|
mov out4 = zero // set NULL timeout pointer
|
|
;;
|
|
|
|
(pt7) ld4 t5 = [t4] // load contention count
|
|
(pt8) st8 [loc3] = sp // Save the SP so we can identify the owner.
|
|
(pt8) st4 [t2] = loc2 // save old IRQL
|
|
(pt8) br.ret.sptk.clr brp // return
|
|
;;
|
|
|
|
Eafm10:
|
|
|
|
(pt7) add t5 = 1, t5 // inc contention count
|
|
;;
|
|
st4 [t4] = t5 // save contention count
|
|
br.call.sptk.many brp = KeWaitForSingleObject
|
|
|
|
add t2 = FmOldIrql, a0
|
|
mov ar.pfs = savedpfs // restore pfs
|
|
mov brp = savedbrp // restore brp
|
|
;;
|
|
|
|
st4 [t2] = loc2 // save old IRQL
|
|
st8 [loc3] = sp // Save the SP so we can identify the owner.
|
|
br.ret.sptk.clr brp // return
|
|
|
|
NESTED_EXIT(ExAcquireFastMutex)
|
|
|
|
//++
|
|
//
|
|
// 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)
|
|
|
|
NESTED_SETUP(1, 3, 2, 0)
|
|
add t1 = FmCount, a0
|
|
|
|
PROLOGUE_END
|
|
|
|
//
|
|
// Increment mutex count and release waiter if contention.
|
|
//
|
|
|
|
//
|
|
// use release semantics to synchronize all previous writes
|
|
//
|
|
add t2 = FmOldIrql, a0
|
|
;;
|
|
|
|
ld4 loc2 = [t2] // get old IRQL before releasing lock
|
|
fetchadd4.rel t9 = [t1], 1 // increment mutex count
|
|
add out0 = FmEvent, a0
|
|
;;
|
|
|
|
cmp4.eq pt1, pt0 = zero, t9 // if eq, no waiter
|
|
mov out1 = zero
|
|
(pt0) br.call.spnt.many brp = KeSetEventBoostPriority
|
|
;;
|
|
|
|
LOWER_IRQL (loc2)
|
|
NESTED_RETURN
|
|
|
|
NESTED_EXIT(ExReleaseFastMutex)
|
|
|
|
//++
|
|
//
|
|
// 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)
|
|
|
|
mov t4 = APC_LEVEL
|
|
add t1 = FmCount, a0
|
|
add t2 = FmOldIrql, a0
|
|
add t6 = FmOwner, a0
|
|
GET_IRQL (t0) // get old IRQL
|
|
SET_IRQL (t4) // change IRQL to APC_LEVEL
|
|
;;
|
|
|
|
ld4 t4 = [t1]
|
|
;;
|
|
mov ar.ccv = t4
|
|
cmp4.le pt8, pt7 = t4, zero // if le, mutex acq failed
|
|
|
|
add t5 = -1, t4
|
|
mov v0 = TRUE // return TRUE by default
|
|
(pt8) br.spnt.few Ettafm10
|
|
;;
|
|
|
|
//
|
|
// use acquire semantics to sychronize subsequent reads
|
|
//
|
|
|
|
cmpxchg4.acq t4 = [t1], t5, ar.ccv
|
|
;;
|
|
cmp4.le pt8, pt7 = t4, zero // if le, mutex acq failed
|
|
;;
|
|
|
|
Ettafm10:
|
|
|
|
PSET_IRQL (pt8, t0) // restore IRQL
|
|
(pt7) st4 [t2] = t0 // save old IRQL
|
|
(pt8) mov v0 = FALSE // return FALSE
|
|
(pt7) st8 [t6] = sp // Save the SP so we can identify the owner.
|
|
br.ret.sptk.clr brp // return
|
|
|
|
LEAF_EXIT(ExTryToAcquireFastMutex)
|
|
|
|
//++
|
|
//
|
|
// 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)
|
|
|
|
NESTED_SETUP(1, 3, 5, 0)
|
|
add t1 = FmCount, a0
|
|
;;
|
|
|
|
PROLOGUE_END
|
|
|
|
//
|
|
// Use acquire semantics to synchronize subsequent reads
|
|
//
|
|
|
|
fetchadd4.acq t0 = [t1], -1 // decrement mutex count
|
|
add out0 = FmEvent, a0
|
|
|
|
add t3 = FmContention, a0
|
|
add loc2 = FmOwner, a0
|
|
mov out1 = Executive // set reason for wait
|
|
mov out2 = KernelMode // set mode of wait
|
|
;;
|
|
|
|
cmp4.le p0, pt8 = t0, zero // if le, contention
|
|
mov out3 = FALSE // set nonalertable wait
|
|
;;
|
|
(pt8) st8 [loc2] = sp // Save the SP so we can identify the owner.
|
|
(pt8) br.ret.sptk.clr brp // return
|
|
|
|
//
|
|
// Increment the contention count and then call KeWaitForSingleObject().
|
|
// The outgoing arguments have been set up ahead of time.
|
|
//
|
|
|
|
ld4 t4 = [t3] // get contention count
|
|
;;
|
|
add t4 = 1, t4 // increment contention count
|
|
mov out4 = 0 // set NULL timeout pointer
|
|
;;
|
|
|
|
st4 [t3] = t4 // save contention count
|
|
br.call.sptk.many brp = KeWaitForSingleObject
|
|
|
|
mov ar.pfs = savedpfs // restore pfs
|
|
mov brp = savedbrp // restore return link
|
|
st8 [loc2] = sp // Save the sp of the owner
|
|
br.ret.sptk.clr brp // return
|
|
|
|
NESTED_EXIT(ExAcquireFastMutexUnsafe)
|
|
|
|
//++
|
|
//
|
|
// 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)
|
|
|
|
NESTED_SETUP(1, 2, 2, 0)
|
|
add t1 = FmCount, a0
|
|
;;
|
|
|
|
PROLOGUE_END
|
|
|
|
//
|
|
// Increment mutex count and release waiter if contention.
|
|
//
|
|
|
|
//
|
|
// Use release semantics to syncrhonize all previous writes
|
|
// before the mutext is released.
|
|
//
|
|
|
|
fetchadd4.rel t9 = [t1], 1 // increment mutex count
|
|
;;
|
|
add out0 = FmEvent, a0
|
|
cmp4.eq pt7, pt8 = zero, t9 // if eq, no waiter
|
|
|
|
add out1 = zero, zero
|
|
(pt7) br.ret.sptk.clr brp // return
|
|
(pt8) br.call.spnt.many brp = KeSetEventBoostPriority
|
|
|
|
mov ar.pfs = savedpfs
|
|
mov brp = savedbrp
|
|
br.ret.sptk.clr brp // return
|
|
|
|
NESTED_EXIT(ExReleaseFastMutexUnsafe)
|
|
|
|
|
|
//++
|
|
//
|
|
// 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)
|
|
|
|
|
|
LEAF_EXIT(ExTryToAcquireFastMutexUnsafe)
|
|
#endif
|