Source code of Windows XP (NT5)
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

/*++
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;
}