2006-01-05 16:24:32 +00:00
|
|
|
|
/*
|
|
|
|
|
* PROJECT: ReactOS Kernel
|
2007-05-08 21:35:10 +00:00
|
|
|
|
* LICENSE: GPL - See COPYING in the top level directory
|
1999-05-29 00:15:17 +00:00
|
|
|
|
* FILE: ntoskrnl/ex/resource.c
|
2007-05-08 21:35:10 +00:00
|
|
|
|
* PURPOSE: Executive Resource Implementation
|
|
|
|
|
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
1998-08-25 04:27:26 +00:00
|
|
|
|
*/
|
1999-03-31 13:21:44 +00:00
|
|
|
|
|
1998-08-25 04:27:26 +00:00
|
|
|
|
/* INCLUDES *****************************************************************/
|
|
|
|
|
|
2004-08-15 16:39:12 +00:00
|
|
|
|
#include <ntoskrnl.h>
|
1999-11-12 12:01:17 +00:00
|
|
|
|
#define NDEBUG
|
2007-01-25 23:48:48 +00:00
|
|
|
|
#include <debug.h>
|
1998-08-25 04:27:26 +00:00
|
|
|
|
|
2006-01-05 16:24:32 +00:00
|
|
|
|
/* Macros for reading resource flags */
|
|
|
|
|
#define IsExclusiveWaiting(r) (r->NumberOfExclusiveWaiters)
|
|
|
|
|
#define IsSharedWaiting(r) (r->NumberOfSharedWaiters)
|
|
|
|
|
#define IsOwnedExclusive(r) (r->Flag & ResourceOwnedExclusive)
|
2007-05-08 21:35:10 +00:00
|
|
|
|
#define IsBoostAllowed(r) (!(r->Flag & ResourceHasDisabledPriorityBoost))
|
|
|
|
|
|
2009-06-17 12:44:05 +00:00
|
|
|
|
#if (!(defined(CONFIG_SMP)) && !(DBG))
|
2007-05-08 21:35:10 +00:00
|
|
|
|
|
|
|
|
|
FORCEINLINE
|
2008-12-03 17:28:59 +00:00
|
|
|
|
VOID
|
2008-04-22 20:44:34 +00:00
|
|
|
|
ExAcquireResourceLock(IN PERESOURCE Resource,
|
2007-05-08 21:35:10 +00:00
|
|
|
|
IN PKLOCK_QUEUE_HANDLE LockHandle)
|
|
|
|
|
{
|
|
|
|
|
UNREFERENCED_PARAMETER(Resource);
|
|
|
|
|
UNREFERENCED_PARAMETER(LockHandle);
|
|
|
|
|
|
|
|
|
|
/* Simply disable interrupts */
|
|
|
|
|
_disable();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FORCEINLINE
|
2008-12-03 17:28:59 +00:00
|
|
|
|
VOID
|
2008-04-22 20:44:34 +00:00
|
|
|
|
ExReleaseResourceLock(IN PERESOURCE Resource,
|
2007-05-08 21:35:10 +00:00
|
|
|
|
IN PKLOCK_QUEUE_HANDLE LockHandle)
|
|
|
|
|
{
|
|
|
|
|
UNREFERENCED_PARAMETER(Resource);
|
|
|
|
|
UNREFERENCED_PARAMETER(LockHandle);
|
|
|
|
|
|
|
|
|
|
/* Simply enable interrupts */
|
2008-04-01 12:58:11 +00:00
|
|
|
|
_enable();
|
2007-05-08 21:35:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
|
|
FORCEINLINE
|
2008-12-03 17:28:59 +00:00
|
|
|
|
VOID
|
2008-04-22 20:44:34 +00:00
|
|
|
|
ExAcquireResourceLock(IN PERESOURCE Resource,
|
2007-05-08 21:35:10 +00:00
|
|
|
|
IN PKLOCK_QUEUE_HANDLE LockHandle)
|
|
|
|
|
{
|
|
|
|
|
/* Acquire the lock */
|
|
|
|
|
KeAcquireInStackQueuedSpinLock(&Resource->SpinLock, LockHandle);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FORCEINLINE
|
2008-12-03 17:28:59 +00:00
|
|
|
|
VOID
|
2008-04-22 20:44:34 +00:00
|
|
|
|
ExReleaseResourceLock(IN PERESOURCE Resource,
|
2007-05-08 21:35:10 +00:00
|
|
|
|
IN PKLOCK_QUEUE_HANDLE LockHandle)
|
|
|
|
|
{
|
|
|
|
|
UNREFERENCED_PARAMETER(Resource);
|
|
|
|
|
|
|
|
|
|
/* Release the lock */
|
|
|
|
|
KeReleaseInStackQueuedSpinLock(LockHandle);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2002-09-08 10:23:54 +00:00
|
|
|
|
|
2006-01-05 16:24:32 +00:00
|
|
|
|
/* DATA***********************************************************************/
|
|
|
|
|
|
2007-05-08 21:35:10 +00:00
|
|
|
|
LARGE_INTEGER ExShortTime = {{-100000, -1}};
|
2006-01-05 16:24:32 +00:00
|
|
|
|
LARGE_INTEGER ExpTimeout;
|
|
|
|
|
ULONG ExpResourceTimeoutCount = 90 * 3600 / 2;
|
|
|
|
|
KSPIN_LOCK ExpResourceSpinLock;
|
|
|
|
|
LIST_ENTRY ExpSystemResourcesList;
|
2007-05-08 21:35:10 +00:00
|
|
|
|
BOOLEAN ExResourceStrict = TRUE;
|
2006-01-05 16:24:32 +00:00
|
|
|
|
|
|
|
|
|
/* PRIVATE FUNCTIONS *********************************************************/
|
|
|
|
|
|
|
|
|
|
#if DBG
|
|
|
|
|
/*++
|
|
|
|
|
* @name ExpVerifyResource
|
|
|
|
|
*
|
|
|
|
|
* The ExpVerifyResource routine verifies the correctness of an ERESOURCE
|
|
|
|
|
*
|
|
|
|
|
* @param Resource
|
|
|
|
|
* Pointer to the resource being verified.
|
|
|
|
|
*
|
|
|
|
|
* @return None.
|
|
|
|
|
*
|
|
|
|
|
* @remarks Only present on DBG builds.
|
|
|
|
|
*
|
|
|
|
|
*--*/
|
|
|
|
|
VOID
|
|
|
|
|
NTAPI
|
2008-04-22 20:44:34 +00:00
|
|
|
|
ExpVerifyResource(IN PERESOURCE Resource)
|
2002-09-08 10:23:54 +00:00
|
|
|
|
{
|
2006-01-05 16:24:32 +00:00
|
|
|
|
/* Verify the resource data */
|
|
|
|
|
ASSERT((((ULONG_PTR)Resource) & (sizeof(ULONG_PTR) - 1)) == 0);
|
|
|
|
|
ASSERT(!Resource->SharedWaiters ||
|
|
|
|
|
Resource->SharedWaiters->Header.Type == SemaphoreObject);
|
|
|
|
|
ASSERT(!Resource->SharedWaiters ||
|
|
|
|
|
Resource->SharedWaiters->Header.Size == (sizeof(KSEMAPHORE) / sizeof(ULONG)));
|
|
|
|
|
ASSERT(!Resource->ExclusiveWaiters ||
|
|
|
|
|
Resource->ExclusiveWaiters->Header.Type == SynchronizationEvent);
|
|
|
|
|
ASSERT(!Resource->ExclusiveWaiters ||
|
|
|
|
|
Resource->ExclusiveWaiters->Header.Size == (sizeof(KEVENT) / sizeof(ULONG)));
|
2002-09-08 10:23:54 +00:00
|
|
|
|
}
|
|
|
|
|
|
2006-01-05 16:24:32 +00:00
|
|
|
|
/*++
|
|
|
|
|
* @name ExpCheckForApcsDisabled
|
|
|
|
|
*
|
|
|
|
|
* The ExpCheckForApcsDisabled routine checks if Kernel APCs are still
|
|
|
|
|
* enabled when they should be disabled, and optionally breakpoints.
|
|
|
|
|
*
|
2007-05-08 21:35:10 +00:00
|
|
|
|
* @param Irql
|
|
|
|
|
* Specifies the IRQL during the acquire attempt.
|
2006-01-05 16:24:32 +00:00
|
|
|
|
*
|
|
|
|
|
* @param Resource
|
|
|
|
|
* Pointer to the resource being checked.
|
|
|
|
|
*
|
|
|
|
|
* @param Thread
|
|
|
|
|
* Pointer to the thread being checked.
|
|
|
|
|
*
|
|
|
|
|
* @return None.
|
|
|
|
|
*
|
|
|
|
|
* @remarks Only present on DBG builds. Depends on ExResourceStrict value.
|
|
|
|
|
*
|
|
|
|
|
*--*/
|
|
|
|
|
VOID
|
|
|
|
|
NTAPI
|
2007-05-08 21:35:10 +00:00
|
|
|
|
ExpCheckForApcsDisabled(IN KIRQL Irql,
|
2008-04-22 20:44:34 +00:00
|
|
|
|
IN PERESOURCE Resource,
|
2007-05-08 21:35:10 +00:00
|
|
|
|
IN PKTHREAD Thread)
|
2006-01-05 16:24:32 +00:00
|
|
|
|
{
|
|
|
|
|
/* Check if we should care and check if we should break */
|
|
|
|
|
if ((ExResourceStrict) &&
|
2008-04-22 20:44:34 +00:00
|
|
|
|
(Irql < APC_LEVEL) &&
|
2007-05-08 21:35:10 +00:00
|
|
|
|
!(((PETHREAD)Thread)->SystemThread) &&
|
|
|
|
|
!(Thread->CombinedApcDisable))
|
2006-01-05 16:24:32 +00:00
|
|
|
|
{
|
|
|
|
|
/* Bad! */
|
|
|
|
|
DPRINT1("EX: resource: APCs still enabled before resource %p acquire "
|
|
|
|
|
"!!!\n", Resource);
|
|
|
|
|
DbgBreakPoint();
|
|
|
|
|
}
|
|
|
|
|
}
|
2006-03-04 17:27:40 +00:00
|
|
|
|
#else
|
|
|
|
|
#define ExpVerifyResource(r)
|
|
|
|
|
#define ExpCheckForApcsDisabled(b,r,t)
|
2003-07-15 16:26:18 +00:00
|
|
|
|
#endif
|
|
|
|
|
|
2006-01-05 16:24:32 +00:00
|
|
|
|
/*++
|
|
|
|
|
* @name ExpResourceInitialization
|
|
|
|
|
*
|
|
|
|
|
* The ExpResourceInitialization routine initializes resources for use.
|
|
|
|
|
*
|
|
|
|
|
* @param None.
|
|
|
|
|
*
|
|
|
|
|
* @return None.
|
|
|
|
|
*
|
|
|
|
|
* @remarks This routine should only be called once, during system startup.
|
|
|
|
|
*
|
|
|
|
|
*--*/
|
|
|
|
|
VOID
|
|
|
|
|
NTAPI
|
|
|
|
|
INIT_FUNCTION
|
|
|
|
|
ExpResourceInitialization(VOID)
|
|
|
|
|
{
|
|
|
|
|
/* Setup the timeout */
|
|
|
|
|
ExpTimeout.QuadPart = Int32x32To64(4, -10000000);
|
|
|
|
|
InitializeListHead(&ExpSystemResourcesList);
|
|
|
|
|
KeInitializeSpinLock(&ExpResourceSpinLock);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*++
|
|
|
|
|
* @name ExpAllocateExclusiveWaiterEvent
|
|
|
|
|
*
|
|
|
|
|
* The ExpAllocateExclusiveWaiterEvent routine creates the event that will
|
|
|
|
|
* be used by exclusive waiters on the resource.
|
|
|
|
|
*
|
|
|
|
|
* @param Resource
|
|
|
|
|
* Pointer to the resource.
|
|
|
|
|
*
|
2007-05-08 21:35:10 +00:00
|
|
|
|
* @param LockHandle
|
|
|
|
|
* Pointer to in-stack queued spinlock.
|
2006-01-05 16:24:32 +00:00
|
|
|
|
*
|
|
|
|
|
* @return None.
|
|
|
|
|
*
|
|
|
|
|
* @remarks The pointer to the event must be atomically set.
|
|
|
|
|
*
|
|
|
|
|
*--*/
|
|
|
|
|
VOID
|
|
|
|
|
NTAPI
|
2008-04-22 20:44:34 +00:00
|
|
|
|
ExpAllocateExclusiveWaiterEvent(IN PERESOURCE Resource,
|
2007-05-08 21:35:10 +00:00
|
|
|
|
IN PKLOCK_QUEUE_HANDLE LockHandle)
|
2006-01-05 16:24:32 +00:00
|
|
|
|
{
|
|
|
|
|
PKEVENT Event;
|
|
|
|
|
|
|
|
|
|
/* Release the lock */
|
2007-05-08 21:35:10 +00:00
|
|
|
|
ExReleaseResourceLock(Resource, LockHandle);
|
|
|
|
|
|
|
|
|
|
/* Loop as long as we keep running out of memory */
|
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
/* Allocate the event */
|
|
|
|
|
Event = ExAllocatePoolWithTag(NonPagedPool,
|
|
|
|
|
sizeof(KEVENT),
|
|
|
|
|
TAG_RESOURCE_EVENT);
|
|
|
|
|
if (Event)
|
|
|
|
|
{
|
|
|
|
|
/* Initialize it */
|
|
|
|
|
KeInitializeEvent(Event, SynchronizationEvent, FALSE);
|
2006-01-05 16:24:32 +00:00
|
|
|
|
|
2007-05-08 21:35:10 +00:00
|
|
|
|
/* Set it */
|
2010-01-13 22:35:43 +00:00
|
|
|
|
if (InterlockedCompareExchangePointer((PVOID*)&Resource->ExclusiveWaiters,
|
2007-05-08 21:35:10 +00:00
|
|
|
|
Event,
|
|
|
|
|
NULL))
|
|
|
|
|
{
|
|
|
|
|
/* Someone already set it, free our event */
|
|
|
|
|
DPRINT1("WARNING: Handling race condition\n");
|
|
|
|
|
ExFreePool(Event);
|
|
|
|
|
}
|
2006-01-05 16:24:32 +00:00
|
|
|
|
|
2007-05-08 21:35:10 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
2006-01-05 16:24:32 +00:00
|
|
|
|
|
2007-05-08 21:35:10 +00:00
|
|
|
|
/* Wait a bit before trying again */
|
|
|
|
|
KeDelayExecutionThread(KernelMode, FALSE, &ExShortTime);
|
|
|
|
|
} while (TRUE);
|
2006-01-05 16:24:32 +00:00
|
|
|
|
|
|
|
|
|
/* Re-acquire the lock */
|
2007-05-08 21:35:10 +00:00
|
|
|
|
ExAcquireResourceLock(Resource, LockHandle);
|
2006-01-05 16:24:32 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*++
|
|
|
|
|
* @name ExpAllocateSharedWaiterSemaphore
|
|
|
|
|
*
|
|
|
|
|
* The ExpAllocateSharedWaiterSemaphore routine creates the semaphore that
|
|
|
|
|
* will be used by shared waiters on the resource.
|
|
|
|
|
*
|
|
|
|
|
* @param Resource
|
|
|
|
|
* Pointer to the resource.
|
|
|
|
|
*
|
2007-05-08 21:35:10 +00:00
|
|
|
|
* @param LockHandle
|
|
|
|
|
* Pointer to in-stack queued spinlock.
|
2006-01-05 16:24:32 +00:00
|
|
|
|
*
|
|
|
|
|
* @return None.
|
|
|
|
|
*
|
|
|
|
|
* @remarks The pointer to the semaphore must be atomically set.
|
|
|
|
|
*
|
|
|
|
|
*--*/
|
|
|
|
|
VOID
|
|
|
|
|
NTAPI
|
2008-04-22 20:44:34 +00:00
|
|
|
|
ExpAllocateSharedWaiterSemaphore(IN PERESOURCE Resource,
|
2007-05-08 21:35:10 +00:00
|
|
|
|
IN PKLOCK_QUEUE_HANDLE LockHandle)
|
2006-01-05 16:24:32 +00:00
|
|
|
|
{
|
|
|
|
|
PKSEMAPHORE Semaphore;
|
|
|
|
|
|
|
|
|
|
/* Release the lock */
|
2007-05-08 21:35:10 +00:00
|
|
|
|
ExReleaseResourceLock(Resource, LockHandle);
|
2006-01-05 16:24:32 +00:00
|
|
|
|
|
2007-05-08 21:35:10 +00:00
|
|
|
|
/* Loop as long as we keep running out of memory */
|
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
/* Allocate the semaphore */
|
|
|
|
|
Semaphore = ExAllocatePoolWithTag(NonPagedPool,
|
|
|
|
|
sizeof(KSEMAPHORE),
|
|
|
|
|
TAG_RESOURCE_SEMAPHORE);
|
|
|
|
|
if (Semaphore)
|
|
|
|
|
{
|
|
|
|
|
/* Initialize it */
|
|
|
|
|
KeInitializeSemaphore(Semaphore, 0, MAXLONG);
|
2006-01-05 16:24:32 +00:00
|
|
|
|
|
2007-05-08 21:35:10 +00:00
|
|
|
|
/* Set it */
|
2010-01-13 22:35:43 +00:00
|
|
|
|
if (InterlockedCompareExchangePointer((PVOID*)&Resource->SharedWaiters,
|
2007-05-08 21:35:10 +00:00
|
|
|
|
Semaphore,
|
|
|
|
|
NULL))
|
|
|
|
|
{
|
|
|
|
|
/* Someone already set it, free our semaphore */
|
|
|
|
|
DPRINT1("WARNING: Handling race condition\n");
|
|
|
|
|
ExFreePool(Semaphore);
|
|
|
|
|
}
|
2006-01-05 16:24:32 +00:00
|
|
|
|
|
2007-05-08 21:35:10 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Wait a bit before trying again */
|
|
|
|
|
KeDelayExecutionThread(KernelMode, FALSE, &ExShortTime);
|
|
|
|
|
} while (TRUE);
|
2006-01-05 16:24:32 +00:00
|
|
|
|
|
|
|
|
|
/* Re-acquire the lock */
|
2007-05-08 21:35:10 +00:00
|
|
|
|
ExAcquireResourceLock(Resource, LockHandle);
|
2006-01-05 16:24:32 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*++
|
|
|
|
|
* @name ExpExpandResourceOwnerTable
|
|
|
|
|
*
|
|
|
|
|
* The ExpExpandResourceOwnerTable routine expands the owner table of the
|
|
|
|
|
* specified resource.
|
|
|
|
|
*
|
|
|
|
|
* @param Resource
|
|
|
|
|
* Pointer to the resource.
|
|
|
|
|
*
|
2007-05-08 21:35:10 +00:00
|
|
|
|
* @param LockHandle
|
|
|
|
|
* Pointer to in-stack queued spinlock.
|
2006-01-05 16:24:32 +00:00
|
|
|
|
*
|
|
|
|
|
* @return None.
|
|
|
|
|
*
|
|
|
|
|
* @remarks None.
|
|
|
|
|
*
|
|
|
|
|
*--*/
|
|
|
|
|
VOID
|
|
|
|
|
NTAPI
|
2008-04-22 20:44:34 +00:00
|
|
|
|
ExpExpandResourceOwnerTable(IN PERESOURCE Resource,
|
2007-05-08 21:35:10 +00:00
|
|
|
|
IN PKLOCK_QUEUE_HANDLE LockHandle)
|
2006-01-05 16:24:32 +00:00
|
|
|
|
{
|
|
|
|
|
POWNER_ENTRY Owner, Table;
|
2007-05-08 21:35:10 +00:00
|
|
|
|
KIRQL OldIrql;
|
2006-01-05 16:24:32 +00:00
|
|
|
|
ULONG NewSize, OldSize;
|
|
|
|
|
|
|
|
|
|
/* Get the owner table */
|
|
|
|
|
Owner = Resource->OwnerTable;
|
|
|
|
|
if (!Owner)
|
|
|
|
|
{
|
|
|
|
|
/* Start with the default size of 3 */
|
|
|
|
|
OldSize = 0;
|
|
|
|
|
NewSize = 3;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* Add 4 more entries */
|
|
|
|
|
OldSize = Owner->TableSize;
|
|
|
|
|
NewSize = OldSize + 4;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Release the lock */
|
2007-05-08 21:35:10 +00:00
|
|
|
|
ExReleaseResourceLock(Resource, LockHandle);
|
2006-01-05 16:24:32 +00:00
|
|
|
|
|
|
|
|
|
/* Allocate memory for the table */
|
|
|
|
|
Table = ExAllocatePoolWithTag(NonPagedPool,
|
|
|
|
|
NewSize * sizeof(OWNER_ENTRY),
|
|
|
|
|
TAG_RESOURCE_TABLE);
|
|
|
|
|
|
|
|
|
|
/* Zero the table */
|
2007-01-25 23:48:48 +00:00
|
|
|
|
RtlZeroMemory(Table + OldSize,
|
2006-01-05 16:24:32 +00:00
|
|
|
|
(NewSize - OldSize) * sizeof(OWNER_ENTRY));
|
|
|
|
|
|
|
|
|
|
/* Lock the resource */
|
2007-05-08 21:35:10 +00:00
|
|
|
|
ExAcquireResourceLock(Resource, LockHandle);
|
2006-01-05 16:24:32 +00:00
|
|
|
|
|
|
|
|
|
/* Make sure nothing has changed */
|
|
|
|
|
if ((Owner != Resource->OwnerTable) ||
|
2007-05-08 21:35:10 +00:00
|
|
|
|
((Owner) && (OldSize != Owner->TableSize)))
|
2006-01-05 16:24:32 +00:00
|
|
|
|
{
|
|
|
|
|
/* Resource changed while we weren't holding the lock; bail out */
|
2007-05-08 21:35:10 +00:00
|
|
|
|
ExReleaseResourceLock(Resource, LockHandle);
|
2006-01-05 16:24:32 +00:00
|
|
|
|
ExFreePool(Table);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* Copy the table */
|
2007-05-08 21:35:10 +00:00
|
|
|
|
RtlCopyMemory(Table, Owner, OldSize * sizeof(OWNER_ENTRY));
|
2006-01-05 16:24:32 +00:00
|
|
|
|
|
|
|
|
|
/* Acquire dispatcher lock to prevent thread boosting */
|
2007-05-08 21:35:10 +00:00
|
|
|
|
OldIrql = KiAcquireDispatcherLock();
|
2006-01-05 16:24:32 +00:00
|
|
|
|
|
|
|
|
|
/* Set the new table data */
|
|
|
|
|
Table->TableSize = NewSize;
|
|
|
|
|
Resource->OwnerTable = Table;
|
|
|
|
|
|
2007-01-25 23:48:48 +00:00
|
|
|
|
/* Release dispatcher lock */
|
2007-05-08 21:35:10 +00:00
|
|
|
|
KiReleaseDispatcherLock(OldIrql);
|
2007-01-25 23:48:48 +00:00
|
|
|
|
|
2006-01-05 16:24:32 +00:00
|
|
|
|
/* Sanity check */
|
|
|
|
|
ExpVerifyResource(Resource);
|
|
|
|
|
|
2007-01-25 23:48:48 +00:00
|
|
|
|
/* Release lock */
|
2007-05-08 21:35:10 +00:00
|
|
|
|
ExReleaseResourceLock(Resource, LockHandle);
|
2006-01-05 16:24:32 +00:00
|
|
|
|
|
|
|
|
|
/* Free the old table */
|
|
|
|
|
if (Owner) ExFreePool(Owner);
|
|
|
|
|
|
|
|
|
|
/* Set the resource index */
|
|
|
|
|
if (!OldSize) OldSize = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Set the resource index */
|
|
|
|
|
KeGetCurrentThread()->ResourceIndex = (UCHAR)OldSize;
|
|
|
|
|
|
|
|
|
|
/* Lock the resource again */
|
2007-05-08 21:35:10 +00:00
|
|
|
|
ExAcquireResourceLock(Resource, LockHandle);
|
2006-01-05 16:24:32 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*++
|
|
|
|
|
* @name ExpFindFreeEntry
|
|
|
|
|
*
|
|
|
|
|
* The ExpFindFreeEntry routine locates an empty owner entry in the
|
|
|
|
|
* specified resource. If none was found, then the owner table is
|
|
|
|
|
* expanded.
|
|
|
|
|
*
|
|
|
|
|
* @param Resource
|
|
|
|
|
* Pointer to the resource.
|
|
|
|
|
*
|
2007-05-08 21:35:10 +00:00
|
|
|
|
* @param LockHandle
|
|
|
|
|
* Pointer to in-stack queued spinlock.
|
2006-01-05 16:24:32 +00:00
|
|
|
|
*
|
|
|
|
|
* @return Pointer to an empty OWNER_ENTRY structure.
|
|
|
|
|
*
|
|
|
|
|
* @remarks None.
|
|
|
|
|
*
|
|
|
|
|
*--*/
|
|
|
|
|
POWNER_ENTRY
|
|
|
|
|
FASTCALL
|
2008-04-22 20:44:34 +00:00
|
|
|
|
ExpFindFreeEntry(IN PERESOURCE Resource,
|
2007-05-08 21:35:10 +00:00
|
|
|
|
IN PKLOCK_QUEUE_HANDLE LockHandle)
|
2006-01-05 16:24:32 +00:00
|
|
|
|
{
|
|
|
|
|
POWNER_ENTRY Owner, Limit;
|
|
|
|
|
|
|
|
|
|
/* Sanity check */
|
2007-05-08 21:35:10 +00:00
|
|
|
|
ASSERT(LockHandle != 0);
|
2008-04-22 20:44:34 +00:00
|
|
|
|
ASSERT(Resource->OwnerEntry.OwnerThread != 0);
|
2006-01-05 16:24:32 +00:00
|
|
|
|
|
2008-04-22 20:44:34 +00:00
|
|
|
|
/* Get the current table pointer */
|
|
|
|
|
Owner = Resource->OwnerTable;
|
|
|
|
|
if (Owner)
|
2006-01-05 16:24:32 +00:00
|
|
|
|
{
|
2008-04-22 20:44:34 +00:00
|
|
|
|
/* Set the limit, move to the next owner and loop owner entries */
|
|
|
|
|
Limit = &Owner[Owner->TableSize];
|
|
|
|
|
Owner++;
|
|
|
|
|
while (Owner->OwnerThread)
|
2006-01-05 16:24:32 +00:00
|
|
|
|
{
|
2008-04-22 20:44:34 +00:00
|
|
|
|
/* Move to the next one */
|
2006-01-05 16:24:32 +00:00
|
|
|
|
Owner++;
|
2008-04-22 20:44:34 +00:00
|
|
|
|
|
|
|
|
|
/* Check if the entry is free */
|
|
|
|
|
if (Owner == Limit) goto Expand;
|
2006-01-05 16:24:32 +00:00
|
|
|
|
}
|
2008-04-22 20:44:34 +00:00
|
|
|
|
|
|
|
|
|
/* Update the resource entry */
|
|
|
|
|
KeGetCurrentThread()->ResourceIndex = (UCHAR)(Owner - Resource->OwnerTable);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Expand:
|
2006-01-05 16:24:32 +00:00
|
|
|
|
/* No free entry, expand the table */
|
2007-05-08 21:35:10 +00:00
|
|
|
|
ExpExpandResourceOwnerTable(Resource, LockHandle);
|
2008-04-22 20:44:34 +00:00
|
|
|
|
Owner = NULL;
|
2006-01-05 16:24:32 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Return the entry found */
|
2008-04-22 20:44:34 +00:00
|
|
|
|
return Owner;
|
2006-01-05 16:24:32 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*++
|
|
|
|
|
* @name ExpFindEntryForThread
|
|
|
|
|
*
|
|
|
|
|
* The ExpFindEntryForThread routine locates the owner entry associated with
|
|
|
|
|
* the specified thread in the given resource. If none was found, then the
|
|
|
|
|
* owner table is expanded.
|
|
|
|
|
*
|
|
|
|
|
* @param Resource
|
|
|
|
|
* Pointer to the resource.
|
|
|
|
|
*
|
|
|
|
|
* @param Thread
|
|
|
|
|
* Pointer to the thread to find.
|
|
|
|
|
*
|
2007-05-08 21:35:10 +00:00
|
|
|
|
* @param LockHandle
|
|
|
|
|
* Pointer to in-stack queued spinlock.
|
2006-01-05 16:24:32 +00:00
|
|
|
|
*
|
|
|
|
|
* @return Pointer to an empty OWNER_ENTRY structure.
|
|
|
|
|
*
|
|
|
|
|
* @remarks None.
|
|
|
|
|
*
|
|
|
|
|
*--*/
|
|
|
|
|
POWNER_ENTRY
|
|
|
|
|
FASTCALL
|
2008-04-22 20:44:34 +00:00
|
|
|
|
ExpFindEntryForThread(IN PERESOURCE Resource,
|
2006-01-05 16:24:32 +00:00
|
|
|
|
IN ERESOURCE_THREAD Thread,
|
2008-04-22 20:44:34 +00:00
|
|
|
|
IN PKLOCK_QUEUE_HANDLE LockHandle,
|
|
|
|
|
IN BOOLEAN FirstEntryInelligible)
|
2006-01-05 16:24:32 +00:00
|
|
|
|
{
|
|
|
|
|
POWNER_ENTRY FreeEntry, Owner, Limit;
|
|
|
|
|
|
|
|
|
|
/* Start by looking in the static array */
|
2008-04-22 20:44:34 +00:00
|
|
|
|
Owner = &Resource->OwnerEntry;
|
2007-01-25 23:48:48 +00:00
|
|
|
|
if (Owner->OwnerThread == Thread) return Owner;
|
2006-01-05 16:24:32 +00:00
|
|
|
|
|
2007-01-25 23:48:48 +00:00
|
|
|
|
/* Check if this is a free entry */
|
2008-04-22 20:44:34 +00:00
|
|
|
|
if ((FirstEntryInelligible) || (Owner->OwnerThread))
|
|
|
|
|
{
|
|
|
|
|
/* No free entry */
|
|
|
|
|
FreeEntry = NULL;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* Use the first entry as our free entry */
|
|
|
|
|
FreeEntry = Owner;
|
|
|
|
|
}
|
2006-01-05 16:24:32 +00:00
|
|
|
|
|
2008-04-22 20:44:34 +00:00
|
|
|
|
/* Get the current table pointer */
|
2007-01-25 23:48:48 +00:00
|
|
|
|
Owner = Resource->OwnerTable;
|
|
|
|
|
if (Owner)
|
|
|
|
|
{
|
2008-04-22 20:44:34 +00:00
|
|
|
|
/* Set the limit, move to the next owner and loop owner entries */
|
2007-01-25 23:48:48 +00:00
|
|
|
|
Limit = &Owner[Owner->TableSize];
|
|
|
|
|
Owner++;
|
2008-04-22 20:44:34 +00:00
|
|
|
|
while (Owner->OwnerThread != Thread)
|
2007-01-25 23:48:48 +00:00
|
|
|
|
{
|
2008-04-22 20:44:34 +00:00
|
|
|
|
/* Check if we don't have a free entry */
|
|
|
|
|
if (!FreeEntry)
|
2006-01-05 16:24:32 +00:00
|
|
|
|
{
|
2008-04-22 20:44:34 +00:00
|
|
|
|
/* Check if this entry is free */
|
|
|
|
|
if (!Owner->OwnerThread)
|
|
|
|
|
{
|
|
|
|
|
/* Save it as our free entry */
|
|
|
|
|
FreeEntry = Owner;
|
|
|
|
|
}
|
2007-01-25 23:48:48 +00:00
|
|
|
|
}
|
2006-01-05 16:24:32 +00:00
|
|
|
|
|
2008-04-22 20:44:34 +00:00
|
|
|
|
/* Move to the next one */
|
2007-01-25 23:48:48 +00:00
|
|
|
|
Owner++;
|
2008-04-22 20:44:34 +00:00
|
|
|
|
|
|
|
|
|
/* Check if the entry is free */
|
|
|
|
|
if (Owner == Limit) goto Expand;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Update the resource entry */
|
|
|
|
|
KeGetCurrentThread()->ResourceIndex = (UCHAR)(Owner - Resource->OwnerTable);
|
|
|
|
|
return Owner;
|
|
|
|
|
}
|
|
|
|
|
else
|
2006-01-05 16:24:32 +00:00
|
|
|
|
{
|
2008-04-22 20:44:34 +00:00
|
|
|
|
Expand:
|
|
|
|
|
/* Check if it's OK to do an expansion */
|
|
|
|
|
if (!LockHandle) return NULL;
|
|
|
|
|
|
|
|
|
|
/* If we found a free entry by now, return it */
|
|
|
|
|
if (FreeEntry)
|
|
|
|
|
{
|
|
|
|
|
/* Set the resource index */
|
|
|
|
|
KeGetCurrentThread()->ResourceIndex = (UCHAR)(FreeEntry - Resource->OwnerTable);
|
|
|
|
|
return FreeEntry;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* No free entry, expand the table */
|
|
|
|
|
ExpExpandResourceOwnerTable(Resource, LockHandle);
|
|
|
|
|
return NULL;
|
2006-01-05 16:24:32 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*++
|
|
|
|
|
* @name ExpBoostOwnerThread
|
|
|
|
|
*
|
|
|
|
|
* The ExpBoostOwnerThread routine increases the priority of a waiting
|
|
|
|
|
* thread in an attempt to fight a possible deadlock.
|
|
|
|
|
*
|
|
|
|
|
* @param Thread
|
|
|
|
|
* Pointer to the current thread.
|
|
|
|
|
*
|
|
|
|
|
* @param OwnerThread
|
|
|
|
|
* Pointer to thread that owns the resource.
|
|
|
|
|
*
|
|
|
|
|
* @return None.
|
|
|
|
|
*
|
|
|
|
|
* @remarks None.
|
|
|
|
|
*
|
|
|
|
|
*--*/
|
|
|
|
|
VOID
|
|
|
|
|
FASTCALL
|
|
|
|
|
ExpBoostOwnerThread(IN PKTHREAD Thread,
|
|
|
|
|
IN PKTHREAD OwnerThread)
|
|
|
|
|
{
|
|
|
|
|
/* Make sure the owner thread is a pointer, not an ID */
|
|
|
|
|
if (!((ULONG_PTR)OwnerThread & 0x3))
|
|
|
|
|
{
|
|
|
|
|
/* Check if we can actually boost it */
|
|
|
|
|
if ((OwnerThread->Priority < Thread->Priority) &&
|
|
|
|
|
(OwnerThread->Priority < 14))
|
|
|
|
|
{
|
2007-01-25 23:48:48 +00:00
|
|
|
|
/* Acquire the thread lock */
|
|
|
|
|
KiAcquireThreadLock(Thread);
|
2006-01-05 16:24:32 +00:00
|
|
|
|
|
|
|
|
|
/* Set the new priority */
|
|
|
|
|
OwnerThread->PriorityDecrement += 14 - OwnerThread->Priority;
|
|
|
|
|
|
|
|
|
|
/* Update quantum */
|
|
|
|
|
OwnerThread->Quantum = OwnerThread->QuantumReset;
|
|
|
|
|
|
|
|
|
|
/* Update the kernel state */
|
2007-01-25 23:48:48 +00:00
|
|
|
|
KiSetPriorityThread(OwnerThread, 14);
|
2006-01-05 16:24:32 +00:00
|
|
|
|
|
2007-01-25 23:48:48 +00:00
|
|
|
|
/* Release the thread lock */
|
|
|
|
|
KiReleaseThreadLock(Thread);
|
2006-01-05 16:24:32 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*++
|
|
|
|
|
* @name ExpWaitForResource
|
|
|
|
|
*
|
|
|
|
|
* The ExpWaitForResource routine performs a wait on the specified resource.
|
|
|
|
|
*
|
|
|
|
|
* @param Resource
|
|
|
|
|
* Pointer to the resource to wait on.
|
|
|
|
|
*
|
|
|
|
|
* @param OwnerThread
|
|
|
|
|
* Pointer to object (exclusive event or shared semaphore) to wait on.
|
|
|
|
|
*
|
|
|
|
|
* @return None.
|
|
|
|
|
*
|
|
|
|
|
* @remarks None.
|
|
|
|
|
*
|
|
|
|
|
*--*/
|
|
|
|
|
VOID
|
|
|
|
|
FASTCALL
|
2008-04-22 20:44:34 +00:00
|
|
|
|
ExpWaitForResource(IN PERESOURCE Resource,
|
2006-01-05 16:24:32 +00:00
|
|
|
|
IN PVOID Object)
|
|
|
|
|
{
|
|
|
|
|
ULONG i;
|
2006-03-04 17:27:40 +00:00
|
|
|
|
ULONG Size;
|
2006-01-05 16:24:32 +00:00
|
|
|
|
POWNER_ENTRY Owner;
|
2006-03-04 17:27:40 +00:00
|
|
|
|
ULONG WaitCount = 0;
|
2006-01-05 16:24:32 +00:00
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
LARGE_INTEGER Timeout;
|
2007-01-25 23:48:48 +00:00
|
|
|
|
PKTHREAD Thread, OwnerThread;
|
|
|
|
|
#if DBG
|
2007-05-08 21:35:10 +00:00
|
|
|
|
KLOCK_QUEUE_HANDLE LockHandle;
|
2007-01-25 23:48:48 +00:00
|
|
|
|
#endif
|
2006-01-05 16:24:32 +00:00
|
|
|
|
|
|
|
|
|
/* Increase contention count and use a 5 second timeout */
|
|
|
|
|
Resource->ContentionCount++;
|
|
|
|
|
Timeout.QuadPart = 500 * -10000;
|
2007-01-25 23:48:48 +00:00
|
|
|
|
for (;;)
|
2006-01-05 16:24:32 +00:00
|
|
|
|
{
|
|
|
|
|
/* Wait for ownership */
|
|
|
|
|
Status = KeWaitForSingleObject(Object,
|
|
|
|
|
WrResource,
|
|
|
|
|
KernelMode,
|
|
|
|
|
FALSE,
|
|
|
|
|
&Timeout);
|
|
|
|
|
if (Status != STATUS_TIMEOUT) break;
|
|
|
|
|
|
|
|
|
|
/* Increase wait count */
|
|
|
|
|
WaitCount++;
|
|
|
|
|
Timeout = ExpTimeout;
|
|
|
|
|
|
|
|
|
|
/* Check if we've exceeded the limit */
|
|
|
|
|
if (WaitCount > ExpResourceTimeoutCount)
|
|
|
|
|
{
|
|
|
|
|
/* Reset wait count */
|
|
|
|
|
WaitCount = 0;
|
|
|
|
|
#if DBG
|
|
|
|
|
/* Lock the resource */
|
2007-05-08 21:35:10 +00:00
|
|
|
|
ExAcquireResourceLock(Resource, &LockHandle);
|
2006-01-05 16:24:32 +00:00
|
|
|
|
|
|
|
|
|
/* Dump debug information */
|
|
|
|
|
DPRINT1("Resource @ %lx\n", Resource);
|
2008-04-22 20:44:34 +00:00
|
|
|
|
DPRINT1(" ActiveEntries = %04lx Flags = %s%s%s\n",
|
|
|
|
|
Resource->ActiveEntries,
|
2006-01-05 16:24:32 +00:00
|
|
|
|
IsOwnedExclusive(Resource) ? "IsOwnedExclusive " : "",
|
|
|
|
|
IsSharedWaiting(Resource) ? "SharedWaiter " : "",
|
|
|
|
|
IsExclusiveWaiting(Resource) ? "ExclusiveWaiter " : "");
|
|
|
|
|
DPRINT1(" NumberOfExclusiveWaiters = %04lx\n",
|
|
|
|
|
Resource->NumberOfExclusiveWaiters);
|
|
|
|
|
DPRINT1(" Thread = %08lx, Count = %02x\n",
|
2008-04-22 20:44:34 +00:00
|
|
|
|
Resource->OwnerEntry.OwnerThread,
|
|
|
|
|
Resource->OwnerEntry.OwnerCount);
|
2006-01-05 16:24:32 +00:00
|
|
|
|
|
|
|
|
|
/* Dump out the table too */
|
|
|
|
|
Owner = Resource->OwnerTable;
|
|
|
|
|
if (Owner)
|
|
|
|
|
{
|
|
|
|
|
/* Loop every entry */
|
|
|
|
|
Size = Owner->TableSize;
|
|
|
|
|
for (i = 1; i < Size; i++)
|
|
|
|
|
{
|
|
|
|
|
/* Print the data */
|
|
|
|
|
Owner++;
|
|
|
|
|
DPRINT1(" Thread = %08lx, Count = %02x\n",
|
|
|
|
|
Owner->OwnerThread,
|
|
|
|
|
Owner->OwnerCount);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Break */
|
|
|
|
|
DbgBreakPoint();
|
|
|
|
|
DPRINT1("EX - Rewaiting\n");
|
2007-05-08 21:35:10 +00:00
|
|
|
|
ExReleaseResourceLock(Resource, &LockHandle);
|
2006-01-05 16:24:32 +00:00
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Check if we can boost */
|
2007-01-25 23:48:48 +00:00
|
|
|
|
if (IsBoostAllowed(Resource))
|
2006-01-05 16:24:32 +00:00
|
|
|
|
{
|
|
|
|
|
/* Get the current kernel thread and lock the dispatcher */
|
|
|
|
|
Thread = KeGetCurrentThread();
|
2006-09-10 18:26:50 +00:00
|
|
|
|
Thread->WaitIrql = KiAcquireDispatcherLock();
|
2006-01-05 16:24:32 +00:00
|
|
|
|
Thread->WaitNext = TRUE;
|
|
|
|
|
|
|
|
|
|
/* Get the owner thread and boost it */
|
2008-04-22 20:44:34 +00:00
|
|
|
|
OwnerThread = (PKTHREAD)Resource->OwnerEntry.OwnerThread;
|
2006-01-05 16:24:32 +00:00
|
|
|
|
if (OwnerThread) ExpBoostOwnerThread(Thread, OwnerThread);
|
|
|
|
|
|
|
|
|
|
/* If it's a shared resource */
|
|
|
|
|
if (!IsOwnedExclusive(Resource))
|
|
|
|
|
{
|
|
|
|
|
/* Get the table */
|
|
|
|
|
Owner = Resource->OwnerTable;
|
|
|
|
|
if (Owner)
|
|
|
|
|
{
|
|
|
|
|
/* Loop every entry */
|
|
|
|
|
Size = Owner->TableSize;
|
|
|
|
|
for (i = 1; i < Size; i++)
|
|
|
|
|
{
|
2006-01-13 00:15:31 +00:00
|
|
|
|
/* Move to next entry */
|
2006-01-13 00:16:51 +00:00
|
|
|
|
Owner++;
|
2006-01-13 00:15:31 +00:00
|
|
|
|
|
|
|
|
|
/* Get the thread */
|
2006-01-13 00:16:51 +00:00
|
|
|
|
OwnerThread = (PKTHREAD)Owner->OwnerThread;
|
2006-01-13 00:15:31 +00:00
|
|
|
|
|
|
|
|
|
/* Boost it */
|
2006-01-05 16:24:32 +00:00
|
|
|
|
if (OwnerThread) ExpBoostOwnerThread(Thread, OwnerThread);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* FUNCTIONS *****************************************************************/
|
|
|
|
|
|
|
|
|
|
/*++
|
|
|
|
|
* @name ExAcquireResourceExclusiveLite
|
|
|
|
|
* @implemented NT4
|
|
|
|
|
*
|
|
|
|
|
* The ExAcquireResourceExclusiveLite routine acquires the given resource
|
|
|
|
|
* for exclusive access by the calling thread.
|
|
|
|
|
*
|
|
|
|
|
* @param Resource
|
|
|
|
|
* Pointer to the resource to acquire.
|
|
|
|
|
*
|
|
|
|
|
* @param Wait
|
|
|
|
|
* Specifies the routine's behavior whenever the resource cannot be
|
|
|
|
|
* acquired immediately.
|
|
|
|
|
*
|
|
|
|
|
* @return TRUE if the resource is acquired. FALSE if the input Wait is FALSE
|
|
|
|
|
* and exclusive access cannot be granted immediately.
|
|
|
|
|
*
|
|
|
|
|
* @remarks The caller can release the resource by calling either
|
|
|
|
|
* ExReleaseResourceLite or ExReleaseResourceForThreadLite.
|
|
|
|
|
*
|
|
|
|
|
* Normal kernel APC delivery must be disabled before calling this
|
|
|
|
|
* routine. Disable normal kernel APC delivery by calling
|
|
|
|
|
* KeEnterCriticalRegion. Delivery must remain disabled until the
|
|
|
|
|
* resource is released, at which point it can be reenabled by calling
|
|
|
|
|
* KeLeaveCriticalRegion.
|
|
|
|
|
*
|
|
|
|
|
* For better performance, call ExTryToAcquireResourceExclusiveLite,
|
|
|
|
|
* rather than calling ExAcquireResourceExclusiveLite with Wait set
|
|
|
|
|
* to FALSE.
|
|
|
|
|
*
|
|
|
|
|
* Callers of ExAcquireResourceExclusiveLite must be running at IRQL <
|
|
|
|
|
* DISPATCH_LEVEL.
|
|
|
|
|
*
|
|
|
|
|
*--*/
|
2002-09-08 10:23:54 +00:00
|
|
|
|
BOOLEAN
|
2006-01-05 16:24:32 +00:00
|
|
|
|
NTAPI
|
2008-04-22 20:44:34 +00:00
|
|
|
|
ExAcquireResourceExclusiveLite(IN PERESOURCE Resource,
|
2007-05-08 21:35:10 +00:00
|
|
|
|
IN BOOLEAN Wait)
|
2002-09-08 10:23:54 +00:00
|
|
|
|
{
|
2007-05-08 21:35:10 +00:00
|
|
|
|
KLOCK_QUEUE_HANDLE LockHandle;
|
2006-01-05 16:24:32 +00:00
|
|
|
|
ERESOURCE_THREAD Thread;
|
|
|
|
|
BOOLEAN Success;
|
|
|
|
|
|
|
|
|
|
/* Sanity check */
|
|
|
|
|
ASSERT((Resource->Flag & ResourceNeverExclusive) == 0);
|
|
|
|
|
|
|
|
|
|
/* Get the thread */
|
|
|
|
|
Thread = ExGetCurrentResourceThread();
|
|
|
|
|
|
|
|
|
|
/* Sanity check and validation */
|
|
|
|
|
ASSERT(KeIsExecutingDpc() == FALSE);
|
|
|
|
|
ExpVerifyResource(Resource);
|
|
|
|
|
|
|
|
|
|
/* Acquire the lock */
|
2007-05-08 21:35:10 +00:00
|
|
|
|
ExAcquireResourceLock(Resource, &LockHandle);
|
|
|
|
|
ExpCheckForApcsDisabled(LockHandle.OldIrql, Resource, (PKTHREAD)Thread);
|
2006-01-05 16:24:32 +00:00
|
|
|
|
|
|
|
|
|
/* Check if there is a shared owner or exclusive owner */
|
|
|
|
|
TryAcquire:
|
2008-04-22 20:44:34 +00:00
|
|
|
|
if (Resource->ActiveEntries)
|
2006-01-05 16:24:32 +00:00
|
|
|
|
{
|
2008-04-22 20:44:34 +00:00
|
|
|
|
/* Check if it's exclusively owned, and we own it */
|
2006-01-05 16:24:32 +00:00
|
|
|
|
if ((IsOwnedExclusive(Resource)) &&
|
2008-04-22 20:44:34 +00:00
|
|
|
|
(Resource->OwnerEntry.OwnerThread == Thread))
|
2006-01-05 16:24:32 +00:00
|
|
|
|
{
|
|
|
|
|
/* Increase the owning count */
|
2008-04-22 20:44:34 +00:00
|
|
|
|
Resource->OwnerEntry.OwnerCount++;
|
2006-01-05 16:24:32 +00:00
|
|
|
|
Success = TRUE;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* If the caller doesn't want us to wait, we can't acquire the
|
|
|
|
|
* resource because someone else then us owns it. If we can wait,
|
|
|
|
|
* then we'll wait.
|
|
|
|
|
*/
|
|
|
|
|
if (!Wait)
|
|
|
|
|
{
|
|
|
|
|
Success = FALSE;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* Check if it has exclusive waiters */
|
|
|
|
|
if (!Resource->ExclusiveWaiters)
|
|
|
|
|
{
|
|
|
|
|
/* It doesn't, allocate the event and try acquiring again */
|
2007-05-08 21:35:10 +00:00
|
|
|
|
ExpAllocateExclusiveWaiterEvent(Resource, &LockHandle);
|
2006-01-05 16:24:32 +00:00
|
|
|
|
goto TryAcquire;
|
|
|
|
|
}
|
2007-05-08 21:35:10 +00:00
|
|
|
|
|
|
|
|
|
/* Has exclusive waiters, wait on it */
|
|
|
|
|
Resource->NumberOfExclusiveWaiters++;
|
|
|
|
|
ExReleaseResourceLock(Resource, &LockHandle);
|
|
|
|
|
ExpWaitForResource(Resource, Resource->ExclusiveWaiters);
|
|
|
|
|
|
|
|
|
|
/* Set owner and return success */
|
2008-04-22 20:44:34 +00:00
|
|
|
|
Resource->OwnerEntry.OwnerThread = ExGetCurrentResourceThread();
|
2007-05-08 21:35:10 +00:00
|
|
|
|
return TRUE;
|
2006-01-05 16:24:32 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* Nobody owns it, so let's! */
|
2008-04-22 20:44:34 +00:00
|
|
|
|
ASSERT(Resource->ActiveEntries == 0);
|
|
|
|
|
ASSERT(Resource->ActiveCount == 0);
|
2006-01-05 16:24:32 +00:00
|
|
|
|
Resource->Flag |= ResourceOwnedExclusive;
|
2008-04-22 20:44:34 +00:00
|
|
|
|
Resource->ActiveEntries = 1;
|
2006-01-05 16:24:32 +00:00
|
|
|
|
Resource->ActiveCount = 1;
|
2008-04-22 20:44:34 +00:00
|
|
|
|
Resource->OwnerEntry.OwnerThread = Thread;
|
|
|
|
|
Resource->OwnerEntry.OwnerCount = 1;
|
2006-01-05 16:24:32 +00:00
|
|
|
|
Success = TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Release the lock and return */
|
2007-05-08 21:35:10 +00:00
|
|
|
|
ExReleaseResourceLock(Resource, &LockHandle);
|
2006-01-05 16:24:32 +00:00
|
|
|
|
return Success;
|
2002-09-08 10:23:54 +00:00
|
|
|
|
}
|
|
|
|
|
|
2006-01-05 16:24:32 +00:00
|
|
|
|
/*++
|
|
|
|
|
* @name ExAcquireResourceSharedLite
|
|
|
|
|
* @implemented NT4
|
|
|
|
|
*
|
|
|
|
|
* The ExAcquireResourceSharedLite routine acquires the given resource
|
|
|
|
|
* for shared access by the calling thread.
|
|
|
|
|
*
|
|
|
|
|
* @param Resource
|
|
|
|
|
* Pointer to the resource to acquire.
|
|
|
|
|
*
|
|
|
|
|
* @param Wait
|
|
|
|
|
* Specifies the routine's behavior whenever the resource cannot be
|
|
|
|
|
* acquired immediately.
|
|
|
|
|
*
|
|
|
|
|
* @return TRUE if the resource is acquired. FALSE if the input Wait is FALSE
|
|
|
|
|
* and exclusive access cannot be granted immediately.
|
|
|
|
|
*
|
|
|
|
|
* @remarks The caller can release the resource by calling either
|
|
|
|
|
* ExReleaseResourceLite or ExReleaseResourceForThreadLite.
|
|
|
|
|
*
|
|
|
|
|
* Normal kernel APC delivery must be disabled before calling this
|
|
|
|
|
* routine. Disable normal kernel APC delivery by calling
|
|
|
|
|
* KeEnterCriticalRegion. Delivery must remain disabled until the
|
|
|
|
|
* resource is released, at which point it can be reenabled by calling
|
|
|
|
|
* KeLeaveCriticalRegion.
|
|
|
|
|
*
|
|
|
|
|
* Callers of ExAcquireResourceExclusiveLite must be running at IRQL <
|
|
|
|
|
* DISPATCH_LEVEL.
|
|
|
|
|
*
|
|
|
|
|
*--*/
|
|
|
|
|
BOOLEAN
|
|
|
|
|
NTAPI
|
2008-04-22 20:44:34 +00:00
|
|
|
|
ExAcquireResourceSharedLite(IN PERESOURCE Resource,
|
2007-05-08 21:35:10 +00:00
|
|
|
|
IN BOOLEAN Wait)
|
2006-01-05 16:24:32 +00:00
|
|
|
|
{
|
2007-05-08 21:35:10 +00:00
|
|
|
|
KLOCK_QUEUE_HANDLE LockHandle;
|
2006-01-05 16:24:32 +00:00
|
|
|
|
ERESOURCE_THREAD Thread;
|
2008-06-11 16:48:07 +00:00
|
|
|
|
POWNER_ENTRY Owner = NULL;
|
2008-04-22 20:44:34 +00:00
|
|
|
|
BOOLEAN FirstEntryBusy;
|
2006-01-05 16:24:32 +00:00
|
|
|
|
|
|
|
|
|
/* Get the thread */
|
|
|
|
|
Thread = ExGetCurrentResourceThread();
|
|
|
|
|
|
|
|
|
|
/* Sanity check and validation */
|
|
|
|
|
ASSERT(KeIsExecutingDpc() == FALSE);
|
|
|
|
|
ExpVerifyResource(Resource);
|
|
|
|
|
|
|
|
|
|
/* Acquire the lock */
|
2007-05-08 21:35:10 +00:00
|
|
|
|
ExAcquireResourceLock(Resource, &LockHandle);
|
|
|
|
|
ExpCheckForApcsDisabled(LockHandle.OldIrql, Resource, (PKTHREAD)Thread);
|
2006-01-05 16:24:32 +00:00
|
|
|
|
|
2008-04-22 20:44:34 +00:00
|
|
|
|
/* Check how many active entries we've got */
|
|
|
|
|
while (Resource->ActiveEntries != 0)
|
2006-01-05 16:24:32 +00:00
|
|
|
|
{
|
2008-04-22 20:44:34 +00:00
|
|
|
|
/* Check if it's exclusively owned */
|
|
|
|
|
if (IsOwnedExclusive(Resource))
|
2006-01-05 16:24:32 +00:00
|
|
|
|
{
|
2008-04-22 20:44:34 +00:00
|
|
|
|
/* Check if we own it */
|
|
|
|
|
if (Resource->OwnerEntry.OwnerThread == Thread)
|
|
|
|
|
{
|
|
|
|
|
/* Increase the owning count */
|
|
|
|
|
Resource->OwnerEntry.OwnerCount++;
|
|
|
|
|
|
|
|
|
|
/* Release the lock and return */
|
|
|
|
|
ExReleaseResourceLock(Resource, &LockHandle);
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Find a free entry */
|
|
|
|
|
Owner = ExpFindFreeEntry(Resource, &LockHandle);
|
|
|
|
|
if (!Owner) continue;
|
2006-01-05 16:24:32 +00:00
|
|
|
|
}
|
2008-04-22 20:44:34 +00:00
|
|
|
|
else
|
2006-01-05 16:24:32 +00:00
|
|
|
|
{
|
2008-04-22 20:44:34 +00:00
|
|
|
|
/* Resource is shared, find who owns it */
|
|
|
|
|
FirstEntryBusy = IsExclusiveWaiting(Resource);
|
|
|
|
|
Owner = ExpFindEntryForThread(Resource,
|
|
|
|
|
Thread,
|
|
|
|
|
&LockHandle,
|
|
|
|
|
FirstEntryBusy);
|
|
|
|
|
if (!Owner) continue;
|
|
|
|
|
|
|
|
|
|
/* Is it us? */
|
|
|
|
|
if (Owner->OwnerThread == Thread)
|
|
|
|
|
{
|
|
|
|
|
/* Increase acquire count and return */
|
|
|
|
|
Owner->OwnerCount++;
|
|
|
|
|
ASSERT(Owner->OwnerCount != 0);
|
|
|
|
|
|
|
|
|
|
/* Release the lock and return */
|
|
|
|
|
ExReleaseResourceLock(Resource, &LockHandle);
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Try to find if there are exclusive waiters */
|
|
|
|
|
if (!FirstEntryBusy)
|
|
|
|
|
{
|
|
|
|
|
/* There are none, so acquire it */
|
|
|
|
|
Owner->OwnerThread = Thread;
|
|
|
|
|
Owner->OwnerCount = 1;
|
|
|
|
|
|
|
|
|
|
/* Check how many active entries we had */
|
|
|
|
|
if (Resource->ActiveEntries == 0)
|
|
|
|
|
{
|
|
|
|
|
/* Set initial counts */
|
|
|
|
|
ASSERT(Resource->ActiveCount == 0);
|
|
|
|
|
Resource->ActiveEntries = 1;
|
|
|
|
|
Resource->ActiveCount = 1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* Increase active entries */
|
|
|
|
|
ASSERT(Resource->ActiveCount == 1);
|
|
|
|
|
Resource->ActiveEntries++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Release the lock and return */
|
|
|
|
|
ExReleaseResourceLock(Resource, &LockHandle);
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
2006-01-05 16:24:32 +00:00
|
|
|
|
}
|
2008-04-22 20:44:34 +00:00
|
|
|
|
|
|
|
|
|
/* If we got here, then we need to wait. Are we allowed? */
|
|
|
|
|
if (!Wait)
|
2006-01-05 16:24:32 +00:00
|
|
|
|
{
|
|
|
|
|
/* Release the lock and return */
|
2007-05-08 21:35:10 +00:00
|
|
|
|
ExReleaseResourceLock(Resource, &LockHandle);
|
2008-04-22 20:44:34 +00:00
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Check if we have a shared waiters semaphore */
|
|
|
|
|
if (!Resource->SharedWaiters)
|
|
|
|
|
{
|
|
|
|
|
/* Allocate it and try another acquire */
|
|
|
|
|
ExpAllocateSharedWaiterSemaphore(Resource, &LockHandle);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* We have shared waiters, wait for it */
|
|
|
|
|
break;
|
2006-01-05 16:24:32 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2008-04-22 20:44:34 +00:00
|
|
|
|
|
|
|
|
|
/* Did we get here because we don't have active entries? */
|
|
|
|
|
if (Resource->ActiveEntries == 0)
|
2006-01-05 16:24:32 +00:00
|
|
|
|
{
|
2008-04-22 20:44:34 +00:00
|
|
|
|
/* Acquire it */
|
|
|
|
|
ASSERT(Resource->ActiveEntries == 0);
|
|
|
|
|
ASSERT(Resource->ActiveCount == 0);
|
|
|
|
|
Resource->ActiveEntries = 1;
|
|
|
|
|
Resource->ActiveCount = 1;
|
|
|
|
|
Resource->OwnerEntry.OwnerThread = Thread;
|
|
|
|
|
Resource->OwnerEntry.OwnerCount = 1;
|
|
|
|
|
|
2006-01-05 16:24:32 +00:00
|
|
|
|
/* Release the lock and return */
|
2007-05-08 21:35:10 +00:00
|
|
|
|
ExReleaseResourceLock(Resource, &LockHandle);
|
2008-04-22 20:44:34 +00:00
|
|
|
|
return TRUE;
|
2006-01-05 16:24:32 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Now wait for the resource */
|
|
|
|
|
Owner->OwnerThread = Thread;
|
|
|
|
|
Owner->OwnerCount = 1;
|
|
|
|
|
Resource->NumberOfSharedWaiters++;
|
|
|
|
|
|
|
|
|
|
/* Release the lock and return */
|
2007-05-08 21:35:10 +00:00
|
|
|
|
ExReleaseResourceLock(Resource, &LockHandle);
|
2006-01-05 16:24:32 +00:00
|
|
|
|
ExpWaitForResource(Resource, Resource->SharedWaiters);
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*++
|
|
|
|
|
* @name ExAcquireSharedStarveExclusive
|
|
|
|
|
* @implemented NT4
|
|
|
|
|
*
|
|
|
|
|
* The ExAcquireSharedStarveExclusive routine acquires the given resource
|
|
|
|
|
* shared access without waiting for any pending attempts to acquire
|
|
|
|
|
* exclusive access to the same resource.
|
|
|
|
|
*
|
|
|
|
|
* @param Resource
|
|
|
|
|
* Pointer to the resource to acquire.
|
|
|
|
|
*
|
|
|
|
|
* @param Wait
|
|
|
|
|
* Specifies the routine's behavior whenever the resource cannot be
|
|
|
|
|
* acquired immediately.
|
|
|
|
|
*
|
|
|
|
|
* @return TRUE if the resource is acquired. FALSE if the input Wait is FALSE
|
|
|
|
|
* and exclusive access cannot be granted immediately.
|
|
|
|
|
*
|
|
|
|
|
* @remarks The caller can release the resource by calling either
|
|
|
|
|
* ExReleaseResourceLite or ExReleaseResourceForThreadLite.
|
|
|
|
|
*
|
|
|
|
|
* Normal kernel APC delivery must be disabled before calling this
|
|
|
|
|
* routine. Disable normal kernel APC delivery by calling
|
|
|
|
|
* KeEnterCriticalRegion. Delivery must remain disabled until the
|
|
|
|
|
* resource is released, at which point it can be reenabled by calling
|
|
|
|
|
* KeLeaveCriticalRegion.
|
|
|
|
|
*
|
|
|
|
|
* Callers of ExAcquireSharedStarveExclusive usually need quick access
|
|
|
|
|
* to a shared resource in order to save an exclusive accessor from
|
|
|
|
|
* doing redundant work. For example, a file system might call this
|
|
|
|
|
* routine to modify a cached resource, such as a BCB pinned in the
|
|
|
|
|
* cache, before the Cache Manager can acquire exclusive access to the
|
|
|
|
|
* resource and write the cache out to disk.
|
|
|
|
|
*
|
|
|
|
|
* Callers of ExAcquireResourceExclusiveLite must be running at IRQL <
|
|
|
|
|
* DISPATCH_LEVEL.
|
|
|
|
|
*
|
|
|
|
|
*--*/
|
2000-06-07 13:05:09 +00:00
|
|
|
|
BOOLEAN
|
2006-01-05 16:24:32 +00:00
|
|
|
|
NTAPI
|
2008-04-22 20:44:34 +00:00
|
|
|
|
ExAcquireSharedStarveExclusive(IN PERESOURCE Resource,
|
2007-05-08 21:35:10 +00:00
|
|
|
|
IN BOOLEAN Wait)
|
1999-05-29 00:15:17 +00:00
|
|
|
|
{
|
2007-05-08 21:35:10 +00:00
|
|
|
|
KLOCK_QUEUE_HANDLE LockHandle;
|
2006-01-05 16:24:32 +00:00
|
|
|
|
ERESOURCE_THREAD Thread;
|
|
|
|
|
POWNER_ENTRY Owner;
|
|
|
|
|
|
|
|
|
|
/* Get the thread */
|
|
|
|
|
Thread = ExGetCurrentResourceThread();
|
|
|
|
|
|
|
|
|
|
/* Sanity check and validation */
|
|
|
|
|
ASSERT(KeIsExecutingDpc() == FALSE);
|
|
|
|
|
ExpVerifyResource(Resource);
|
|
|
|
|
|
|
|
|
|
/* Acquire the lock */
|
2007-05-08 21:35:10 +00:00
|
|
|
|
ExAcquireResourceLock(Resource, &LockHandle);
|
2006-01-05 16:24:32 +00:00
|
|
|
|
|
2008-04-22 20:44:34 +00:00
|
|
|
|
/* See if anyone owns it */
|
2006-01-05 16:24:32 +00:00
|
|
|
|
TryAcquire:
|
2008-04-22 20:44:34 +00:00
|
|
|
|
if (Resource->ActiveEntries == 0)
|
2006-01-05 16:24:32 +00:00
|
|
|
|
{
|
|
|
|
|
/* Nobody owns it, so let's take control */
|
2008-04-22 20:44:34 +00:00
|
|
|
|
ASSERT(Resource->ActiveEntries == 0);
|
|
|
|
|
ASSERT(Resource->ActiveCount == 0);
|
2006-01-05 16:24:32 +00:00
|
|
|
|
Resource->ActiveCount = 1;
|
2008-04-22 20:44:34 +00:00
|
|
|
|
Resource->ActiveEntries = 1;
|
|
|
|
|
Resource->OwnerEntry.OwnerThread = Thread;
|
|
|
|
|
Resource->OwnerEntry.OwnerCount = 1;
|
|
|
|
|
|
2006-01-05 16:24:32 +00:00
|
|
|
|
/* Release the lock and return */
|
2007-05-08 21:35:10 +00:00
|
|
|
|
ExReleaseResourceLock(Resource, &LockHandle);
|
2006-01-05 16:24:32 +00:00
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
2005-05-09 01:38:29 +00:00
|
|
|
|
|
2006-01-05 16:24:32 +00:00
|
|
|
|
/* Check if it's exclusively owned */
|
|
|
|
|
if (IsOwnedExclusive(Resource))
|
|
|
|
|
{
|
|
|
|
|
/* Check if we own it */
|
2008-04-22 20:44:34 +00:00
|
|
|
|
if (Resource->OwnerEntry.OwnerThread == Thread)
|
2006-01-05 16:24:32 +00:00
|
|
|
|
{
|
|
|
|
|
/* Increase the owning count */
|
2008-04-22 20:44:34 +00:00
|
|
|
|
Resource->OwnerEntry.OwnerCount++;
|
2006-01-05 16:24:32 +00:00
|
|
|
|
|
|
|
|
|
/* Release the lock and return */
|
2007-05-08 21:35:10 +00:00
|
|
|
|
ExReleaseResourceLock(Resource, &LockHandle);
|
2006-01-05 16:24:32 +00:00
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
2005-05-09 01:38:29 +00:00
|
|
|
|
|
2006-01-05 16:24:32 +00:00
|
|
|
|
/* Find a free entry */
|
2007-05-08 21:35:10 +00:00
|
|
|
|
Owner = ExpFindFreeEntry(Resource, &LockHandle);
|
2006-01-05 16:24:32 +00:00
|
|
|
|
if (!Owner) goto TryAcquire;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* Resource is shared, find who owns it */
|
2008-04-22 20:44:34 +00:00
|
|
|
|
Owner = ExpFindEntryForThread(Resource, Thread, &LockHandle, FALSE);
|
2006-01-05 16:24:32 +00:00
|
|
|
|
if (!Owner) goto TryAcquire;
|
|
|
|
|
|
|
|
|
|
/* Is it us? */
|
|
|
|
|
if (Owner->OwnerThread == Thread)
|
|
|
|
|
{
|
|
|
|
|
/* Increase acquire count and return */
|
|
|
|
|
Owner->OwnerCount++;
|
|
|
|
|
ASSERT(Owner->OwnerCount != 0);
|
|
|
|
|
|
|
|
|
|
/* Release the lock and return */
|
2007-05-08 21:35:10 +00:00
|
|
|
|
ExReleaseResourceLock(Resource, &LockHandle);
|
2006-01-05 16:24:32 +00:00
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Acquire it */
|
|
|
|
|
Owner->OwnerThread = Thread;
|
|
|
|
|
Owner->OwnerCount = 1;
|
2008-04-22 20:44:34 +00:00
|
|
|
|
|
|
|
|
|
/* Check how many active entries we had */
|
|
|
|
|
if (Resource->ActiveEntries == 0)
|
|
|
|
|
{
|
|
|
|
|
/* Set initial counts */
|
|
|
|
|
ASSERT(Resource->ActiveCount == 0);
|
|
|
|
|
Resource->ActiveEntries = 1;
|
|
|
|
|
Resource->ActiveCount = 1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* Increase active entries */
|
|
|
|
|
ASSERT(Resource->ActiveCount == 1);
|
|
|
|
|
Resource->ActiveEntries++;
|
|
|
|
|
}
|
2006-01-05 16:24:32 +00:00
|
|
|
|
|
|
|
|
|
/* Release the lock and return */
|
2007-05-08 21:35:10 +00:00
|
|
|
|
ExReleaseResourceLock(Resource, &LockHandle);
|
2006-01-05 16:24:32 +00:00
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* If we got here, then we need to wait. Are we allowed? */
|
|
|
|
|
if (!Wait)
|
|
|
|
|
{
|
|
|
|
|
/* Release the lock and return */
|
2007-05-08 21:35:10 +00:00
|
|
|
|
ExReleaseResourceLock(Resource, &LockHandle);
|
2006-01-05 16:24:32 +00:00
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
2004-11-21 18:38:51 +00:00
|
|
|
|
|
2007-05-08 21:35:10 +00:00
|
|
|
|
/* Check if we have a shared waiters semaphore */
|
|
|
|
|
if (!Resource->SharedWaiters)
|
|
|
|
|
{
|
|
|
|
|
/* Allocate it and try another acquire */
|
|
|
|
|
ExpAllocateSharedWaiterSemaphore(Resource, &LockHandle);
|
|
|
|
|
goto TryAcquire;
|
|
|
|
|
}
|
|
|
|
|
|
2006-01-05 16:24:32 +00:00
|
|
|
|
/* Now wait for the resource */
|
|
|
|
|
Owner->OwnerThread = Thread;
|
|
|
|
|
Owner->OwnerCount = 1;
|
|
|
|
|
Resource->NumberOfSharedWaiters++;
|
|
|
|
|
|
|
|
|
|
/* Release the lock and return */
|
2007-05-08 21:35:10 +00:00
|
|
|
|
ExReleaseResourceLock(Resource, &LockHandle);
|
2006-01-05 16:24:32 +00:00
|
|
|
|
ExpWaitForResource(Resource, Resource->SharedWaiters);
|
|
|
|
|
return TRUE;
|
1999-05-29 00:15:17 +00:00
|
|
|
|
}
|
|
|
|
|
|
2006-01-05 16:24:32 +00:00
|
|
|
|
/*++
|
|
|
|
|
* @name ExAcquireSharedWaitForExclusive
|
|
|
|
|
* @implemented NT4
|
|
|
|
|
*
|
|
|
|
|
* The ExAcquireSharedWaitForExclusive routine acquires the given resource
|
|
|
|
|
* for shared access if shared access can be granted and there are no
|
|
|
|
|
* exclusive waiters.
|
|
|
|
|
*
|
|
|
|
|
* @param Resource
|
|
|
|
|
* Pointer to the resource to acquire.
|
|
|
|
|
*
|
|
|
|
|
* @param Wait
|
|
|
|
|
* Specifies the routine's behavior whenever the resource cannot be
|
|
|
|
|
* acquired immediately.
|
|
|
|
|
*
|
|
|
|
|
* @return TRUE if the resource is acquired. FALSE if the input Wait is FALSE
|
|
|
|
|
* and exclusive access cannot be granted immediately.
|
|
|
|
|
*
|
|
|
|
|
* @remarks The caller can release the resource by calling either
|
|
|
|
|
* ExReleaseResourceLite or ExReleaseResourceForThreadLite.
|
|
|
|
|
*
|
|
|
|
|
* Normal kernel APC delivery must be disabled before calling this
|
|
|
|
|
* routine. Disable normal kernel APC delivery by calling
|
|
|
|
|
* KeEnterCriticalRegion. Delivery must remain disabled until the
|
|
|
|
|
* resource is released, at which point it can be reenabled by calling
|
|
|
|
|
* KeLeaveCriticalRegion.
|
|
|
|
|
*
|
|
|
|
|
* Callers of ExAcquireResourceExclusiveLite must be running at IRQL <
|
|
|
|
|
* DISPATCH_LEVEL.
|
|
|
|
|
*
|
|
|
|
|
*--*/
|
|
|
|
|
BOOLEAN
|
|
|
|
|
NTAPI
|
2008-04-22 20:44:34 +00:00
|
|
|
|
ExAcquireSharedWaitForExclusive(IN PERESOURCE Resource,
|
2007-01-25 23:48:48 +00:00
|
|
|
|
IN BOOLEAN Wait)
|
2006-01-05 16:24:32 +00:00
|
|
|
|
{
|
2007-05-08 21:35:10 +00:00
|
|
|
|
KLOCK_QUEUE_HANDLE LockHandle;
|
2006-01-05 16:24:32 +00:00
|
|
|
|
ERESOURCE_THREAD Thread;
|
|
|
|
|
POWNER_ENTRY Owner;
|
|
|
|
|
|
|
|
|
|
/* Get the thread */
|
|
|
|
|
Thread = ExGetCurrentResourceThread();
|
|
|
|
|
|
|
|
|
|
/* Sanity check and validation */
|
|
|
|
|
ASSERT(KeIsExecutingDpc() == FALSE);
|
|
|
|
|
ExpVerifyResource(Resource);
|
|
|
|
|
|
|
|
|
|
/* Acquire the lock */
|
2007-05-08 21:35:10 +00:00
|
|
|
|
ExAcquireResourceLock(Resource, &LockHandle);
|
2006-01-05 16:24:32 +00:00
|
|
|
|
|
|
|
|
|
/* See if nobody owns us */
|
|
|
|
|
TryAcquire:
|
2008-04-22 20:44:34 +00:00
|
|
|
|
if (!Resource->ActiveEntries)
|
2006-01-05 16:24:32 +00:00
|
|
|
|
{
|
|
|
|
|
/* Nobody owns it, so let's take control */
|
2008-04-22 20:44:34 +00:00
|
|
|
|
ASSERT(Resource->ActiveEntries == 0);
|
|
|
|
|
ASSERT(Resource->ActiveCount == 0);
|
2006-01-05 16:24:32 +00:00
|
|
|
|
Resource->ActiveCount = 1;
|
2008-04-22 20:44:34 +00:00
|
|
|
|
Resource->ActiveEntries = 1;
|
|
|
|
|
Resource->OwnerEntry.OwnerThread = Thread;
|
|
|
|
|
Resource->OwnerEntry.OwnerCount = 1;
|
2006-01-05 16:24:32 +00:00
|
|
|
|
|
|
|
|
|
/* Release the lock and return */
|
2007-05-08 21:35:10 +00:00
|
|
|
|
ExReleaseResourceLock(Resource, &LockHandle);
|
2006-01-05 16:24:32 +00:00
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Check if it's exclusively owned */
|
|
|
|
|
if (IsOwnedExclusive(Resource))
|
|
|
|
|
{
|
|
|
|
|
/* Check if we own it */
|
2008-04-22 20:44:34 +00:00
|
|
|
|
if (Resource->OwnerEntry.OwnerThread == Thread)
|
2006-01-05 16:24:32 +00:00
|
|
|
|
{
|
|
|
|
|
/* Increase the owning count */
|
2008-04-22 20:44:34 +00:00
|
|
|
|
Resource->OwnerEntry.OwnerCount++;
|
2006-01-05 16:24:32 +00:00
|
|
|
|
|
|
|
|
|
/* Release the lock and return */
|
2007-05-08 21:35:10 +00:00
|
|
|
|
ExReleaseResourceLock(Resource, &LockHandle);
|
2006-01-05 16:24:32 +00:00
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2007-01-25 23:48:48 +00:00
|
|
|
|
/* Find a free entry */
|
2007-05-08 21:35:10 +00:00
|
|
|
|
Owner = ExpFindFreeEntry(Resource, &LockHandle);
|
2007-01-25 23:48:48 +00:00
|
|
|
|
if (!Owner) goto TryAcquire;
|
2006-01-05 16:24:32 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* Try to find if there are exclusive waiters */
|
|
|
|
|
if (IsExclusiveWaiting(Resource))
|
|
|
|
|
{
|
|
|
|
|
/* We have to wait for the exclusive waiter to be done */
|
|
|
|
|
if (!Wait)
|
|
|
|
|
{
|
|
|
|
|
/* So bail out if we're not allowed */
|
2007-05-08 21:35:10 +00:00
|
|
|
|
ExReleaseResourceLock(Resource, &LockHandle);
|
2006-01-05 16:24:32 +00:00
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Check if we have a shared waiters semaphore */
|
|
|
|
|
if (!Resource->SharedWaiters)
|
|
|
|
|
{
|
|
|
|
|
/* Allocate one and try again */
|
2007-05-08 21:35:10 +00:00
|
|
|
|
ExpAllocateSharedWaiterSemaphore(Resource, &LockHandle);
|
2006-01-05 16:24:32 +00:00
|
|
|
|
goto TryAcquire;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Now wait for the resource */
|
|
|
|
|
Resource->NumberOfSharedWaiters++;
|
2007-05-08 21:35:10 +00:00
|
|
|
|
ExReleaseResourceLock(Resource, &LockHandle);
|
2006-01-05 16:24:32 +00:00
|
|
|
|
ExpWaitForResource(Resource, Resource->SharedWaiters);
|
|
|
|
|
|
|
|
|
|
/* Get the lock back */
|
2007-05-08 21:35:10 +00:00
|
|
|
|
ExAcquireResourceLock(Resource, &LockHandle);
|
2006-01-05 16:24:32 +00:00
|
|
|
|
|
|
|
|
|
/* Find who owns it now */
|
2008-04-22 20:44:34 +00:00
|
|
|
|
while (!(Owner = ExpFindEntryForThread(Resource, Thread, &LockHandle, TRUE)));
|
2006-01-05 16:24:32 +00:00
|
|
|
|
|
|
|
|
|
/* Sanity checks */
|
|
|
|
|
ASSERT(IsOwnedExclusive(Resource) == FALSE);
|
2008-04-22 20:44:34 +00:00
|
|
|
|
ASSERT(Resource->ActiveEntries > 0);
|
2006-01-05 16:24:32 +00:00
|
|
|
|
ASSERT(Owner->OwnerThread != Thread);
|
|
|
|
|
|
|
|
|
|
/* Take control */
|
|
|
|
|
Owner->OwnerThread = Thread;
|
|
|
|
|
Owner->OwnerCount = 1;
|
|
|
|
|
|
|
|
|
|
/* Release the lock and return */
|
2007-05-08 21:35:10 +00:00
|
|
|
|
ExReleaseResourceLock(Resource, &LockHandle);
|
2006-01-05 16:24:32 +00:00
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* Resource is shared, find who owns it */
|
2008-04-22 20:44:34 +00:00
|
|
|
|
Owner = ExpFindEntryForThread(Resource, Thread, &LockHandle, FALSE);
|
2006-01-05 16:24:32 +00:00
|
|
|
|
if (!Owner) goto TryAcquire;
|
|
|
|
|
|
|
|
|
|
/* Is it us? */
|
|
|
|
|
if (Owner->OwnerThread == Thread)
|
|
|
|
|
{
|
|
|
|
|
/* Increase acquire count and return */
|
|
|
|
|
Owner->OwnerCount++;
|
|
|
|
|
ASSERT(Owner->OwnerCount != 0);
|
|
|
|
|
|
|
|
|
|
/* Release the lock and return */
|
2007-05-08 21:35:10 +00:00
|
|
|
|
ExReleaseResourceLock(Resource, &LockHandle);
|
2006-01-05 16:24:32 +00:00
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* No exclusive waiters, so acquire it */
|
|
|
|
|
Owner->OwnerThread = Thread;
|
|
|
|
|
Owner->OwnerCount = 1;
|
|
|
|
|
|
2008-04-22 20:44:34 +00:00
|
|
|
|
/* Check how many active entries we had */
|
|
|
|
|
if (Resource->ActiveEntries == 0)
|
|
|
|
|
{
|
|
|
|
|
/* Set initial counts */
|
|
|
|
|
ASSERT(Resource->ActiveCount == 0);
|
|
|
|
|
Resource->ActiveEntries = 1;
|
|
|
|
|
Resource->ActiveCount = 1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* Increase active entries */
|
|
|
|
|
ASSERT(Resource->ActiveCount == 1);
|
|
|
|
|
Resource->ActiveEntries++;
|
|
|
|
|
}
|
|
|
|
|
|
2006-01-05 16:24:32 +00:00
|
|
|
|
/* Release the lock and return */
|
2007-05-08 21:35:10 +00:00
|
|
|
|
ExReleaseResourceLock(Resource, &LockHandle);
|
2006-01-05 16:24:32 +00:00
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
2007-01-25 23:48:48 +00:00
|
|
|
|
|
|
|
|
|
/* We have to wait for the exclusive waiter to be done */
|
|
|
|
|
if (!Wait)
|
|
|
|
|
{
|
|
|
|
|
/* So bail out if we're not allowed */
|
2007-05-08 21:35:10 +00:00
|
|
|
|
ExReleaseResourceLock(Resource, &LockHandle);
|
2007-01-25 23:48:48 +00:00
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Check if we have a shared waiters semaphore */
|
|
|
|
|
if (!Resource->SharedWaiters)
|
|
|
|
|
{
|
|
|
|
|
/* Allocate one and try again */
|
2007-05-08 21:35:10 +00:00
|
|
|
|
ExpAllocateSharedWaiterSemaphore(Resource,&LockHandle);
|
2007-01-25 23:48:48 +00:00
|
|
|
|
goto TryAcquire;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Take control */
|
|
|
|
|
Owner->OwnerThread = Thread;
|
|
|
|
|
Owner->OwnerCount = 1;
|
|
|
|
|
Resource->NumberOfSharedWaiters++;
|
|
|
|
|
|
|
|
|
|
/* Release the lock and return */
|
2007-05-08 21:35:10 +00:00
|
|
|
|
ExReleaseResourceLock(Resource, &LockHandle);
|
2007-01-25 23:48:48 +00:00
|
|
|
|
ExpWaitForResource(Resource, Resource->SharedWaiters);
|
|
|
|
|
return TRUE;
|
2006-01-05 16:24:32 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*++
|
|
|
|
|
* @name ExConvertExclusiveToSharedLite
|
|
|
|
|
* @implemented NT4
|
|
|
|
|
*
|
|
|
|
|
* The ExConvertExclusiveToSharedLite routine converts an exclusively
|
|
|
|
|
* acquired resource into a resource that can be acquired shared.
|
|
|
|
|
*
|
|
|
|
|
* @param Resource
|
|
|
|
|
* Pointer to the resource to convert.
|
|
|
|
|
*
|
|
|
|
|
* @return None.
|
|
|
|
|
*
|
|
|
|
|
* @remarks Callers of ExConvertExclusiveToSharedLite must be running at IRQL <
|
|
|
|
|
* DISPATCH_LEVEL.
|
|
|
|
|
*
|
|
|
|
|
*--*/
|
|
|
|
|
VOID
|
|
|
|
|
NTAPI
|
2008-04-22 20:44:34 +00:00
|
|
|
|
ExConvertExclusiveToSharedLite(IN PERESOURCE Resource)
|
1999-05-29 00:15:17 +00:00
|
|
|
|
{
|
2006-01-05 16:24:32 +00:00
|
|
|
|
ULONG OldWaiters;
|
2007-05-08 21:35:10 +00:00
|
|
|
|
KLOCK_QUEUE_HANDLE LockHandle;
|
2006-01-05 16:24:32 +00:00
|
|
|
|
|
|
|
|
|
/* Sanity checks */
|
|
|
|
|
ASSERT(KeIsExecutingDpc() == FALSE);
|
|
|
|
|
ExpVerifyResource(Resource);
|
|
|
|
|
ASSERT(IsOwnedExclusive(Resource));
|
2008-04-22 20:44:34 +00:00
|
|
|
|
ASSERT(Resource->OwnerEntry.OwnerThread == (ERESOURCE_THREAD)PsGetCurrentThread());
|
|
|
|
|
|
2007-01-25 23:48:48 +00:00
|
|
|
|
/* Lock the resource */
|
2007-05-08 21:35:10 +00:00
|
|
|
|
ExAcquireResourceLock(Resource, &LockHandle);
|
2007-01-25 23:48:48 +00:00
|
|
|
|
|
2006-01-05 16:24:32 +00:00
|
|
|
|
/* Erase the exclusive flag */
|
|
|
|
|
Resource->Flag &= ~ResourceOwnedExclusive;
|
|
|
|
|
|
|
|
|
|
/* Check if we have shared waiters */
|
2007-01-25 23:48:48 +00:00
|
|
|
|
if (IsSharedWaiting(Resource))
|
2006-01-05 16:24:32 +00:00
|
|
|
|
{
|
|
|
|
|
/* Make the waiters active owners */
|
2007-01-25 23:48:48 +00:00
|
|
|
|
OldWaiters = Resource->NumberOfSharedWaiters;
|
2008-04-22 20:44:34 +00:00
|
|
|
|
Resource->ActiveEntries += OldWaiters;
|
2006-01-05 16:24:32 +00:00
|
|
|
|
Resource->NumberOfSharedWaiters = 0;
|
|
|
|
|
|
|
|
|
|
/* Release lock and wake the waiters */
|
2007-05-08 21:35:10 +00:00
|
|
|
|
ExReleaseResourceLock(Resource, &LockHandle);
|
2006-01-05 16:24:32 +00:00
|
|
|
|
KeReleaseSemaphore(Resource->SharedWaiters, 0, OldWaiters, FALSE);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* Release lock */
|
2007-05-08 21:35:10 +00:00
|
|
|
|
ExReleaseResourceLock(Resource, &LockHandle);
|
2006-01-05 16:24:32 +00:00
|
|
|
|
}
|
1999-05-29 00:15:17 +00:00
|
|
|
|
}
|
|
|
|
|
|
2006-01-05 16:24:32 +00:00
|
|
|
|
/*++
|
|
|
|
|
* @name ExDeleteResourceLite
|
|
|
|
|
* @implemented NT4
|
|
|
|
|
*
|
|
|
|
|
* The ExConvertExclusiveToSharedLite routine deletes a given resource
|
|
|
|
|
* from the system<EFBFBD>s resource list.
|
|
|
|
|
*
|
|
|
|
|
* @param Resource
|
|
|
|
|
* Pointer to the resource to delete.
|
|
|
|
|
*
|
|
|
|
|
* @return STATUS_SUCCESS if the resource was deleted.
|
|
|
|
|
*
|
|
|
|
|
* @remarks Callers of ExDeleteResourceLite must be running at IRQL <
|
|
|
|
|
* DISPATCH_LEVEL.
|
|
|
|
|
*
|
|
|
|
|
*--*/
|
|
|
|
|
NTSTATUS
|
|
|
|
|
NTAPI
|
2008-04-22 20:44:34 +00:00
|
|
|
|
ExDeleteResourceLite(IN PERESOURCE Resource)
|
1999-05-29 00:15:17 +00:00
|
|
|
|
{
|
2007-05-08 21:35:10 +00:00
|
|
|
|
KLOCK_QUEUE_HANDLE LockHandle;
|
2005-05-09 01:38:29 +00:00
|
|
|
|
|
2006-01-05 16:24:32 +00:00
|
|
|
|
/* Sanity checks */
|
|
|
|
|
ASSERT(IsSharedWaiting(Resource) == FALSE);
|
|
|
|
|
ASSERT(IsExclusiveWaiting(Resource) == FALSE);
|
|
|
|
|
ASSERT(KeIsExecutingDpc() == FALSE);
|
|
|
|
|
ExpVerifyResource(Resource);
|
1998-08-25 04:27:26 +00:00
|
|
|
|
|
2006-01-05 16:24:32 +00:00
|
|
|
|
/* Lock the resource */
|
2007-05-08 21:35:10 +00:00
|
|
|
|
KeAcquireInStackQueuedSpinLock(&ExpResourceSpinLock, &LockHandle);
|
2005-05-09 01:38:29 +00:00
|
|
|
|
|
2006-01-05 16:24:32 +00:00
|
|
|
|
/* Remove the resource */
|
|
|
|
|
RemoveEntryList(&Resource->SystemResourcesList);
|
2004-11-21 18:38:51 +00:00
|
|
|
|
|
2006-01-05 16:24:32 +00:00
|
|
|
|
/* Release the lock */
|
2007-05-08 21:35:10 +00:00
|
|
|
|
KeReleaseInStackQueuedSpinLock(&LockHandle);
|
2005-05-09 01:38:29 +00:00
|
|
|
|
|
2006-01-05 16:24:32 +00:00
|
|
|
|
/* Free every structure */
|
|
|
|
|
if (Resource->OwnerTable) ExFreePool(Resource->OwnerTable);
|
|
|
|
|
if (Resource->SharedWaiters) ExFreePool(Resource->SharedWaiters);
|
|
|
|
|
if (Resource->ExclusiveWaiters) ExFreePool(Resource->ExclusiveWaiters);
|
2004-11-21 18:38:51 +00:00
|
|
|
|
|
2006-01-05 16:24:32 +00:00
|
|
|
|
/* Return success */
|
|
|
|
|
return STATUS_SUCCESS;
|
1998-08-25 04:27:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
2006-01-05 16:24:32 +00:00
|
|
|
|
/*++
|
|
|
|
|
* @name ExDisableResourceBoostLite
|
|
|
|
|
* @implemented NT4
|
|
|
|
|
*
|
|
|
|
|
* The ExDisableResourceBoostLite routine disables thread boosting for
|
|
|
|
|
* the given resource.
|
|
|
|
|
*
|
|
|
|
|
* @param Resource
|
|
|
|
|
* Pointer to the resource whose thread boosting will be disabled.
|
|
|
|
|
*
|
|
|
|
|
* @return None.
|
|
|
|
|
*
|
|
|
|
|
* @remarks None.
|
|
|
|
|
*
|
|
|
|
|
*--*/
|
2000-06-07 13:05:09 +00:00
|
|
|
|
VOID
|
2006-01-05 16:24:32 +00:00
|
|
|
|
NTAPI
|
2008-04-22 20:44:34 +00:00
|
|
|
|
ExDisableResourceBoostLite(IN PERESOURCE Resource)
|
1998-08-25 04:27:26 +00:00
|
|
|
|
{
|
2007-05-08 21:35:10 +00:00
|
|
|
|
KLOCK_QUEUE_HANDLE LockHandle;
|
1998-08-25 04:27:26 +00:00
|
|
|
|
|
2006-01-05 16:24:32 +00:00
|
|
|
|
/* Sanity check */
|
|
|
|
|
ExpVerifyResource(Resource);
|
|
|
|
|
|
|
|
|
|
/* Lock the resource */
|
2007-05-08 21:35:10 +00:00
|
|
|
|
ExAcquireResourceLock(Resource, &LockHandle);
|
2006-01-05 16:24:32 +00:00
|
|
|
|
|
|
|
|
|
/* Remove the flag */
|
|
|
|
|
Resource->Flag |= ResourceHasDisabledPriorityBoost;
|
|
|
|
|
|
|
|
|
|
/* Release the lock */
|
2007-05-08 21:35:10 +00:00
|
|
|
|
ExReleaseResourceLock(Resource, &LockHandle);
|
2000-07-04 01:30:18 +00:00
|
|
|
|
}
|
|
|
|
|
|
2006-01-05 16:24:32 +00:00
|
|
|
|
/*++
|
|
|
|
|
* @name ExGetExclusiveWaiterCount
|
|
|
|
|
* @implemented NT4
|
|
|
|
|
*
|
|
|
|
|
* The ExGetExclusiveWaiterCount routine returns the number of exclusive
|
|
|
|
|
* waiters for the given resource.
|
|
|
|
|
*
|
|
|
|
|
* @param Resource
|
|
|
|
|
* Pointer to the resource to check.
|
|
|
|
|
*
|
|
|
|
|
* @return The number of exclusive waiters.
|
|
|
|
|
*
|
|
|
|
|
* @remarks None.
|
|
|
|
|
*
|
|
|
|
|
*--*/
|
2000-06-07 13:05:09 +00:00
|
|
|
|
ULONG
|
2006-01-05 16:24:32 +00:00
|
|
|
|
NTAPI
|
2008-04-22 20:44:34 +00:00
|
|
|
|
ExGetExclusiveWaiterCount(IN PERESOURCE Resource)
|
1998-08-25 04:27:26 +00:00
|
|
|
|
{
|
2006-01-05 16:24:32 +00:00
|
|
|
|
/* Return the count */
|
|
|
|
|
return Resource->NumberOfExclusiveWaiters;
|
1998-08-25 04:27:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
2006-01-05 16:24:32 +00:00
|
|
|
|
/*++
|
|
|
|
|
* @name ExGetSharedWaiterCount
|
|
|
|
|
* @implemented NT4
|
|
|
|
|
*
|
|
|
|
|
* The ExGetSharedWaiterCount routine returns the number of shared
|
|
|
|
|
* waiters for the given resource.
|
|
|
|
|
*
|
|
|
|
|
* @param Resource
|
|
|
|
|
* Pointer to the resource to check.
|
|
|
|
|
*
|
|
|
|
|
* @return The number of shared waiters.
|
|
|
|
|
*
|
|
|
|
|
* @remarks None.
|
|
|
|
|
*
|
|
|
|
|
*--*/
|
|
|
|
|
ULONG
|
|
|
|
|
NTAPI
|
2008-04-22 20:44:34 +00:00
|
|
|
|
ExGetSharedWaiterCount(IN PERESOURCE Resource)
|
1998-08-25 04:27:26 +00:00
|
|
|
|
{
|
2006-01-05 16:24:32 +00:00
|
|
|
|
/* Return the count */
|
|
|
|
|
return Resource->NumberOfSharedWaiters;
|
1998-08-25 04:27:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
2006-01-05 16:24:32 +00:00
|
|
|
|
/*++
|
|
|
|
|
* @name ExInitializeResourceLite
|
|
|
|
|
* @implemented NT4
|
|
|
|
|
*
|
|
|
|
|
* The ExInitializeResourceLite routine initializes a resource variable.
|
|
|
|
|
*
|
|
|
|
|
* @param Resource
|
|
|
|
|
* Pointer to the resource to check.
|
|
|
|
|
*
|
|
|
|
|
* @return STATUS_SUCCESS.
|
|
|
|
|
*
|
|
|
|
|
* @remarks The storage for ERESOURCE must not be allocated from paged pool.
|
|
|
|
|
*
|
|
|
|
|
* The storage must be 8-byte aligned.
|
|
|
|
|
*
|
|
|
|
|
*--*/
|
|
|
|
|
NTSTATUS
|
|
|
|
|
NTAPI
|
2008-04-22 20:44:34 +00:00
|
|
|
|
ExInitializeResourceLite(IN PERESOURCE Resource)
|
1998-08-25 04:27:26 +00:00
|
|
|
|
{
|
2007-05-08 21:35:10 +00:00
|
|
|
|
KLOCK_QUEUE_HANDLE LockHandle;
|
1998-08-25 04:27:26 +00:00
|
|
|
|
|
2006-01-05 16:24:32 +00:00
|
|
|
|
/* Clear the structure */
|
2008-04-22 20:44:34 +00:00
|
|
|
|
RtlZeroMemory(Resource, sizeof(ERESOURCE));
|
2003-07-15 16:26:18 +00:00
|
|
|
|
|
2006-01-05 16:24:32 +00:00
|
|
|
|
/* Initialize the lock */
|
|
|
|
|
KeInitializeSpinLock(&Resource->SpinLock);
|
2003-07-15 16:26:18 +00:00
|
|
|
|
|
2006-01-05 16:24:32 +00:00
|
|
|
|
/* Add it into the system list */
|
2007-05-08 21:35:10 +00:00
|
|
|
|
KeAcquireInStackQueuedSpinLock(&ExpResourceSpinLock, &LockHandle);
|
|
|
|
|
InsertTailList(&ExpSystemResourcesList, &Resource->SystemResourcesList);
|
|
|
|
|
KeReleaseInStackQueuedSpinLock(&LockHandle);
|
2003-07-15 16:26:18 +00:00
|
|
|
|
|
2006-01-05 16:24:32 +00:00
|
|
|
|
/* Return success */
|
|
|
|
|
return STATUS_SUCCESS;
|
1998-08-25 04:27:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
2006-01-05 16:24:32 +00:00
|
|
|
|
/*++
|
|
|
|
|
* @name ExIsResourceAcquiredExclusiveLite
|
|
|
|
|
* @implemented NT4
|
|
|
|
|
*
|
|
|
|
|
* The ExIsResourceAcquiredExclusiveLite routine returns whether the
|
|
|
|
|
* current thread has exclusive access to a given resource.
|
|
|
|
|
*
|
|
|
|
|
* @param Resource
|
|
|
|
|
* Pointer to the resource to check.
|
|
|
|
|
*
|
|
|
|
|
* @return TRUE if the caller already has exclusive access to the given resource.
|
|
|
|
|
*
|
|
|
|
|
* @remarks Callers of ExIsResourceAcquiredExclusiveLite must be running at
|
|
|
|
|
* IRQL <= DISPATCH_LEVEL.
|
|
|
|
|
*
|
|
|
|
|
*--*/
|
|
|
|
|
BOOLEAN
|
|
|
|
|
NTAPI
|
2008-04-22 20:44:34 +00:00
|
|
|
|
ExIsResourceAcquiredExclusiveLite(IN PERESOURCE Resource)
|
1998-08-25 04:27:26 +00:00
|
|
|
|
{
|
2006-01-05 16:24:32 +00:00
|
|
|
|
BOOLEAN IsAcquired = FALSE;
|
|
|
|
|
|
|
|
|
|
/* Sanity check */
|
|
|
|
|
ExpVerifyResource(Resource);
|
|
|
|
|
|
|
|
|
|
/* Check if it's exclusively acquired */
|
|
|
|
|
if ((IsOwnedExclusive(Resource)) &&
|
2008-04-22 20:44:34 +00:00
|
|
|
|
(Resource->OwnerEntry.OwnerThread == ExGetCurrentResourceThread()))
|
2006-01-05 16:24:32 +00:00
|
|
|
|
{
|
|
|
|
|
/* It is acquired */
|
|
|
|
|
IsAcquired = TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Return if it's acquired */
|
|
|
|
|
return IsAcquired;
|
1998-08-25 04:27:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
2006-01-05 16:24:32 +00:00
|
|
|
|
/*++
|
|
|
|
|
* @name ExIsResourceAcquiredSharedLite
|
|
|
|
|
* @implemented NT4
|
|
|
|
|
*
|
|
|
|
|
* The ExIsResourceAcquiredSharedLite routine returns whether the
|
|
|
|
|
* current thread has has access (either shared or exclusive) to a
|
|
|
|
|
* given resource.
|
|
|
|
|
*
|
|
|
|
|
* @param Resource
|
|
|
|
|
* Pointer to the resource to check.
|
|
|
|
|
*
|
|
|
|
|
* @return Number of times the caller has acquired the given resource for
|
|
|
|
|
* shared or exclusive access.
|
|
|
|
|
*
|
|
|
|
|
* @remarks Callers of ExIsResourceAcquiredExclusiveLite must be running at
|
|
|
|
|
* IRQL <= DISPATCH_LEVEL.
|
|
|
|
|
*
|
|
|
|
|
*--*/
|
2000-06-07 13:05:09 +00:00
|
|
|
|
ULONG
|
2006-01-05 16:24:32 +00:00
|
|
|
|
NTAPI
|
2008-04-22 20:44:34 +00:00
|
|
|
|
ExIsResourceAcquiredSharedLite(IN PERESOURCE Resource)
|
1998-08-25 04:27:26 +00:00
|
|
|
|
{
|
2006-01-05 16:24:32 +00:00
|
|
|
|
ERESOURCE_THREAD Thread;
|
|
|
|
|
ULONG i, Size;
|
|
|
|
|
ULONG Count = 0;
|
2007-05-08 21:35:10 +00:00
|
|
|
|
KLOCK_QUEUE_HANDLE LockHandle;
|
2006-01-05 16:24:32 +00:00
|
|
|
|
POWNER_ENTRY Owner;
|
1998-08-25 04:27:26 +00:00
|
|
|
|
|
2006-01-05 16:24:32 +00:00
|
|
|
|
/* Sanity check */
|
|
|
|
|
ExpVerifyResource(Resource);
|
2003-07-15 16:26:18 +00:00
|
|
|
|
|
2007-05-08 21:35:10 +00:00
|
|
|
|
/* Check if nobody owns us */
|
2008-04-22 20:44:34 +00:00
|
|
|
|
if (!Resource->ActiveEntries) return 0;
|
2007-05-08 21:35:10 +00:00
|
|
|
|
|
2006-01-05 16:24:32 +00:00
|
|
|
|
/* Get the thread */
|
|
|
|
|
Thread = ExGetCurrentResourceThread();
|
2003-07-15 16:26:18 +00:00
|
|
|
|
|
2006-01-05 16:24:32 +00:00
|
|
|
|
/* Check if we are in the thread list */
|
2008-04-22 20:44:34 +00:00
|
|
|
|
if (Resource->OwnerEntry.OwnerThread == Thread)
|
2006-01-05 16:24:32 +00:00
|
|
|
|
{
|
|
|
|
|
/* Found it, return count */
|
2008-04-22 20:44:34 +00:00
|
|
|
|
Count = Resource->OwnerEntry.OwnerCount;
|
2006-01-05 16:24:32 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2007-05-08 21:35:10 +00:00
|
|
|
|
/* We can't own an exclusive resource at this point */
|
|
|
|
|
if (IsOwnedExclusive(Resource)) return 0;
|
|
|
|
|
|
2008-04-22 20:44:34 +00:00
|
|
|
|
/* Lock the resource */
|
|
|
|
|
ExAcquireResourceLock(Resource, &LockHandle);
|
|
|
|
|
|
|
|
|
|
/* Not in the list, do a full table look up */
|
|
|
|
|
Owner = Resource->OwnerTable;
|
|
|
|
|
if (Owner)
|
2006-01-05 16:24:32 +00:00
|
|
|
|
{
|
2008-04-22 20:44:34 +00:00
|
|
|
|
/* Get the resource index */
|
|
|
|
|
i = ((PKTHREAD)Thread)->ResourceIndex;
|
|
|
|
|
Size = Owner->TableSize;
|
|
|
|
|
|
|
|
|
|
/* Check if the index is valid and check if we don't match */
|
|
|
|
|
if ((i >= Size) || (Owner[i].OwnerThread != Thread))
|
2006-01-05 16:24:32 +00:00
|
|
|
|
{
|
2008-04-22 20:44:34 +00:00
|
|
|
|
/* Sh*t! We need to do a full search */
|
|
|
|
|
for (i = 1; i < Size; i++)
|
2007-05-08 21:35:10 +00:00
|
|
|
|
{
|
2008-04-22 20:44:34 +00:00
|
|
|
|
/* Move to next owner */
|
|
|
|
|
Owner++;
|
|
|
|
|
|
|
|
|
|
/* Try to find a match */
|
|
|
|
|
if (Owner->OwnerThread == Thread)
|
2006-01-05 16:24:32 +00:00
|
|
|
|
{
|
2008-04-22 20:44:34 +00:00
|
|
|
|
/* Finally! */
|
|
|
|
|
Count = Owner->OwnerCount;
|
|
|
|
|
break;
|
2006-01-05 16:24:32 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2008-04-22 20:44:34 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* We found the match directlry */
|
|
|
|
|
Count = Owner[i].OwnerCount;
|
|
|
|
|
}
|
2006-01-05 16:24:32 +00:00
|
|
|
|
}
|
2008-04-22 20:44:34 +00:00
|
|
|
|
|
|
|
|
|
/* Release the lock */
|
|
|
|
|
ExReleaseResourceLock(Resource, &LockHandle);
|
2006-01-05 16:24:32 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Return count */
|
|
|
|
|
return Count;
|
1998-08-25 04:27:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
2006-01-05 16:24:32 +00:00
|
|
|
|
/*++
|
|
|
|
|
* @name ExReinitializeResourceLite
|
|
|
|
|
* @implemented NT4
|
|
|
|
|
*
|
|
|
|
|
* The ExReinitializeResourceLite routine routine reinitializes
|
|
|
|
|
* an existing resource variable.
|
|
|
|
|
*
|
|
|
|
|
* @param Resource
|
|
|
|
|
* Pointer to the resource to be reinitialized.
|
|
|
|
|
*
|
|
|
|
|
* @return STATUS_SUCCESS.
|
|
|
|
|
*
|
|
|
|
|
* @remarks With a single call to ExReinitializeResource, a driver writer can
|
|
|
|
|
* replace three calls: one to ExDeleteResourceLite, another to
|
|
|
|
|
* ExAllocatePool, and a third to ExInitializeResourceLite. As
|
|
|
|
|
* contention for a resource variable increases, memory is dynamically
|
|
|
|
|
* allocated and attached to the resource in order to track this
|
|
|
|
|
* contention. As an optimization, ExReinitializeResourceLite retains
|
|
|
|
|
* and zeroes this previously allocated memory.
|
|
|
|
|
*
|
|
|
|
|
* Callers of ExReinitializeResourceLite must be running at
|
|
|
|
|
* IRQL <= DISPATCH_LEVEL.
|
|
|
|
|
*
|
|
|
|
|
*--*/
|
|
|
|
|
NTSTATUS
|
|
|
|
|
NTAPI
|
2008-04-22 20:44:34 +00:00
|
|
|
|
ExReinitializeResourceLite(IN PERESOURCE Resource)
|
1998-08-25 04:27:26 +00:00
|
|
|
|
{
|
2006-01-05 16:24:32 +00:00
|
|
|
|
PKEVENT Event;
|
|
|
|
|
PKSEMAPHORE Semaphore;
|
|
|
|
|
ULONG i, Size;
|
|
|
|
|
POWNER_ENTRY Owner;
|
|
|
|
|
|
|
|
|
|
/* Get the owner table */
|
|
|
|
|
Owner = Resource->OwnerTable;
|
|
|
|
|
if (Owner)
|
|
|
|
|
{
|
|
|
|
|
/* Get the size and loop it */
|
|
|
|
|
Size = Owner->TableSize;
|
|
|
|
|
for (i = 0; i < Size; i++)
|
|
|
|
|
{
|
|
|
|
|
/* Zero the table */
|
|
|
|
|
Owner[i].OwnerThread = 0;
|
|
|
|
|
Owner[i].OwnerCount = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Zero the flags and count */
|
|
|
|
|
Resource->Flag = 0;
|
|
|
|
|
Resource->ActiveCount = 0;
|
2008-04-22 20:44:34 +00:00
|
|
|
|
Resource->ActiveEntries = 0;
|
2006-01-05 16:24:32 +00:00
|
|
|
|
|
|
|
|
|
/* Reset the semaphore */
|
|
|
|
|
Semaphore = Resource->SharedWaiters;
|
|
|
|
|
if (Semaphore) KeInitializeSemaphore(Semaphore, 0, MAXLONG);
|
|
|
|
|
|
|
|
|
|
/* Reset the event */
|
|
|
|
|
Event = Resource->ExclusiveWaiters;
|
|
|
|
|
if (Event) KeInitializeEvent(Event, SynchronizationEvent, FALSE);
|
|
|
|
|
|
|
|
|
|
/* Clear the resource data */
|
2008-04-22 20:44:34 +00:00
|
|
|
|
Resource->OwnerEntry.OwnerThread = 0;
|
|
|
|
|
Resource->OwnerEntry.OwnerCount = 0;
|
2006-01-05 16:24:32 +00:00
|
|
|
|
Resource->ContentionCount = 0;
|
|
|
|
|
Resource->NumberOfSharedWaiters = 0;
|
|
|
|
|
Resource->NumberOfExclusiveWaiters = 0;
|
|
|
|
|
return STATUS_SUCCESS;
|
1998-08-25 04:27:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
2006-01-05 16:24:32 +00:00
|
|
|
|
/*++
|
|
|
|
|
* @name ExReleaseResourceLite
|
|
|
|
|
* @implemented NT4
|
|
|
|
|
*
|
|
|
|
|
* The ExReleaseResourceLite routine routine releases
|
|
|
|
|
* a specified executive resource owned by the current thread.
|
|
|
|
|
*
|
|
|
|
|
* @param Resource
|
|
|
|
|
* Pointer to the resource to be released.
|
|
|
|
|
*
|
|
|
|
|
* @return None.
|
|
|
|
|
*
|
|
|
|
|
* @remarks Callers of ExReleaseResourceLite must be running at
|
|
|
|
|
* IRQL <= DISPATCH_LEVEL.
|
|
|
|
|
*
|
|
|
|
|
*--*/
|
|
|
|
|
VOID
|
|
|
|
|
FASTCALL
|
2008-04-22 20:44:34 +00:00
|
|
|
|
ExReleaseResourceLite(IN PERESOURCE Resource)
|
1998-08-25 04:27:26 +00:00
|
|
|
|
{
|
2008-04-22 20:44:34 +00:00
|
|
|
|
/* Just call the For-Thread function */
|
|
|
|
|
ExReleaseResourceForThreadLite(Resource, (ERESOURCE_THREAD)PsGetCurrentThread());
|
1998-08-25 04:27:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
2006-01-05 16:24:32 +00:00
|
|
|
|
/*++
|
|
|
|
|
* @name ExReleaseResourceForThreadLite
|
|
|
|
|
* @implemented NT4
|
|
|
|
|
*
|
|
|
|
|
* The ExReleaseResourceForThreadLite routine routine releases
|
|
|
|
|
* the input resource of the indicated thread.
|
|
|
|
|
*
|
|
|
|
|
* @param Resource
|
|
|
|
|
* Pointer to the resource to be released.
|
|
|
|
|
*
|
|
|
|
|
* @param Thread
|
|
|
|
|
* Identifies the thread that originally acquired the resource.
|
|
|
|
|
*
|
|
|
|
|
* @return None.
|
|
|
|
|
*
|
|
|
|
|
* @remarks Callers of ExReleaseResourceForThreadLite must be running at
|
|
|
|
|
* IRQL <= DISPATCH_LEVEL.
|
|
|
|
|
*
|
|
|
|
|
*--*/
|
2000-06-07 13:05:09 +00:00
|
|
|
|
VOID
|
2006-01-05 16:24:32 +00:00
|
|
|
|
NTAPI
|
2008-04-22 20:44:34 +00:00
|
|
|
|
ExReleaseResourceForThreadLite(IN PERESOURCE Resource,
|
2007-05-08 21:35:10 +00:00
|
|
|
|
IN ERESOURCE_THREAD Thread)
|
1998-08-25 04:27:26 +00:00
|
|
|
|
{
|
2006-01-05 16:24:32 +00:00
|
|
|
|
ULONG i;
|
|
|
|
|
ULONG Count;
|
2007-05-08 21:35:10 +00:00
|
|
|
|
KLOCK_QUEUE_HANDLE LockHandle;
|
|
|
|
|
POWNER_ENTRY Owner, Limit;
|
2006-01-05 16:24:32 +00:00
|
|
|
|
ASSERT(Thread != 0);
|
|
|
|
|
|
|
|
|
|
/* Get the thread and lock the resource */
|
2007-05-08 21:35:10 +00:00
|
|
|
|
ExAcquireResourceLock(Resource, &LockHandle);
|
2006-01-05 16:24:32 +00:00
|
|
|
|
|
2007-05-08 21:35:10 +00:00
|
|
|
|
/* Sanity checks */
|
2006-01-05 16:24:32 +00:00
|
|
|
|
ExpVerifyResource(Resource);
|
2007-05-08 21:35:10 +00:00
|
|
|
|
ExpCheckForApcsDisabled(LockHandle.OldIrql, Resource, (PKTHREAD)Thread);
|
2006-01-05 16:24:32 +00:00
|
|
|
|
|
|
|
|
|
/* Check if it's exclusively owned */
|
|
|
|
|
if (IsOwnedExclusive(Resource))
|
|
|
|
|
{
|
|
|
|
|
/* Decrement owner count and check if we're done */
|
2008-04-22 20:44:34 +00:00
|
|
|
|
ASSERT(Resource->OwnerEntry.OwnerThread == Thread);
|
|
|
|
|
if (--Resource->OwnerEntry.OwnerCount)
|
2006-01-05 16:24:32 +00:00
|
|
|
|
{
|
|
|
|
|
/* Done, release lock! */
|
2007-05-08 21:35:10 +00:00
|
|
|
|
ExReleaseResourceLock(Resource, &LockHandle);
|
2006-01-05 16:24:32 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
1999-03-31 13:21:44 +00:00
|
|
|
|
|
2006-01-05 16:24:32 +00:00
|
|
|
|
/* Clear the owner */
|
2008-04-22 20:44:34 +00:00
|
|
|
|
Resource->OwnerEntry.OwnerThread = 0;
|
|
|
|
|
|
|
|
|
|
/* Decrement the number of active entries */
|
|
|
|
|
ASSERT(Resource->ActiveEntries == 1);
|
|
|
|
|
Resource->ActiveEntries--;
|
|
|
|
|
|
|
|
|
|
/* Check if there are shared waiters */
|
|
|
|
|
if (IsSharedWaiting(Resource))
|
2006-01-05 16:24:32 +00:00
|
|
|
|
{
|
|
|
|
|
/* Remove the exclusive flag */
|
|
|
|
|
Resource->Flag &= ~ResourceOwnedExclusive;
|
2008-04-22 20:44:34 +00:00
|
|
|
|
|
|
|
|
|
/* Give ownage to another thread */
|
|
|
|
|
Count = Resource->NumberOfSharedWaiters;
|
|
|
|
|
Resource->ActiveEntries = Count;
|
|
|
|
|
Resource->NumberOfSharedWaiters = 0;
|
|
|
|
|
|
|
|
|
|
/* Release lock and let someone else have it */
|
2008-05-07 09:46:37 +00:00
|
|
|
|
ASSERT(Resource->ActiveCount == 1);
|
2008-04-22 20:44:34 +00:00
|
|
|
|
ExReleaseResourceLock(Resource, &LockHandle);
|
|
|
|
|
KeReleaseSemaphore(Resource->SharedWaiters, 0, Count, FALSE);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
else if (IsExclusiveWaiting(Resource))
|
|
|
|
|
{
|
|
|
|
|
/* Give exclusive access */
|
|
|
|
|
Resource->OwnerEntry.OwnerThread = 1;
|
|
|
|
|
Resource->OwnerEntry.OwnerCount = 1;
|
|
|
|
|
Resource->ActiveEntries = 1;
|
|
|
|
|
Resource->NumberOfExclusiveWaiters--;
|
|
|
|
|
|
|
|
|
|
/* Release the lock and give it away */
|
2008-05-07 09:46:37 +00:00
|
|
|
|
ASSERT(Resource->ActiveCount == 1);
|
2008-04-22 20:44:34 +00:00
|
|
|
|
ExReleaseResourceLock(Resource, &LockHandle);
|
|
|
|
|
KeSetEventBoostPriority(Resource->ExclusiveWaiters,
|
|
|
|
|
(PKTHREAD*)&Resource->OwnerEntry.OwnerThread);
|
|
|
|
|
return;
|
2006-01-05 16:24:32 +00:00
|
|
|
|
}
|
2008-04-22 20:44:34 +00:00
|
|
|
|
|
|
|
|
|
/* Remove the exclusive flag */
|
|
|
|
|
Resource->Flag &= ~ResourceOwnedExclusive;
|
|
|
|
|
Resource->ActiveCount = 0;
|
2006-01-05 16:24:32 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* Check if we are in the thread list */
|
2008-04-22 20:44:34 +00:00
|
|
|
|
if (Resource->OwnerEntry.OwnerThread == Thread)
|
2006-01-05 16:24:32 +00:00
|
|
|
|
{
|
|
|
|
|
/* Found it, get owner */
|
2008-04-22 20:44:34 +00:00
|
|
|
|
Owner = &Resource->OwnerEntry;
|
2006-01-05 16:24:32 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* Assume no valid index */
|
|
|
|
|
i = 1;
|
|
|
|
|
|
|
|
|
|
/* If we got a valid pointer, try to get the resource index */
|
|
|
|
|
if (!((ULONG)Thread & 3)) i = ((PKTHREAD)Thread)->ResourceIndex;
|
|
|
|
|
|
|
|
|
|
/* Do a table lookup */
|
|
|
|
|
Owner = Resource->OwnerTable;
|
|
|
|
|
ASSERT(Owner != NULL);
|
|
|
|
|
|
|
|
|
|
/* Check if we're out of the size and don't match */
|
|
|
|
|
if ((i >= Owner->TableSize) || (Owner[i].OwnerThread != Thread))
|
|
|
|
|
{
|
|
|
|
|
/* Get the last entry */
|
2007-05-08 21:35:10 +00:00
|
|
|
|
Limit = &Owner[Owner->TableSize];
|
2006-01-05 16:24:32 +00:00
|
|
|
|
for (;;)
|
|
|
|
|
{
|
|
|
|
|
/* Move to the next entry */
|
|
|
|
|
Owner++;
|
|
|
|
|
|
2007-05-08 21:35:10 +00:00
|
|
|
|
/* Make sure we're not out of bounds */
|
|
|
|
|
if (Owner >= Limit)
|
|
|
|
|
{
|
|
|
|
|
/* Bugcheck, nobody owns us */
|
|
|
|
|
KeBugCheckEx(RESOURCE_NOT_OWNED,
|
|
|
|
|
(ULONG_PTR)Resource,
|
|
|
|
|
(ULONG_PTR)Thread,
|
|
|
|
|
(ULONG_PTR)Resource->OwnerTable,
|
|
|
|
|
(ULONG_PTR)3);
|
|
|
|
|
}
|
|
|
|
|
|
2006-01-05 16:24:32 +00:00
|
|
|
|
/* Check for a match */
|
|
|
|
|
if (Owner->OwnerThread == Thread) break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* Get the entry directly */
|
|
|
|
|
Owner = &Owner[i];
|
|
|
|
|
}
|
|
|
|
|
}
|
2003-07-15 16:26:18 +00:00
|
|
|
|
|
2006-01-05 16:24:32 +00:00
|
|
|
|
/* Sanity checks */
|
|
|
|
|
ASSERT(Owner->OwnerThread == Thread);
|
|
|
|
|
ASSERT(Owner->OwnerCount > 0);
|
2003-07-15 16:26:18 +00:00
|
|
|
|
|
2006-01-05 16:24:32 +00:00
|
|
|
|
/* Check if we are the last owner */
|
2008-04-22 20:44:34 +00:00
|
|
|
|
if (--Owner->OwnerCount)
|
2006-01-05 16:24:32 +00:00
|
|
|
|
{
|
2008-04-22 20:44:34 +00:00
|
|
|
|
/* There are other owners, release lock */
|
2007-05-08 21:35:10 +00:00
|
|
|
|
ExReleaseResourceLock(Resource, &LockHandle);
|
2006-01-05 16:24:32 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
2003-07-15 16:26:18 +00:00
|
|
|
|
|
2006-01-05 16:24:32 +00:00
|
|
|
|
/* Clear owner */
|
|
|
|
|
Owner->OwnerThread = 0;
|
|
|
|
|
|
|
|
|
|
/* See if the resource isn't being owned anymore */
|
2008-04-22 20:44:34 +00:00
|
|
|
|
ASSERT(Resource->ActiveEntries > 0);
|
|
|
|
|
if (!(--Resource->ActiveEntries))
|
2006-01-05 16:24:32 +00:00
|
|
|
|
{
|
|
|
|
|
/* Check if there's an exclusive waiter */
|
|
|
|
|
if (IsExclusiveWaiting(Resource))
|
|
|
|
|
{
|
|
|
|
|
/* Give exclusive access */
|
2007-05-08 21:35:10 +00:00
|
|
|
|
Resource->Flag |= ResourceOwnedExclusive;
|
2008-04-22 20:44:34 +00:00
|
|
|
|
Resource->OwnerEntry.OwnerThread = 1;
|
|
|
|
|
Resource->OwnerEntry.OwnerCount = 1;
|
|
|
|
|
Resource->ActiveEntries = 1;
|
2006-01-05 16:24:32 +00:00
|
|
|
|
Resource->NumberOfExclusiveWaiters--;
|
|
|
|
|
|
|
|
|
|
/* Release the lock and give it away */
|
2008-05-07 09:46:37 +00:00
|
|
|
|
ASSERT(Resource->ActiveCount == 1);
|
2007-05-08 21:35:10 +00:00
|
|
|
|
ExReleaseResourceLock(Resource, &LockHandle);
|
2006-01-05 16:24:32 +00:00
|
|
|
|
KeSetEventBoostPriority(Resource->ExclusiveWaiters,
|
2008-04-22 20:44:34 +00:00
|
|
|
|
(PKTHREAD*)&Resource->OwnerEntry.OwnerThread);
|
2006-01-05 16:24:32 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
2008-04-22 20:44:34 +00:00
|
|
|
|
|
|
|
|
|
/* Clear the active count */
|
|
|
|
|
Resource->ActiveCount = 0;
|
2006-01-05 16:24:32 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2003-07-15 16:26:18 +00:00
|
|
|
|
|
2006-01-05 16:24:32 +00:00
|
|
|
|
/* Release lock */
|
2007-05-08 21:35:10 +00:00
|
|
|
|
ExReleaseResourceLock(Resource, &LockHandle);
|
1998-08-25 04:27:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
2006-01-05 16:24:32 +00:00
|
|
|
|
/*++
|
|
|
|
|
* @name ExSetResourceOwnerPointer
|
|
|
|
|
* @implemented NT4
|
|
|
|
|
*
|
|
|
|
|
* The ExSetResourceOwnerPointer routine routine sets the owner thread
|
|
|
|
|
* thread pointer for an executive resource.
|
|
|
|
|
*
|
|
|
|
|
* @param Resource
|
|
|
|
|
* Pointer to the resource whose owner to change.
|
|
|
|
|
*
|
|
|
|
|
* @param OwnerPointer
|
|
|
|
|
* Pointer to an owner thread pointer of type ERESOURCE_THREAD.
|
|
|
|
|
*
|
|
|
|
|
* @return None.
|
|
|
|
|
*
|
|
|
|
|
* @remarks ExSetResourceOwnerPointer, used in conjunction with
|
|
|
|
|
* ExReleaseResourceForThreadLite, provides a means for one thread
|
|
|
|
|
* (acting as an resource manager thread) to acquire and release
|
|
|
|
|
* resources for use by another thread (acting as a resource user
|
|
|
|
|
* thread).
|
|
|
|
|
*
|
|
|
|
|
* After calling ExSetResourceOwnerPointer for a specific resource,
|
|
|
|
|
* the only other routine that can be called for that resource is
|
|
|
|
|
* ExReleaseResourceForThreadLite.
|
|
|
|
|
*
|
|
|
|
|
* Callers of ExSetResourceOwnerPointer must be running at
|
|
|
|
|
* IRQL <= DISPATCH_LEVEL.
|
|
|
|
|
*
|
|
|
|
|
*--*/
|
2000-06-07 13:05:09 +00:00
|
|
|
|
VOID
|
2006-01-05 16:24:32 +00:00
|
|
|
|
NTAPI
|
2008-04-22 20:44:34 +00:00
|
|
|
|
ExSetResourceOwnerPointer(IN PERESOURCE Resource,
|
2006-01-05 16:24:32 +00:00
|
|
|
|
IN PVOID OwnerPointer)
|
1998-08-25 04:27:26 +00:00
|
|
|
|
{
|
2006-01-05 16:24:32 +00:00
|
|
|
|
ERESOURCE_THREAD Thread;
|
2007-05-08 21:35:10 +00:00
|
|
|
|
KLOCK_QUEUE_HANDLE LockHandle;
|
2006-01-05 16:24:32 +00:00
|
|
|
|
POWNER_ENTRY Owner, ThisOwner;
|
1998-08-25 04:27:26 +00:00
|
|
|
|
|
2006-01-05 16:24:32 +00:00
|
|
|
|
/* Sanity check */
|
|
|
|
|
ASSERT((OwnerPointer != 0) && (((ULONG_PTR)OwnerPointer & 3) == 3));
|
2000-07-04 01:30:18 +00:00
|
|
|
|
|
2006-01-05 16:24:32 +00:00
|
|
|
|
/* Get the thread */
|
|
|
|
|
Thread = ExGetCurrentResourceThread();
|
2005-05-09 01:38:29 +00:00
|
|
|
|
|
2006-01-05 16:24:32 +00:00
|
|
|
|
/* Sanity check */
|
|
|
|
|
ExpVerifyResource(Resource);
|
2005-05-09 01:38:29 +00:00
|
|
|
|
|
Implemented:
ExSetResourceOwnerPointer, FsRtlDissectDbcs, FsRtlDoesDbcsContainWildCards, FsRtlAcquireFileExclusive, FsRtlReleaseFile, FsRtlGetNextMcbEntry, FsRtlLookupLastMcbEntry, FsRtlLookupMcbEntry, FsRtlRemoveMcbEntry, FsRtlIncrementCcFastReadResourceMiss, FsRtlIncrementCcFastReadNotPossible, FsRtlIncrementCcFastReadWait, FsRtlIncrementCcFastReadNoWait , FsRtlAreNamesEqual, FsRtlDoesNameContainWildCards, IoCreateDriver, IoDeleteDriver
Thanks to Filip for reviewing some of these.
svn path=/trunk/; revision=12408
2004-12-30 18:30:05 +00:00
|
|
|
|
/* Lock the resource */
|
2007-05-08 21:35:10 +00:00
|
|
|
|
ExAcquireResourceLock(Resource, &LockHandle);
|
2005-05-09 01:38:29 +00:00
|
|
|
|
|
Implemented:
ExSetResourceOwnerPointer, FsRtlDissectDbcs, FsRtlDoesDbcsContainWildCards, FsRtlAcquireFileExclusive, FsRtlReleaseFile, FsRtlGetNextMcbEntry, FsRtlLookupLastMcbEntry, FsRtlLookupMcbEntry, FsRtlRemoveMcbEntry, FsRtlIncrementCcFastReadResourceMiss, FsRtlIncrementCcFastReadNotPossible, FsRtlIncrementCcFastReadWait, FsRtlIncrementCcFastReadNoWait , FsRtlAreNamesEqual, FsRtlDoesNameContainWildCards, IoCreateDriver, IoDeleteDriver
Thanks to Filip for reviewing some of these.
svn path=/trunk/; revision=12408
2004-12-30 18:30:05 +00:00
|
|
|
|
/* Check if it's exclusive */
|
2006-01-05 16:24:32 +00:00
|
|
|
|
if (IsOwnedExclusive(Resource))
|
|
|
|
|
{
|
Implemented:
ExSetResourceOwnerPointer, FsRtlDissectDbcs, FsRtlDoesDbcsContainWildCards, FsRtlAcquireFileExclusive, FsRtlReleaseFile, FsRtlGetNextMcbEntry, FsRtlLookupLastMcbEntry, FsRtlLookupMcbEntry, FsRtlRemoveMcbEntry, FsRtlIncrementCcFastReadResourceMiss, FsRtlIncrementCcFastReadNotPossible, FsRtlIncrementCcFastReadWait, FsRtlIncrementCcFastReadNoWait , FsRtlAreNamesEqual, FsRtlDoesNameContainWildCards, IoCreateDriver, IoDeleteDriver
Thanks to Filip for reviewing some of these.
svn path=/trunk/; revision=12408
2004-12-30 18:30:05 +00:00
|
|
|
|
/* If it's exclusive, set the first entry no matter what */
|
2008-04-22 20:44:34 +00:00
|
|
|
|
ASSERT(Resource->OwnerEntry.OwnerThread == Thread);
|
|
|
|
|
ASSERT(Resource->OwnerEntry.OwnerCount > 0);
|
|
|
|
|
Resource->OwnerEntry.OwnerThread = (ULONG_PTR)OwnerPointer;
|
2006-01-05 16:24:32 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* Set the thread in both entries */
|
|
|
|
|
ThisOwner = ExpFindEntryForThread(Resource,
|
2007-05-08 21:35:10 +00:00
|
|
|
|
(ERESOURCE_THREAD)OwnerPointer,
|
2008-04-22 20:44:34 +00:00
|
|
|
|
0,
|
|
|
|
|
FALSE);
|
|
|
|
|
Owner = ExpFindEntryForThread(Resource, Thread, 0, FALSE);
|
2006-01-05 16:24:32 +00:00
|
|
|
|
if (!Owner)
|
|
|
|
|
{
|
|
|
|
|
/* Nobody owns it, crash */
|
2008-04-22 20:44:34 +00:00
|
|
|
|
KeBugCheckEx(RESOURCE_NOT_OWNED,
|
2006-01-05 16:24:32 +00:00
|
|
|
|
(ULONG_PTR)Resource,
|
|
|
|
|
Thread,
|
|
|
|
|
(ULONG_PTR)Resource->OwnerTable,
|
|
|
|
|
3);
|
|
|
|
|
}
|
2005-05-09 01:38:29 +00:00
|
|
|
|
|
2006-01-05 16:24:32 +00:00
|
|
|
|
/* Set if we are the owner */
|
|
|
|
|
if (ThisOwner)
|
|
|
|
|
{
|
|
|
|
|
/* Update data */
|
|
|
|
|
ThisOwner->OwnerCount += Owner->OwnerCount;
|
|
|
|
|
Owner->OwnerCount = 0;
|
|
|
|
|
Owner->OwnerThread = 0;
|
2008-04-22 20:44:34 +00:00
|
|
|
|
ASSERT(Resource->ActiveEntries >= 2);
|
|
|
|
|
Resource->ActiveEntries--;
|
2006-01-05 16:24:32 +00:00
|
|
|
|
}
|
2007-05-08 21:35:10 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* Update the owner entry instead */
|
|
|
|
|
Owner->OwnerThread = (ERESOURCE_THREAD)OwnerPointer;
|
|
|
|
|
}
|
2006-01-05 16:24:32 +00:00
|
|
|
|
}
|
2005-05-09 01:38:29 +00:00
|
|
|
|
|
2006-01-05 16:24:32 +00:00
|
|
|
|
/* Release the resource */
|
2007-05-08 21:35:10 +00:00
|
|
|
|
ExReleaseResourceLock(Resource, &LockHandle);
|
2006-01-05 16:24:32 +00:00
|
|
|
|
}
|
2005-05-09 01:38:29 +00:00
|
|
|
|
|
2006-01-05 16:24:32 +00:00
|
|
|
|
/*++
|
|
|
|
|
* @name ExTryToAcquireResourceExclusiveLite
|
|
|
|
|
* @implemented NT4
|
|
|
|
|
*
|
|
|
|
|
* The ExTryToAcquireResourceExclusiveLite routine routine attemps to
|
|
|
|
|
* acquire the given resource for exclusive access.
|
|
|
|
|
*
|
|
|
|
|
* @param Resource
|
|
|
|
|
* Pointer to the resource to be acquired.
|
|
|
|
|
*
|
|
|
|
|
* @return TRUE if the given resource has been acquired for the caller.
|
|
|
|
|
*
|
|
|
|
|
* @remarks Callers of ExTryToAcquireResourceExclusiveLite must be running at
|
|
|
|
|
* IRQL < DISPATCH_LEVEL.
|
|
|
|
|
*
|
|
|
|
|
*--*/
|
|
|
|
|
BOOLEAN
|
|
|
|
|
NTAPI
|
2008-04-22 20:44:34 +00:00
|
|
|
|
ExTryToAcquireResourceExclusiveLite(IN PERESOURCE Resource)
|
2006-01-05 16:24:32 +00:00
|
|
|
|
{
|
|
|
|
|
ERESOURCE_THREAD Thread;
|
2007-05-08 21:35:10 +00:00
|
|
|
|
KLOCK_QUEUE_HANDLE LockHandle;
|
2006-01-05 16:24:32 +00:00
|
|
|
|
BOOLEAN Acquired = FALSE;
|
|
|
|
|
|
|
|
|
|
/* Sanity check */
|
|
|
|
|
ASSERT((Resource->Flag & ResourceNeverExclusive) == 0);
|
|
|
|
|
|
|
|
|
|
/* Get the thread */
|
|
|
|
|
Thread = ExGetCurrentResourceThread();
|
|
|
|
|
|
|
|
|
|
/* Sanity check and validation */
|
|
|
|
|
ASSERT(KeIsExecutingDpc() == FALSE);
|
|
|
|
|
ExpVerifyResource(Resource);
|
|
|
|
|
|
|
|
|
|
/* Acquire the lock */
|
2007-05-08 21:35:10 +00:00
|
|
|
|
ExAcquireResourceLock(Resource, &LockHandle);
|
2006-01-05 16:24:32 +00:00
|
|
|
|
|
|
|
|
|
/* Check if there is an owner */
|
|
|
|
|
if (!Resource->ActiveCount)
|
|
|
|
|
{
|
|
|
|
|
/* No owner, give exclusive access */
|
|
|
|
|
Resource->Flag |= ResourceOwnedExclusive;
|
2008-04-22 20:44:34 +00:00
|
|
|
|
Resource->OwnerEntry.OwnerThread = Thread;
|
|
|
|
|
Resource->OwnerEntry.OwnerCount = 1;
|
2006-01-05 16:24:32 +00:00
|
|
|
|
Resource->ActiveCount = 1;
|
2008-04-22 20:44:34 +00:00
|
|
|
|
Resource->ActiveEntries = 1;
|
2006-01-05 16:24:32 +00:00
|
|
|
|
Acquired = TRUE;
|
|
|
|
|
}
|
|
|
|
|
else if ((IsOwnedExclusive(Resource)) &&
|
2008-04-22 20:44:34 +00:00
|
|
|
|
(Resource->OwnerEntry.OwnerThread == Thread))
|
2006-01-05 16:24:32 +00:00
|
|
|
|
{
|
|
|
|
|
/* Do a recursive acquire */
|
2008-04-22 20:44:34 +00:00
|
|
|
|
Resource->OwnerEntry.OwnerCount++;
|
2006-01-05 16:24:32 +00:00
|
|
|
|
Acquired = TRUE;
|
|
|
|
|
}
|
2005-05-09 01:38:29 +00:00
|
|
|
|
|
2006-01-05 16:24:32 +00:00
|
|
|
|
/* Release the resource */
|
2007-05-08 21:35:10 +00:00
|
|
|
|
ExReleaseResourceLock(Resource, &LockHandle);
|
2006-01-05 16:24:32 +00:00
|
|
|
|
return Acquired;
|
|
|
|
|
}
|
2005-05-09 01:38:29 +00:00
|
|
|
|
|
2006-01-05 16:24:32 +00:00
|
|
|
|
/*++
|
|
|
|
|
* @name ExEnterCriticalRegionAndAcquireResourceExclusive
|
|
|
|
|
* @implemented NT5.1
|
|
|
|
|
*
|
|
|
|
|
* The ExEnterCriticalRegionAndAcquireResourceExclusive enters a critical
|
|
|
|
|
* region and then exclusively acquires a resource.
|
|
|
|
|
*
|
|
|
|
|
* @param Resource
|
|
|
|
|
* Pointer to the resource to acquire.
|
|
|
|
|
*
|
|
|
|
|
* @return Pointer to the Win32K thread pointer of the current thread.
|
|
|
|
|
*
|
|
|
|
|
* @remarks See ExAcquireResourceExclusiveLite.
|
|
|
|
|
*
|
|
|
|
|
*--*/
|
|
|
|
|
PVOID
|
|
|
|
|
NTAPI
|
2007-05-08 21:35:10 +00:00
|
|
|
|
ExEnterCriticalRegionAndAcquireResourceExclusive(IN PERESOURCE Resource)
|
2006-01-05 16:24:32 +00:00
|
|
|
|
{
|
|
|
|
|
/* Enter critical region */
|
|
|
|
|
KeEnterCriticalRegion();
|
2005-05-09 01:38:29 +00:00
|
|
|
|
|
2006-01-05 16:24:32 +00:00
|
|
|
|
/* Acquire the resource */
|
|
|
|
|
ExAcquireResourceExclusiveLite(Resource, TRUE);
|
2005-05-09 01:38:29 +00:00
|
|
|
|
|
2006-01-05 16:24:32 +00:00
|
|
|
|
/* Return the Win32 Thread */
|
|
|
|
|
return KeGetCurrentThread()->Win32Thread;
|
|
|
|
|
}
|
2005-05-09 01:38:29 +00:00
|
|
|
|
|
2008-11-02 14:08:49 +00:00
|
|
|
|
/*++
|
|
|
|
|
* @name ExEnterCriticalRegionAndAcquireResourceShared
|
|
|
|
|
* @implemented NT5.2
|
|
|
|
|
*
|
|
|
|
|
* The ExEnterCriticalRegionAndAcquireResourceShared routine
|
|
|
|
|
* enters a critical region and then acquires a resource shared.
|
|
|
|
|
*
|
|
|
|
|
* @param Resource
|
|
|
|
|
* Pointer to the resource to acquire.
|
|
|
|
|
*
|
|
|
|
|
* @return Pointer to the Win32K thread pointer of the current thread.
|
|
|
|
|
*
|
|
|
|
|
* @remarks See ExAcquireResourceSharedLite.
|
|
|
|
|
*
|
|
|
|
|
*--*/
|
|
|
|
|
PVOID
|
|
|
|
|
NTAPI
|
|
|
|
|
ExEnterCriticalRegionAndAcquireResourceShared(IN PERESOURCE Resource)
|
|
|
|
|
{
|
|
|
|
|
/* Enter critical region */
|
|
|
|
|
KeEnterCriticalRegion();
|
|
|
|
|
|
|
|
|
|
/* Acquire the resource */
|
|
|
|
|
ExAcquireResourceSharedLite(Resource, TRUE);
|
|
|
|
|
|
|
|
|
|
/* Return the Win32 Thread */
|
|
|
|
|
return KeGetCurrentThread()->Win32Thread;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*++
|
|
|
|
|
* @name ExEnterCriticalRegionAndAcquireSharedWaitForExclusive
|
|
|
|
|
* @implemented NT5.2
|
|
|
|
|
*
|
|
|
|
|
* The ExEnterCriticalRegionAndAcquireSharedWaitForExclusive routine
|
|
|
|
|
* enters a critical region and then acquires a resource shared if
|
|
|
|
|
* shared access can be granted and there are no exclusive waiters.
|
|
|
|
|
* It then acquires the resource exclusively.
|
|
|
|
|
*
|
|
|
|
|
* @param Resource
|
|
|
|
|
* Pointer to the resource to acquire.
|
|
|
|
|
*
|
|
|
|
|
* @return Pointer to the Win32K thread pointer of the current thread.
|
|
|
|
|
*
|
|
|
|
|
* @remarks See ExAcquireSharedWaitForExclusive.
|
|
|
|
|
*
|
|
|
|
|
*--*/
|
|
|
|
|
PVOID
|
|
|
|
|
NTAPI
|
|
|
|
|
ExEnterCriticalRegionAndAcquireSharedWaitForExclusive(IN PERESOURCE Resource)
|
|
|
|
|
{
|
|
|
|
|
/* Enter critical region */
|
|
|
|
|
KeEnterCriticalRegion();
|
|
|
|
|
|
|
|
|
|
/* Acquire the resource */
|
|
|
|
|
ExAcquireSharedWaitForExclusive(Resource, TRUE);
|
|
|
|
|
|
|
|
|
|
/* Return the Win32 Thread */
|
|
|
|
|
return KeGetCurrentThread()->Win32Thread;
|
|
|
|
|
}
|
|
|
|
|
|
2006-01-05 16:24:32 +00:00
|
|
|
|
/*++
|
|
|
|
|
* @name ExReleaseResourceAndLeaveCriticalRegion
|
|
|
|
|
* @implemented NT5.1
|
|
|
|
|
*
|
|
|
|
|
* The ExReleaseResourceAndLeaveCriticalRegion release a resource and
|
|
|
|
|
* then leaves a critical region.
|
|
|
|
|
*
|
|
|
|
|
* @param Resource
|
|
|
|
|
* Pointer to the resource to release.
|
|
|
|
|
*
|
|
|
|
|
* @return None
|
|
|
|
|
*
|
|
|
|
|
* @remarks See ExReleaseResourceLite.
|
|
|
|
|
*
|
|
|
|
|
*--*/
|
|
|
|
|
VOID
|
|
|
|
|
FASTCALL
|
2007-05-08 21:35:10 +00:00
|
|
|
|
ExReleaseResourceAndLeaveCriticalRegion(IN PERESOURCE Resource)
|
2006-01-05 16:24:32 +00:00
|
|
|
|
{
|
Implemented:
ExSetResourceOwnerPointer, FsRtlDissectDbcs, FsRtlDoesDbcsContainWildCards, FsRtlAcquireFileExclusive, FsRtlReleaseFile, FsRtlGetNextMcbEntry, FsRtlLookupLastMcbEntry, FsRtlLookupMcbEntry, FsRtlRemoveMcbEntry, FsRtlIncrementCcFastReadResourceMiss, FsRtlIncrementCcFastReadNotPossible, FsRtlIncrementCcFastReadWait, FsRtlIncrementCcFastReadNoWait , FsRtlAreNamesEqual, FsRtlDoesNameContainWildCards, IoCreateDriver, IoDeleteDriver
Thanks to Filip for reviewing some of these.
svn path=/trunk/; revision=12408
2004-12-30 18:30:05 +00:00
|
|
|
|
/* Release the resource */
|
2006-01-05 16:24:32 +00:00
|
|
|
|
ExReleaseResourceLite(Resource);
|
|
|
|
|
|
|
|
|
|
/* Leave critical region */
|
|
|
|
|
KeLeaveCriticalRegion();
|
2000-07-04 01:30:18 +00:00
|
|
|
|
}
|