- Multiple fixes to ERESOURCE implementation.

svn path=/trunk/; revision=25632
This commit is contained in:
Alex Ionescu 2007-01-25 23:48:48 +00:00
parent c4f9542125
commit 32a29de195

View file

@ -20,16 +20,13 @@
#include <ntoskrnl.h> #include <ntoskrnl.h>
#define NDEBUG #define NDEBUG
#include <internal/debug.h> #include <debug.h>
#if defined (ALLOC_PRAGMA)
#pragma alloc_text(INIT, ExpResourceInitialization)
#endif
/* Macros for reading resource flags */ /* Macros for reading resource flags */
#define IsExclusiveWaiting(r) (r->NumberOfExclusiveWaiters) #define IsExclusiveWaiting(r) (r->NumberOfExclusiveWaiters)
#define IsSharedWaiting(r) (r->NumberOfSharedWaiters) #define IsSharedWaiting(r) (r->NumberOfSharedWaiters)
#define IsOwnedExclusive(r) (r->Flag & ResourceOwnedExclusive) #define IsOwnedExclusive(r) (r->Flag & ResourceOwnedExclusive)
#define IsBoostAllowed(r) (r->Flag & ResourceHasDisabledPriorityBoost)
/* DATA***********************************************************************/ /* DATA***********************************************************************/
@ -258,6 +255,7 @@ ExpExpandResourceOwnerTable(IN PERESOURCE_XP Resource,
IN PKIRQL OldIrql) IN PKIRQL OldIrql)
{ {
POWNER_ENTRY Owner, Table; POWNER_ENTRY Owner, Table;
KIRQL OldIrql2;
ULONG NewSize, OldSize; ULONG NewSize, OldSize;
DPRINT("ExpExpandResourceOwnerTable: %p\n", Resource); DPRINT("ExpExpandResourceOwnerTable: %p\n", Resource);
@ -285,7 +283,7 @@ ExpExpandResourceOwnerTable(IN PERESOURCE_XP Resource,
TAG_RESOURCE_TABLE); TAG_RESOURCE_TABLE);
/* Zero the table */ /* Zero the table */
RtlZeroMemory((PVOID)(Table + OldSize), RtlZeroMemory(Table + OldSize,
(NewSize - OldSize) * sizeof(OWNER_ENTRY)); (NewSize - OldSize) * sizeof(OWNER_ENTRY));
/* Lock the resource */ /* Lock the resource */
@ -302,22 +300,24 @@ ExpExpandResourceOwnerTable(IN PERESOURCE_XP Resource,
else else
{ {
/* Copy the table */ /* Copy the table */
RtlCopyMemory((PVOID)Table, RtlCopyMemory(Table,
Owner, Owner,
OldSize * sizeof(OWNER_ENTRY)); OldSize * sizeof(OWNER_ENTRY));
/* Acquire dispatcher lock to prevent thread boosting */ /* Acquire dispatcher lock to prevent thread boosting */
KiAcquireDispatcherLockAtDpcLevel(); OldIrql2 = KiAcquireDispatcherLock();
/* Set the new table data */ /* Set the new table data */
Table->TableSize = NewSize; Table->TableSize = NewSize;
Resource->OwnerTable = Table; Resource->OwnerTable = Table;
/* Release dispatcher lock */
KiReleaseDispatcherLock(OldIrql2);
/* Sanity check */ /* Sanity check */
ExpVerifyResource(Resource); ExpVerifyResource(Resource);
/* Release locks */ /* Release lock */
KiReleaseDispatcherLockFromDpcLevel();
ExReleaseResourceLock(&Resource->SpinLock, *OldIrql); ExReleaseResourceLock(&Resource->SpinLock, *OldIrql);
/* Free the old table */ /* Free the old table */
@ -358,9 +358,7 @@ ExpFindFreeEntry(IN PERESOURCE_XP Resource,
IN PKIRQL OldIrql) IN PKIRQL OldIrql)
{ {
POWNER_ENTRY Owner, Limit; POWNER_ENTRY Owner, Limit;
ULONG Size;
POWNER_ENTRY FreeEntry = NULL; POWNER_ENTRY FreeEntry = NULL;
DPRINT("ExpFindFreeEntry: %p\n", Resource);
/* Sanity check */ /* Sanity check */
ASSERT(OldIrql != 0); ASSERT(OldIrql != 0);
@ -378,34 +376,24 @@ ExpFindFreeEntry(IN PERESOURCE_XP Resource,
Owner = Resource->OwnerTable; Owner = Resource->OwnerTable;
if (Owner) if (Owner)
{ {
/* Loop every entry */ /* Set the limit, move to the next owner and loop owner entries */
Size = Owner->TableSize; Limit = &Owner[Owner->TableSize];
Limit = &Owner[Size];
/* Go to the next entry and loop */
Owner++; Owner++;
do do
{ {
/* Check for a free entry */ /* Check if the entry is free */
if (!Owner->OwnerThread) if (!Owner->OwnerThread)
{ {
/* Found one, return it!*/ /* Update the resource entry and return it */
FreeEntry = Owner; KeGetCurrentThread()->ResourceIndex = (UCHAR)(Owner -
break; Resource->
OwnerTable);
return Owner;
} }
/* Move on */ /* Move to the next one */
Owner++; Owner++;
} while (Owner != Limit); } while (Owner != Limit);
/* If we found a free entry by now, return it */
if (FreeEntry)
{
/* Set the resource index */
KeGetCurrentThread()->ResourceIndex =
(UCHAR)(Owner - Resource->OwnerTable);
return FreeEntry;
}
} }
/* No free entry, expand the table */ /* No free entry, expand the table */
@ -445,64 +433,40 @@ ExpFindEntryForThread(IN PERESOURCE_XP Resource,
IN PKIRQL OldIrql) IN PKIRQL OldIrql)
{ {
POWNER_ENTRY FreeEntry, Owner, Limit; POWNER_ENTRY FreeEntry, Owner, Limit;
ULONG Size;
DPRINT("ExpFindEntryForThread: %p\n", Resource);
/* Start by looking in the static array */ /* Start by looking in the static array */
if (Resource->OwnerThreads[0].OwnerThread == Thread) Owner = &Resource->OwnerThreads[0];
{ if (Owner->OwnerThread == Thread) return Owner;
/* Found it, return it! */ Owner++;
return &Resource->OwnerThreads[0]; if (Owner->OwnerThread == Thread) return Owner;
}
else if (Resource->OwnerThreads[1].OwnerThread == Thread)
{
/* Return it */
return &Resource->OwnerThreads[1];
}
else
{
/* Check if the first array is empty for our use */
FreeEntry = NULL;
if (!Resource->OwnerThreads[1].OwnerThread)
{
/* Use this as the first free entry */
FreeEntry = &Resource->OwnerThreads[1];
}
/* Get the current table pointer */ /* Check if this is a free entry */
FreeEntry = !Owner->OwnerThread ? Owner : NULL;
/* Loop the table */
Owner = Resource->OwnerTable; Owner = Resource->OwnerTable;
if (!Owner) if (Owner)
{ {
/* The current table is empty, so no size */ /* Calculate the limit, skip the first entry, and start looping */
Size = 0; Limit = &Owner[Owner->TableSize];
}
else
{
/* We have a table, get it's size and limit */
Size = Owner->TableSize;
Limit = &Owner[Size];
/* Go to the next entry and loop */
Owner++; Owner++;
do do
{ {
/* Check for a match */ /* Check if we found a match */
if (Owner->OwnerThread == Thread) if (Owner->OwnerThread == Thread)
{ {
/* Match found! Set the resource index */ /* We did, update the index and return it */
KeGetCurrentThread()->ResourceIndex = KeGetCurrentThread()->ResourceIndex = (UCHAR)(Owner -
(UCHAR)(Owner - Resource->OwnerTable); Resource->
OwnerTable);
return Owner; return Owner;
} }
/* If we don't have a free entry yet, make this one free */ /* If we don't yet have a free entry and this one is, choose it */
if (!(FreeEntry) && !(Owner->OwnerThread)) FreeEntry = Owner; if (!(FreeEntry) && !(Owner->OwnerThread)) FreeEntry = Owner;
/* Move on */
Owner++; Owner++;
} while (Owner != Limit); } while (Owner != Limit);
} }
}
/* Check if it's OK to do an expansion */ /* Check if it's OK to do an expansion */
if (!OldIrql) return NULL; if (!OldIrql) return NULL;
@ -511,8 +475,8 @@ ExpFindEntryForThread(IN PERESOURCE_XP Resource,
if (FreeEntry) if (FreeEntry)
{ {
/* Set the resource index */ /* Set the resource index */
KeGetCurrentThread()->ResourceIndex = (UCHAR) KeGetCurrentThread()->ResourceIndex = (UCHAR)(FreeEntry -
(Owner - Resource->OwnerTable); Resource->OwnerTable);
return FreeEntry; return FreeEntry;
} }
@ -538,19 +502,11 @@ ExpFindEntryForThread(IN PERESOURCE_XP Resource,
* @remarks None. * @remarks None.
* *
*--*/ *--*/
#if 0
/*
* Disabled, read the comments bellow.
*/
VOID VOID
FASTCALL FASTCALL
ExpBoostOwnerThread(IN PKTHREAD Thread, ExpBoostOwnerThread(IN PKTHREAD Thread,
IN PKTHREAD OwnerThread) IN PKTHREAD OwnerThread)
{ {
BOOLEAN Released = FALSE;
DPRINT("ExpBoostOwnerThread: %p\n", Thread);
/* Make sure the owner thread is a pointer, not an ID */ /* Make sure the owner thread is a pointer, not an ID */
if (!((ULONG_PTR)OwnerThread & 0x3)) if (!((ULONG_PTR)OwnerThread & 0x3))
{ {
@ -558,8 +514,8 @@ ExpBoostOwnerThread(IN PKTHREAD Thread,
if ((OwnerThread->Priority < Thread->Priority) && if ((OwnerThread->Priority < Thread->Priority) &&
(OwnerThread->Priority < 14)) (OwnerThread->Priority < 14))
{ {
/* Make sure we're at dispatch */ /* Acquire the thread lock */
ASSERT(KeGetCurrentIrql() >= DISPATCH_LEVEL); KiAcquireThreadLock(Thread);
/* Set the new priority */ /* Set the new priority */
OwnerThread->PriorityDecrement += 14 - OwnerThread->Priority; OwnerThread->PriorityDecrement += 14 - OwnerThread->Priority;
@ -568,17 +524,13 @@ ExpBoostOwnerThread(IN PKTHREAD Thread,
OwnerThread->Quantum = OwnerThread->QuantumReset; OwnerThread->Quantum = OwnerThread->QuantumReset;
/* Update the kernel state */ /* Update the kernel state */
KiSetPriorityThread(OwnerThread, 14, &Released); KiSetPriorityThread(OwnerThread, 14);
/* Reacquire lock if it got releases */ /* Release the thread lock */
if (Released) KiAcquireDispatcherLockFromDpcLevel(); KiReleaseThreadLock(Thread);
/* Make sure we're still at dispatch */
ASSERT(KeGetCurrentIrql() >= DISPATCH_LEVEL);
} }
} }
} }
#endif
/*++ /*++
* @name ExpWaitForResource * @name ExpWaitForResource
@ -601,20 +553,21 @@ FASTCALL
ExpWaitForResource(IN PERESOURCE_XP Resource, ExpWaitForResource(IN PERESOURCE_XP Resource,
IN PVOID Object) IN PVOID Object)
{ {
#if DBG
ULONG i; ULONG i;
ULONG Size; ULONG Size;
KIRQL OldIrql;
POWNER_ENTRY Owner; POWNER_ENTRY Owner;
#endif
ULONG WaitCount = 0; ULONG WaitCount = 0;
NTSTATUS Status; NTSTATUS Status;
LARGE_INTEGER Timeout; LARGE_INTEGER Timeout;
PKTHREAD Thread, OwnerThread;
#if DBG
KIRQL OldIrql;
#endif
/* Increase contention count and use a 5 second timeout */ /* Increase contention count and use a 5 second timeout */
Resource->ContentionCount++; Resource->ContentionCount++;
Timeout.QuadPart = 500 * -10000; Timeout.QuadPart = 500 * -10000;
for(;;) for (;;)
{ {
/* Wait for ownership */ /* Wait for ownership */
Status = KeWaitForSingleObject(Object, Status = KeWaitForSingleObject(Object,
@ -675,20 +628,10 @@ ExpWaitForResource(IN PERESOURCE_XP Resource,
ExReleaseResourceLock(&Resource->SpinLock, OldIrql); ExReleaseResourceLock(&Resource->SpinLock, OldIrql);
#endif #endif
} }
#if 0
/*
* Disabled because:
* - We cannot access the OwnerTable without locking the resource.
* - The shared waiters may wait also on the semaphore. It makes no sense to boost a waiting thread.
* - The thread header is initialized like KeWaitForSingleObject (?, ?, ?, TRUE, ?).
* During the boost, possible the dispatcher lock is released but the thread block (WaitNext) isn't changed.
*/
/* Check if we can boost */ /* Check if we can boost */
if (!(Resource->Flag & ResourceHasDisabledPriorityBoost)) if (IsBoostAllowed(Resource))
{ {
PKTHREAD Thread, OwnerThread;
/* Get the current kernel thread and lock the dispatcher */ /* Get the current kernel thread and lock the dispatcher */
Thread = KeGetCurrentThread(); Thread = KeGetCurrentThread();
Thread->WaitIrql = KiAcquireDispatcherLock(); Thread->WaitIrql = KiAcquireDispatcherLock();
@ -725,7 +668,6 @@ ExpWaitForResource(IN PERESOURCE_XP Resource,
} }
} }
} }
#endif
} }
} }
@ -791,8 +733,6 @@ ExAcquireResourceExclusiveLite(PERESOURCE resource,
/* Check if there is a shared owner or exclusive owner */ /* Check if there is a shared owner or exclusive owner */
TryAcquire: TryAcquire:
DPRINT("ExAcquireResourceExclusiveLite(Resource 0x%p, Wait %d)\n",
Resource, Wait);
if (Resource->ActiveCount) if (Resource->ActiveCount)
{ {
/* Check if it's exclusively owned, and we own it */ /* Check if it's exclusively owned, and we own it */
@ -831,7 +771,7 @@ TryAcquire:
ExpWaitForResource(Resource, Resource->ExclusiveWaiters); ExpWaitForResource(Resource, Resource->ExclusiveWaiters);
/* Set owner and return success */ /* Set owner and return success */
Resource->OwnerThreads[0].OwnerThread = Thread; Resource->OwnerThreads[0].OwnerThread = ExGetCurrentResourceThread();
return TRUE; return TRUE;
} }
} }
@ -905,21 +845,10 @@ ExAcquireResourceSharedLite(PERESOURCE resource,
/* See if nobody owns us */ /* See if nobody owns us */
TryAcquire: TryAcquire:
DPRINT("ExAcquireResourceSharedLite(Resource 0x%p, Wait %d)\n",
Resource, Wait);
if (!Resource->ActiveCount) if (!Resource->ActiveCount)
{ {
if (Resource->NumberOfSharedWaiters == 0) /* Setup the owner entry */
{
Owner = &Resource->OwnerThreads[1]; Owner = &Resource->OwnerThreads[1];
}
else
{
/* Find a free entry */
Owner = ExpFindFreeEntry(Resource, &OldIrql);
if (!Owner) goto TryAcquire;
}
Owner->OwnerThread = Thread; Owner->OwnerThread = Thread;
Owner->OwnerCount = 1; Owner->OwnerCount = 1;
Resource->ActiveCount = 1; Resource->ActiveCount = 1;
@ -1066,8 +995,6 @@ ExAcquireSharedStarveExclusive(PERESOURCE resource,
/* See if nobody owns us */ /* See if nobody owns us */
TryAcquire: TryAcquire:
DPRINT("ExAcquireSharedStarveExclusive(Resource 0x%p, Wait %d)\n",
Resource, Wait);
if (!Resource->ActiveCount) if (!Resource->ActiveCount)
{ {
/* Nobody owns it, so let's take control */ /* Nobody owns it, so let's take control */
@ -1097,22 +1024,6 @@ TryAcquire:
/* Find a free entry */ /* Find a free entry */
Owner = ExpFindFreeEntry(Resource, &OldIrql); Owner = ExpFindFreeEntry(Resource, &OldIrql);
if (!Owner) goto TryAcquire; if (!Owner) goto TryAcquire;
/* If we got here, then we need to wait. Are we allowed? */
if (!Wait)
{
/* Release the lock and return */
ExReleaseResourceLock(&Resource->SpinLock, OldIrql);
return TRUE;
}
/* Check if we have a shared waiters semaphore */
if (!Resource->SharedWaiters)
{
/* Allocate one and try again */
ExpAllocateSharedWaiterSemaphore(Resource, &OldIrql);
goto TryAcquire;
}
} }
else else
{ {
@ -1194,8 +1105,8 @@ TryAcquire:
*--*/ *--*/
BOOLEAN BOOLEAN
NTAPI NTAPI
ExAcquireSharedWaitForExclusive(PERESOURCE resource, ExAcquireSharedWaitForExclusive(IN PERESOURCE resource,
BOOLEAN Wait) IN BOOLEAN Wait)
{ {
KIRQL OldIrql; KIRQL OldIrql;
ERESOURCE_THREAD Thread; ERESOURCE_THREAD Thread;
@ -1214,8 +1125,6 @@ ExAcquireSharedWaitForExclusive(PERESOURCE resource,
/* See if nobody owns us */ /* See if nobody owns us */
TryAcquire: TryAcquire:
DPRINT("ExAcquireSharedWaitForExclusive(Resource 0x%p, Wait %d)\n",
Resource, Wait);
if (!Resource->ActiveCount) if (!Resource->ActiveCount)
{ {
/* Nobody owns it, so let's take control */ /* Nobody owns it, so let's take control */
@ -1241,38 +1150,10 @@ TryAcquire:
ExReleaseResourceLock(&Resource->SpinLock, OldIrql); ExReleaseResourceLock(&Resource->SpinLock, OldIrql);
return TRUE; return TRUE;
} }
else
{
/* Find a free entry */ /* Find a free entry */
Owner = ExpFindFreeEntry(Resource, &OldIrql); Owner = ExpFindFreeEntry(Resource, &OldIrql);
if (!Owner) goto TryAcquire; if (!Owner) goto TryAcquire;
/* If we got here, then we need to wait. Are we allowed? */
if (!Wait)
{
/* Release the lock and return */
ExReleaseResourceLock(&Resource->SpinLock, OldIrql);
return TRUE;
}
/* Check if we have a shared waiters semaphore */
if (!Resource->SharedWaiters)
{
/* Allocate one and try again */
ExpAllocateSharedWaiterSemaphore(Resource, &OldIrql);
goto TryAcquire;
}
/* Now take control of the resource */
Owner->OwnerThread = Thread;
Owner->OwnerCount = 1;
Resource->NumberOfSharedWaiters++;
/* Release the lock and wait for it to be ours */
ExReleaseResourceLock(&Resource->SpinLock, OldIrql);
ExpWaitForResource(Resource, Resource->SharedWaiters);
return TRUE;
}
} }
else else
{ {
@ -1304,7 +1185,7 @@ TryAcquire:
ExAcquireResourceLock(&Resource->SpinLock, &OldIrql); ExAcquireResourceLock(&Resource->SpinLock, &OldIrql);
/* Find who owns it now */ /* Find who owns it now */
Owner = ExpFindEntryForThread(Resource, Thread, &OldIrql); while (!(Owner = ExpFindEntryForThread(Resource, Thread, &OldIrql)));
/* Sanity checks */ /* Sanity checks */
ASSERT(IsOwnedExclusive(Resource) == FALSE); ASSERT(IsOwnedExclusive(Resource) == FALSE);
@ -1347,6 +1228,32 @@ TryAcquire:
return TRUE; return TRUE;
} }
} }
/* We have to wait for the exclusive waiter to be done */
if (!Wait)
{
/* So bail out if we're not allowed */
ExReleaseResourceLock(&Resource->SpinLock, OldIrql);
return TRUE;
}
/* Check if we have a shared waiters semaphore */
if (!Resource->SharedWaiters)
{
/* Allocate one and try again */
ExpAllocateSharedWaiterSemaphore(Resource, &OldIrql);
goto TryAcquire;
}
/* Take control */
Owner->OwnerThread = Thread;
Owner->OwnerCount = 1;
Resource->NumberOfSharedWaiters++;
/* Release the lock and return */
ExReleaseResourceLock(&Resource->SpinLock, OldIrql);
ExpWaitForResource(Resource, Resource->SharedWaiters);
return TRUE;
} }
/*++ /*++
@ -1372,10 +1279,6 @@ ExConvertExclusiveToSharedLite(PERESOURCE resource)
ULONG OldWaiters; ULONG OldWaiters;
KIRQL OldIrql; KIRQL OldIrql;
PERESOURCE_XP Resource = (PERESOURCE_XP)resource; PERESOURCE_XP Resource = (PERESOURCE_XP)resource;
DPRINT("ExConvertExclusiveToSharedLite(Resource 0x%p)\n", Resource);
/* Lock the resource */
ExAcquireResourceLock(&Resource->SpinLock, &OldIrql);
/* Sanity checks */ /* Sanity checks */
ASSERT(KeIsExecutingDpc() == FALSE); ASSERT(KeIsExecutingDpc() == FALSE);
@ -1383,14 +1286,17 @@ ExConvertExclusiveToSharedLite(PERESOURCE resource)
ASSERT(IsOwnedExclusive(Resource)); ASSERT(IsOwnedExclusive(Resource));
ASSERT(Resource->OwnerThreads[0].OwnerThread == (ERESOURCE_THREAD)PsGetCurrentThread()); ASSERT(Resource->OwnerThreads[0].OwnerThread == (ERESOURCE_THREAD)PsGetCurrentThread());
/* Lock the resource */
ExAcquireResourceLock(&Resource->SpinLock, &OldIrql);
/* Erase the exclusive flag */ /* Erase the exclusive flag */
Resource->Flag &= ~ResourceOwnedExclusive; Resource->Flag &= ~ResourceOwnedExclusive;
/* Check if we have shared waiters */ /* Check if we have shared waiters */
OldWaiters = Resource->NumberOfSharedWaiters; if (IsSharedWaiting(Resource))
if (OldWaiters)
{ {
/* Make the waiters active owners */ /* Make the waiters active owners */
OldWaiters = Resource->NumberOfSharedWaiters;
Resource->ActiveCount = Resource->ActiveCount + (USHORT)OldWaiters; Resource->ActiveCount = Resource->ActiveCount + (USHORT)OldWaiters;
Resource->NumberOfSharedWaiters = 0; Resource->NumberOfSharedWaiters = 0;
@ -1427,7 +1333,6 @@ ExDeleteResourceLite(PERESOURCE resource)
{ {
KIRQL OldIrql; KIRQL OldIrql;
PERESOURCE_XP Resource = (PERESOURCE_XP)resource; PERESOURCE_XP Resource = (PERESOURCE_XP)resource;
DPRINT("ExDeleteResourceLite(Resource 0x%p)\n", Resource);
/* Sanity checks */ /* Sanity checks */
ASSERT(IsSharedWaiting(Resource) == FALSE); ASSERT(IsSharedWaiting(Resource) == FALSE);
@ -1559,7 +1464,6 @@ NTAPI
ExInitializeResourceLite(PERESOURCE resource) ExInitializeResourceLite(PERESOURCE resource)
{ {
PERESOURCE_XP Resource = (PERESOURCE_XP)resource; PERESOURCE_XP Resource = (PERESOURCE_XP)resource;
DPRINT("ExInitializeResourceLite(Resource 0x%p)\n", Resource);
/* Clear the structure */ /* Clear the structure */
RtlZeroMemory(Resource, sizeof(ERESOURCE_XP)); RtlZeroMemory(Resource, sizeof(ERESOURCE_XP));
@ -1806,7 +1710,6 @@ ExReleaseResourceLite(PERESOURCE resource)
KIRQL OldIrql; KIRQL OldIrql;
POWNER_ENTRY Owner, Limit; POWNER_ENTRY Owner, Limit;
PERESOURCE_XP Resource = (PERESOURCE_XP)resource; PERESOURCE_XP Resource = (PERESOURCE_XP)resource;
DPRINT("ExReleaseResourceLite: %p\n", Resource);
/* Sanity check */ /* Sanity check */
ExpVerifyResource(Resource); ExpVerifyResource(Resource);
@ -1832,6 +1735,10 @@ ExReleaseResourceLite(PERESOURCE resource)
/* Clear the owner */ /* Clear the owner */
Resource->OwnerThreads[0].OwnerThread = 0; Resource->OwnerThreads[0].OwnerThread = 0;
/* Check the active count */
ASSERT(Resource->ActiveCount > 0);
if (!(--Resource->ActiveCount))
{
/* Check if there are shared waiters */ /* Check if there are shared waiters */
if (IsSharedWaiting(Resource)) if (IsSharedWaiting(Resource))
{ {
@ -1840,7 +1747,7 @@ ExReleaseResourceLite(PERESOURCE resource)
/* Give ownage to another thread */ /* Give ownage to another thread */
Count = Resource->NumberOfSharedWaiters; Count = Resource->NumberOfSharedWaiters;
Resource->ActiveCount = (USHORT)Count; Resource->ActiveCount = (SHORT)Count;
Resource->NumberOfSharedWaiters = 0; Resource->NumberOfSharedWaiters = 0;
/* Release lock and let someone else have it */ /* Release lock and let someone else have it */
@ -1863,11 +1770,10 @@ ExReleaseResourceLite(PERESOURCE resource)
&Resource->OwnerThreads[0].OwnerThread); &Resource->OwnerThreads[0].OwnerThread);
return; return;
} }
}
/* Remove the exclusive flag */ /* Remove the exclusive flag */
Resource->Flag &= ~ResourceOwnedExclusive; Resource->Flag &= ~ResourceOwnedExclusive;
Resource->ActiveCount = 0;
} }
else else
{ {
@ -1877,6 +1783,11 @@ ExReleaseResourceLite(PERESOURCE resource)
/* Found it, get owner */ /* Found it, get owner */
Owner = &Resource->OwnerThreads[1]; Owner = &Resource->OwnerThreads[1];
} }
else if (Resource->OwnerThreads[0].OwnerThread == Thread)
{
/* Found it, get owner */
Owner = &Resource->OwnerThreads[0];
}
else else
{ {
/* Not in the list, do a full table look up */ /* Not in the list, do a full table look up */
@ -1965,7 +1876,6 @@ ExReleaseResourceLite(PERESOURCE resource)
/* Release lock */ /* Release lock */
ExReleaseResourceLock(&Resource->SpinLock, OldIrql); ExReleaseResourceLock(&Resource->SpinLock, OldIrql);
return;
} }
/*++ /*++
@ -1998,7 +1908,6 @@ ExReleaseResourceForThreadLite(PERESOURCE resource,
POWNER_ENTRY Owner; POWNER_ENTRY Owner;
PERESOURCE_XP Resource = (PERESOURCE_XP)resource; PERESOURCE_XP Resource = (PERESOURCE_XP)resource;
ASSERT(Thread != 0); ASSERT(Thread != 0);
DPRINT("ExReleaseResourceForThreadLite: %p\n", Resource);
/* Get the thread and lock the resource */ /* Get the thread and lock the resource */
ExAcquireResourceLock(&Resource->SpinLock, &OldIrql); ExAcquireResourceLock(&Resource->SpinLock, &OldIrql);
@ -2034,7 +1943,7 @@ ExReleaseResourceForThreadLite(PERESOURCE resource,
/* Give ownage to another thread */ /* Give ownage to another thread */
Count = Resource->NumberOfSharedWaiters; Count = Resource->NumberOfSharedWaiters;
Resource->ActiveCount = (USHORT)Count; Resource->ActiveCount = (SHORT)Count;
Resource->NumberOfSharedWaiters = 0; Resource->NumberOfSharedWaiters = 0;
/* Release lock and let someone else have it */ /* Release lock and let someone else have it */
@ -2147,7 +2056,6 @@ ExReleaseResourceForThreadLite(PERESOURCE resource,
/* Release lock */ /* Release lock */
ExReleaseResourceLock(&Resource->SpinLock, OldIrql); ExReleaseResourceLock(&Resource->SpinLock, OldIrql);
return;
} }
/*++ /*++
@ -2266,7 +2174,6 @@ ExTryToAcquireResourceExclusiveLite(PERESOURCE resource)
KIRQL OldIrql; KIRQL OldIrql;
BOOLEAN Acquired = FALSE; BOOLEAN Acquired = FALSE;
PERESOURCE_XP Resource = (PERESOURCE_XP)resource; PERESOURCE_XP Resource = (PERESOURCE_XP)resource;
DPRINT("ExTryToAcquireResourceExclusiveLite: %p\n", Resource);
/* Sanity check */ /* Sanity check */
ASSERT((Resource->Flag & ResourceNeverExclusive) == 0); ASSERT((Resource->Flag & ResourceNeverExclusive) == 0);