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.
394 lines
6.3 KiB
394 lines
6.3 KiB
/*++
|
|
|
|
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;
|
|
}
|