windows-nt/Source/XPSP1/NT/base/ntos/ke/amd64/spinlock.c

495 lines
7.4 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
spinlock.c
Abstract:
This module implements the platform specific functions for acquiring
and releasing spin locks.
Author:
David N. Cutler (davec) 12-Jun-2000
Environment:
Kernel mode only.
Revision History:
--*/
#include "ki.h"
__forceinline
VOID
KxAcquireSpinLock (
IN PKSPIN_LOCK SpinLock
)
/*++
Routine Description:
This function acquires a spin lock at the current IRQL.
Arguments:
SpinLock - Supplies a pointer to an spin lock.
Return Value:
None.
--*/
{
PKTHREAD Thread;
//
// Acquire the specified spin lock at the current IRQL.
//
#if !defined(NT_UP)
#if DBG
Thread = KeGetCurrentThread();
while (InterlockedCompareExchange64((PLONGLONG)SpinLock,
(LONGLONG)Thread,
0) != 0) {
#else
while (InterlockedExchange64((PLONGLONG)SpinLock,
(LONGLONG)SpinLock) != 0) {
#endif // DBG
do {
} while (*(volatile LONGLONG *)SpinLock != 0);
}
#endif // !defined(NT_UP)
return;
}
__forceinline
BOOLEAN
KxTryToAcquireSpinLock (
IN PKSPIN_LOCK SpinLock
)
/*++
Routine Description:
This function attempts acquires a spin lock at the current IRQL. If
the spinlock is already owned, then FALSE is returned. Otherwise,
TRUE is returned.
Arguments:
SpinLock - Supplies a pointer to a spin lock.
Return Value:
If the spin lock is acquired a value TRUE is returned. Otherwise, FALSE
is returned as the function value.
--*/
{
PKTHREAD Thread;
//
// Try to acquire the specified spin lock at the current IRQL.
//
#if !defined(NT_UP)
if (*(volatile ULONGLONG *)SpinLock == 0) {
#if DBG
Thread = KeGetCurrentThread();
return InterlockedCompareExchange64((PLONGLONG)SpinLock,
(LONGLONG)Thread,
0) == 0;
#else
return InterlockedExchange64((PLONGLONG)SpinLock,
(LONGLONG)SpinLock) == 0;
#endif // DBG
} else {
return FALSE;
}
#else
return TRUE;
#endif // !defined(NT_UP)
}
__forceinline
VOID
KxReleaseSpinLock (
IN PKSPIN_LOCK SpinLock
)
/*++
Routine Description:
This function releases the specified spin lock at the current IRQL.
Arguments:
SpinLock - Supplies a pointer to a spin lock.
Return Value:
None.
--*/
{
#if !defined(NT_UP)
#if DBG
ASSERT(*(volatile ULONGLONG *)SpinLock == (ULONGLONG)KeGetCurrentThread());
#endif // DBG
*(volatile ULONGLONG *)SpinLock = 0;
#endif // !defined(NT_UP)
return;
}
VOID
KeInitializeSpinLock (
IN PKSPIN_LOCK SpinLock
)
/*++
Routine Description:
This function initializes a spin lock.
Arguments:
SpinLock - Supplies a pointer to a spin lock.
Return Value:
None.
--*/
{
*(volatile ULONGLONG *)SpinLock = 0;
return;
}
KIRQL
KeAcquireSpinLockRaiseToDpc (
IN PKSPIN_LOCK SpinLock
)
/*++
Routine Description:
This function raises IRQL to DISPATCH_LEVEL and acquires the specified
spin lock.
Arguments:
SpinLock - Supplies a pointer to a spin lock.
Return Value:
The previous IRQL is returned.
--*/
{
KIRQL OldIrql;
//
// Raise IRQL to DISPATCH_LEVEL and acquire the specified spin lock.
//
OldIrql = KfRaiseIrql(DISPATCH_LEVEL);
KxAcquireSpinLock(SpinLock);
return OldIrql;
}
KIRQL
KeAcquireSpinLockRaiseToSynch (
IN PKSPIN_LOCK SpinLock
)
/*++
Routine Description:
This function raises IRQL to SYNCH_LEVEL and acquires the specified
spin lock.
Arguments:
SpinLock - Supplies a pointer to a spin lock.
Return Value:
The previous IRQL is returned as the function value.
--*/
{
KIRQL OldIrql;
//
// Raise IRQL to SYNCH_LEVEL and acquire the specified spin lock.
//
OldIrql = KfRaiseIrql(SYNCH_LEVEL);
KxAcquireSpinLock(SpinLock);
return OldIrql;
}
VOID
KeAcquireSpinLockAtDpcLevel (
IN PKSPIN_LOCK SpinLock
)
/*++
Routine Description:
This function acquires a spin lock at the current IRQL.
Arguments:
SpinLock - Supplies a pointer to an spin lock.
Return Value:
None.
--*/
{
//
// Acquired the specified spin lock at the current IRQL.
//
KxAcquireSpinLock(SpinLock);
return;
}
BOOLEAN
KeTryToAcquireSpinLock (
IN PKSPIN_LOCK SpinLock,
OUT PKIRQL OldIrql
)
/*++
Routine Description:
This function raises IRQL to DISPATCH level and attempts to acquire a
spin lock. If the spin lock is already owned, then IRQL is restored to
its previous value and FALSE is returned. Otherwise, the spin lock is
acquired and TRUE is returned.
Arguments:
SpinLock - Supplies a pointer to a spin lock.
OldIrql - Supplies a pointer to a variable that receives the old IRQL.
Return Value:
If the spin lock is acquired a value TRUE is returned. Otherwise, FALSE
is returned.
--*/
{
//
// Raise IRQL to DISPATCH level and attempt to acquire the specified
// spin lock.
//
*OldIrql = KfRaiseIrql(DISPATCH_LEVEL);
if (KxTryToAcquireSpinLock(SpinLock) == FALSE) {
KeLowerIrql(*OldIrql);
return FALSE;
}
return TRUE;
}
BOOLEAN
KeTryToAcquireSpinLockAtDpcLevel (
IN PKSPIN_LOCK SpinLock
)
/*++
Routine Description:
This function attempts acquires a spin lock at the current IRQL. If
the spinlock is already owned, then FALSE is returned. Otherwise,
TRUE is returned.
Arguments:
SpinLock - Supplies a pointer to a spin lock.
Return Value:
If the spin lock is acquired a value TRUE is returned. Otherwise, FALSE
is returned as the function value.
--*/
{
//
// Try to acquire the specified spin lock at the current IRQL.
//
return KxTryToAcquireSpinLock(SpinLock);
}
VOID
KeReleaseSpinLock (
IN PKSPIN_LOCK SpinLock,
IN KIRQL OldIrql
)
/*++
Routine Description:
This function releases the specified spin lock and lowers IRQL to a
previous value.
Arguments:
SpinLock - Supplies a pointer to a spin lock.
OldIrql - Supplies the previous IRQL value.
Return Value:
None.
--*/
{
//
// Release the specified spin lock and lower IRQL.
//
KxReleaseSpinLock(SpinLock);
KeLowerIrql(OldIrql);
return;
}
VOID
KeReleaseSpinLockFromDpcLevel (
IN PKSPIN_LOCK SpinLock
)
/*++
Routine Description:
This function releases a spin lock at the current IRQL.
Arguments:
SpinLock - Supplies a pointer to a spin lock.
Return Value:
None.
--*/
{
//
// Release the specified spin lock.
//
KxReleaseSpinLock(SpinLock);
return;
}
#if defined(KeTestSpinLock)
#undef KeTestSpinLock
#endif
BOOLEAN
KeTestSpinLock (
IN PKSPIN_LOCK SpinLock
)
/*++
Routine Description:
This function tests a spin lock to determine if it is currently owned.
If the spinlock is already owned, then FALSE is returned. Otherwise,
TRUE is returned.
Arguments:
SpinLock - Supplies a pointer to a spin lock.
Return Value:
If the spin lock is currently owned, then a value of FALSE is returned.
Otherwise, a value of TRUE is returned.
--*/
{
#if !defined(NT_UP)
return (*(volatile ULONGLONG *)SpinLock == 0);
#else
return TRUE;
#endif // !defined(NT_UP)
}