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;
|
|||
|
}
|