windows-nt/Source/XPSP1/NT/base/ntos/ex/amd64/fmutex.c
2020-09-26 16:20:57 +08:00

293 lines
5.1 KiB
C

/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
fmutex.c
Abstract:
This module implements the code necessary to acquire and release fast
mutexes.
Author:
David N. Cutler (davec) 23-Jun-2000
Environment:
Any mode.
Revision History:
--*/
#include "exp.h"
VOID
ExAcquireFastMutex (
IN PFAST_MUTEX FastMutex
)
/*++
Routine Description:
This function acquires ownership of a fast mutex and raises IRQL to
APC Level.
Arguments:
FastMutex - Supplies a pointer to a fast mutex.
Return Value:
None.
--*/
{
KIRQL OldIrql;
//
// Raise IRQL to APC_LEVEL and decrement the ownership count to determine
// if the fast mutex is owned.
//
OldIrql = KfRaiseIrql(APC_LEVEL);
if (InterlockedDecrement(&FastMutex->Count) != 0) {
//
// The fast mutex is owned - wait for ownership to be granted.
//
FastMutex->Contention += 1;
KeWaitForSingleObject(&FastMutex->Event,
WrExecutive,
KernelMode,
FALSE,
NULL);
}
//
// Grant ownership of the fast mutext to the current thread.
//
FastMutex->Owner = KeGetCurrentThread();
FastMutex->OldIrql = OldIrql;
return;
}
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 - Supplies a pointer to a fast mutex.
Return Value:
None.
--*/
{
KIRQL OldIrql;
//
// Save the old IRQL, clear the owner thread, and increment the fast mutex
// count to detemine is there are any threads waiting for ownership to be
// granted.
//
OldIrql = (KIRQL)FastMutex->OldIrql;
ASSERT(FastMutex->Owner == KeGetCurrentThread());
ASSERT(KeGetCurrentIrql() == APC_LEVEL);
FastMutex->Owner = NULL;
if (InterlockedIncrement(&FastMutex->Count) <= 0) {
//
// There are one or more threads waiting for ownership of the fast
// mutex.
//
KeSetEventBoostPriority(&FastMutex->Event, NULL);
}
//
// Lower IRQL to its previous value.
//
KeLowerIrql(OldIrql);
return;
}
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 - 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 value of FALSE is
returned.
--*/
{
KIRQL OldIrql;
//
// Raise IRQL to APC_LEVEL and attempt to acquire ownership of the fast
// mutex.
//
OldIrql = KfRaiseIrql(APC_LEVEL);
if (InterlockedCompareExchange(&FastMutex->Count, 0, 1) != 1) {
//
// The fast mutex is owned - lower IRQL to its previous value
// and return FALSE.
//
KeLowerIrql(OldIrql);
return FALSE;
} else {
//
// Grant ownership of the fast mutext to the current thread and
// return TRUE.
//
FastMutex->Owner = KeGetCurrentThread();
FastMutex->OldIrql = OldIrql;
return TRUE;
}
}
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 - Supplies a pointer to a fast mutex.
Return Value:
None.
--*/
{
//
// Decrement the ownership count to determine if the fast mutex is owned.
//
if (InterlockedDecrement(&FastMutex->Count) != 0) {
//
// The fast mutex is owned - wait for ownership to be granted.
//
FastMutex->Contention += 1;
KeWaitForSingleObject(&FastMutex->Event,
WrExecutive,
KernelMode,
FALSE,
NULL);
}
//
// Grant ownership of the fast mutext to the current thread.
//
FastMutex->Owner = KeGetCurrentThread();
return;
}
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 - Supplies a pointer to a fast mutex.
Return Value:
None.
--*/
{
//
// Clear the owner thread and increment the fast mutex count to detemine
// is there are any threads waiting for ownership to be granted.
//
ASSERT(FastMutex->Owner == KeGetCurrentThread());
FastMutex->Owner = NULL;
if (InterlockedIncrement(&FastMutex->Count) <= 0) {
//
// There are one or more threads waiting for ownership of the fast
// mutex.
//
KeSetEventBoostPriority(&FastMutex->Event, NULL);
}
return;
}