395 lines
6.3 KiB
C
395 lines
6.3 KiB
C
/*++
|
||
|
||
Copyright (c) 1990 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
qlock.c
|
||
|
||
Abstract:
|
||
|
||
This module contains the code to emulate the operation of queued spin
|
||
locks using ordinary spin locks interfaces.
|
||
|
||
Author:
|
||
|
||
David N. Cutler 13-Feb-2000
|
||
|
||
Environment:
|
||
|
||
Kernel mode only.
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
#include "ki.h"
|
||
|
||
#if defined(NT_UP)
|
||
#undef KeAcquireQueuedSpinLockRaiseToSynch
|
||
#undef KeAcquireQueuedSpinLock
|
||
#undef KeReleaseQueuedSpinLock
|
||
#undef KeTryToAcquireQueuedSpinLockRaiseToSynch
|
||
#undef KeTryToAcquireQueuedSpinLock
|
||
#undef KeAcquireQueuedSpinLockAtDpcLevel
|
||
#undef KeReleaseQueuedSpinLockFromDpcLevel
|
||
#endif
|
||
|
||
|
||
VOID
|
||
FASTCALL
|
||
KeAcquireQueuedSpinLockAtDpcLevel (
|
||
IN PKSPIN_LOCK_QUEUE LockQueue
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function acquires a queued spin lock at DPC level.
|
||
|
||
Arguments:
|
||
|
||
LockQueue - Supplies a pointer to a lock queue entry in the PRCB.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
KiAcquireSpinLock(LockQueue->Lock);
|
||
return;
|
||
}
|
||
|
||
VOID
|
||
FASTCALL
|
||
KeReleaseQueuedSpinLockFromDpcLevel (
|
||
IN PKSPIN_LOCK_QUEUE LockQueue
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function releases a queued spin lock at DPC level.
|
||
|
||
Arguments:
|
||
|
||
LockQueue - Supplies a pointer to a lock queue entry in the PRCB.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
KiReleaseSpinLock(LockQueue->Lock);
|
||
return;
|
||
}
|
||
|
||
KIRQL
|
||
FASTCALL
|
||
KeAcquireQueuedSpinLock (
|
||
IN KSPIN_LOCK_QUEUE_NUMBER Number
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function acquires a queued spin lock and raises IRQL to DPC
|
||
level.
|
||
|
||
Arguments:
|
||
|
||
Number - Supplies the lock queue number.
|
||
|
||
Return Value:
|
||
|
||
The previous IRQL is returned as the function value.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
PKSPIN_LOCK Lock;
|
||
KIRQL OldIrql;
|
||
|
||
//
|
||
// N.B. It is safe to use any PRCB address since the backpointer
|
||
// to the actual spinlock is always the same.
|
||
//
|
||
|
||
Lock = KeGetCurrentPrcb()->LockQueue[Number].Lock;
|
||
KeAcquireSpinLock(Lock, &OldIrql);
|
||
return OldIrql;
|
||
}
|
||
|
||
VOID
|
||
FASTCALL
|
||
KeReleaseQueuedSpinLock (
|
||
IN KSPIN_LOCK_QUEUE_NUMBER Number,
|
||
IN KIRQL OldIrql
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function releases a queued spin lock and lowers IRQL to the
|
||
previous level.
|
||
|
||
Arguments:
|
||
|
||
LockQueue - Supplies a pointer to a lock queue entry in the PRCB.
|
||
|
||
Irql - Supplies the previos IRQL level.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
PKSPIN_LOCK Lock;
|
||
|
||
//
|
||
// N.B. It is safe to use any PRCB address since the backpointer
|
||
// to the actual spinlock is always the same.
|
||
//
|
||
|
||
Lock = KeGetCurrentPrcb()->LockQueue[Number].Lock;
|
||
KeReleaseSpinLock(Lock, OldIrql);
|
||
return;
|
||
}
|
||
|
||
LOGICAL
|
||
FASTCALL
|
||
KeTryToAcquireQueuedSpinLock(
|
||
IN KSPIN_LOCK_QUEUE_NUMBER Number,
|
||
IN PKIRQL OldIrql
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function attempts to acquire a queued spin lock and raises IRQL
|
||
to DPC level.
|
||
|
||
Arguments:
|
||
|
||
Number - Supplies the lock queue number.
|
||
|
||
OldIrql - Supplies a pointer to a variable that receives the previous
|
||
IRQL value.
|
||
|
||
Return Value:
|
||
|
||
A value of TRUE is returned if the spin lock is acquired. Otherwise,
|
||
a value of FALSE is returned.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
PKSPIN_LOCK Lock;
|
||
|
||
//
|
||
// N.B. It is safe to use any PRCB address since the backpointer
|
||
// to the actual spinlock is always the same.
|
||
//
|
||
|
||
Lock = KeGetCurrentPrcb()->LockQueue[Number].Lock;
|
||
return KeTryToAcquireSpinLock(Lock, OldIrql);
|
||
}
|
||
|
||
KIRQL
|
||
FASTCALL
|
||
KeAcquireQueuedSpinLockRaiseToSynch (
|
||
IN KSPIN_LOCK_QUEUE_NUMBER Number
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function acquires a queued spin lock and raises IRQL to synch
|
||
level.
|
||
|
||
Arguments:
|
||
|
||
Number - Supplies the lock queue number.
|
||
|
||
Return Value:
|
||
|
||
The previous IRQL is returned as the function value.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
PKSPIN_LOCK Lock;
|
||
|
||
//
|
||
// N.B. It is safe to use any PRCB address since the backpointer
|
||
// to the actual spinlock is always the same.
|
||
//
|
||
|
||
Lock = KeGetCurrentPrcb()->LockQueue[Number].Lock;
|
||
return KeAcquireSpinLockRaiseToSynch(Lock);
|
||
}
|
||
|
||
LOGICAL
|
||
FASTCALL
|
||
KeTryToAcquireQueuedSpinLockRaiseToSynch(
|
||
IN KSPIN_LOCK_QUEUE_NUMBER Number,
|
||
IN PKIRQL OldIrql
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function attempts to acquire a queued spin lock and raises IRQL
|
||
to synch level.
|
||
|
||
Arguments:
|
||
|
||
Number - Supplies the lock queue number.
|
||
|
||
OldIrql - Supplies a pointer to a variable that receives the previous
|
||
IRQL value.
|
||
|
||
Return Value:
|
||
|
||
A value of TRUE is returned if the spin lock is acquired. Otherwise,
|
||
a value of FALSE is returned.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
PKSPIN_LOCK Lock;
|
||
|
||
//
|
||
// N.B. It is safe to use any PRCB address since the backpointer
|
||
// to the actual spinlock is always the same.
|
||
//
|
||
|
||
Lock = KeGetCurrentPrcb()->LockQueue[Number].Lock;
|
||
*OldIrql = KeAcquireSpinLockRaiseToSynch(Lock);
|
||
return TRUE;
|
||
}
|
||
|
||
VOID
|
||
KeAcquireInStackQueuedSpinLock (
|
||
IN PKSPIN_LOCK SpinLock,
|
||
IN PKLOCK_QUEUE_HANDLE LockHandle
|
||
)
|
||
|
||
{
|
||
|
||
#if !defined(NT_UP)
|
||
|
||
LockHandle->LockQueue.Next = NULL;
|
||
LockHandle->LockQueue.Lock = SpinLock;
|
||
|
||
#endif
|
||
|
||
LockHandle->OldIrql = KeRaiseIrqlToDpcLevel();
|
||
|
||
#if !defined(NT_UP)
|
||
|
||
KeAcquireQueuedSpinLockAtDpcLevel(&LockHandle->LockQueue);
|
||
|
||
#endif
|
||
|
||
return;
|
||
}
|
||
|
||
VOID
|
||
KeAcquireInStackQueuedSpinLockRaiseToSynch (
|
||
IN PKSPIN_LOCK SpinLock,
|
||
IN PKLOCK_QUEUE_HANDLE LockHandle
|
||
)
|
||
|
||
{
|
||
|
||
#if !defined(NT_UP)
|
||
|
||
LockHandle->LockQueue.Next = NULL;
|
||
LockHandle->LockQueue.Lock = SpinLock;
|
||
|
||
#endif
|
||
|
||
LockHandle->OldIrql = KeRaiseIrqlToSynchLevel();
|
||
|
||
#if !defined(NT_UP)
|
||
|
||
KeAcquireQueuedSpinLockAtDpcLevel(&LockHandle->LockQueue);
|
||
|
||
#endif
|
||
|
||
return;
|
||
}
|
||
|
||
VOID
|
||
KeReleaseInStackQueuedSpinLock (
|
||
IN PKLOCK_QUEUE_HANDLE LockHandle
|
||
)
|
||
|
||
{
|
||
|
||
#if !defined(NT_UP)
|
||
|
||
KeReleaseQueuedSpinLockFromDpcLevel(&LockHandle->LockQueue);
|
||
|
||
#endif
|
||
|
||
KeLowerIrql(LockHandle->OldIrql);
|
||
return;
|
||
}
|
||
|
||
VOID
|
||
KeAcquireInStackQueuedSpinLockAtDpcLevel (
|
||
IN PKSPIN_LOCK SpinLock,
|
||
IN PKLOCK_QUEUE_HANDLE LockHandle
|
||
)
|
||
|
||
{
|
||
|
||
#if !defined(NT_UP)
|
||
|
||
LockHandle->LockQueue.Next = NULL;
|
||
LockHandle->LockQueue.Lock = SpinLock;
|
||
KeAcquireQueuedSpinLockAtDpcLevel(&LockHandle->LockQueue);
|
||
|
||
#endif
|
||
|
||
return;
|
||
}
|
||
|
||
VOID
|
||
KeReleaseInStackQueuedSpinLockFromDpcLevel (
|
||
IN PKLOCK_QUEUE_HANDLE LockHandle
|
||
)
|
||
|
||
{
|
||
|
||
#if !defined(NT_UP)
|
||
|
||
KeReleaseQueuedSpinLockFromDpcLevel(&LockHandle->LockQueue);
|
||
|
||
#endif
|
||
|
||
return;
|
||
}
|