- 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.

svn path=/trunk/; revision=20793
This commit is contained in:
Hartmut Birr 2006-01-11 23:22:15 +00:00
parent bfce7c398c
commit 424e0d5e8d

View file

@ -535,6 +535,11 @@ ExpFindEntryForThread(IN PERESOURCE Resource,
* @remarks None. * @remarks None.
* *
*--*/ *--*/
#if 0
/*
* Disabled, read the comments bellow.
*/
VOID VOID
FASTCALL FASTCALL
ExpBoostOwnerThread(IN PKTHREAD Thread, ExpBoostOwnerThread(IN PKTHREAD Thread,
@ -570,6 +575,7 @@ ExpBoostOwnerThread(IN PKTHREAD Thread,
} }
} }
} }
#endif
/*++ /*++
* @name ExpWaitForResource * @name ExpWaitForResource
@ -596,7 +602,6 @@ ExpWaitForResource(IN PERESOURCE Resource,
ULONG Size, WaitCount = 0; ULONG Size, WaitCount = 0;
KIRQL OldIrql; KIRQL OldIrql;
POWNER_ENTRY Owner; POWNER_ENTRY Owner;
PKTHREAD OwnerThread, Thread;
NTSTATUS Status; NTSTATUS Status;
LARGE_INTEGER Timeout; LARGE_INTEGER Timeout;
@ -664,10 +669,20 @@ ExpWaitForResource(IN PERESOURCE 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 (!(Resource->Flag & ResourceHasDisabledPriorityBoost))
{ {
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 = KeAcquireDispatcherDatabaseLock(); Thread->WaitIrql = KeAcquireDispatcherDatabaseLock();
@ -700,6 +715,7 @@ ExpWaitForResource(IN PERESOURCE Resource,
} }
} }
} }
#endif
} }
} }
@ -881,10 +897,20 @@ TryAcquire:
Resource, Wait); Resource, Wait);
if (!Resource->ActiveCount) if (!Resource->ActiveCount)
{ {
/* Nobody owns it, so let's take control */ if (Resource->NumberOfSharedWaiters == 0)
{
Owner = &Resource->OwnerThreads[1];
}
else
{
/* Find a free entry */
Owner = ExpFindFreeEntry(Resource, &OldIrql);
if (!Owner) goto TryAcquire;
}
Owner->OwnerThread = Thread;
Owner->OwnerCount = 1;
Resource->ActiveCount = 1; Resource->ActiveCount = 1;
Resource->OwnerThreads[1].OwnerThread = Thread;
Resource->OwnerThreads[1].OwnerCount = 1;
/* Release the lock and return */ /* Release the lock and return */
ExReleaseResourceLock(&Resource->SpinLock, OldIrql); ExReleaseResourceLock(&Resource->SpinLock, OldIrql);
@ -946,7 +972,7 @@ TryAcquire:
{ {
/* Release the lock and return */ /* Release the lock and return */
ExReleaseResourceLock(&Resource->SpinLock, OldIrql); ExReleaseResourceLock(&Resource->SpinLock, OldIrql);
return TRUE; return FALSE;
} }
/* Check if we have a shared waiters semaphore */ /* Check if we have a shared waiters semaphore */
@ -1769,6 +1795,7 @@ ExReleaseResourceLite(PERESOURCE Resource)
{ {
/* Decrement owner count and check if we're done */ /* Decrement owner count and check if we're done */
ASSERT(Resource->OwnerThreads[0].OwnerCount > 0); ASSERT(Resource->OwnerThreads[0].OwnerCount > 0);
ASSERT(Resource->ActiveCount == 1);
if (--Resource->OwnerThreads[0].OwnerCount) if (--Resource->OwnerThreads[0].OwnerCount)
{ {
/* Done, release lock! */ /* Done, release lock! */
@ -1779,45 +1806,42 @@ ExReleaseResourceLite(PERESOURCE Resource)
/* Clear the owner */ /* Clear the owner */
Resource->OwnerThreads[0].OwnerThread = 0; Resource->OwnerThreads[0].OwnerThread = 0;
/* See if the resource isn't being owned anymore */ /* Check if there are shared waiters */
ASSERT(Resource->ActiveCount > 0); if (IsSharedWaiting(Resource))
if (!(--Resource->ActiveCount))
{ {
/* Check if there are shared waiters */
if (IsSharedWaiting(Resource))
{
/* Remove the exclusive flag */
Resource->Flag &= ~ResourceOwnedExclusive;
/* Give ownage to another thread */
Count = Resource->NumberOfSharedWaiters;
Resource->ActiveCount = (USHORT)Count;
Resource->NumberOfSharedWaiters = 0;
/* Release lock and let someone else have it */
ExReleaseResourceLock(&Resource->SpinLock, OldIrql);
KeReleaseSemaphore(Resource->SharedWaiters, 0, Count, FALSE);
return;
}
else if (IsExclusiveWaiting(Resource))
{
/* Give exclusive access */
Resource->OwnerThreads[0].OwnerThread = 1;
Resource->OwnerThreads[0].OwnerCount = 1;
Resource->ActiveCount = 1;
Resource->NumberOfExclusiveWaiters--;
/* Release the lock and give it away */
ExReleaseResourceLock(&Resource->SpinLock, OldIrql);
KeSetEventBoostPriority(Resource->ExclusiveWaiters,
(PKTHREAD*)
&Resource->OwnerThreads[0].OwnerThread);
return;
}
/* Remove the exclusive flag */ /* Remove the exclusive flag */
Resource->Flag &= ~ResourceOwnedExclusive; Resource->Flag &= ~ResourceOwnedExclusive;
}
/* Give ownage to another thread */
Count = Resource->NumberOfSharedWaiters;
Resource->ActiveCount = (USHORT)Count;
Resource->NumberOfSharedWaiters = 0;
/* Release lock and let someone else have it */
ExReleaseResourceLock(&Resource->SpinLock, OldIrql);
KeReleaseSemaphore(Resource->SharedWaiters, 0, Count, FALSE);
return;
}
else if (IsExclusiveWaiting(Resource))
{
/* Give exclusive access */
Resource->OwnerThreads[0].OwnerThread = 1;
Resource->OwnerThreads[0].OwnerCount = 1;
Resource->ActiveCount = 1;
Resource->NumberOfExclusiveWaiters--;
/* Release the lock and give it away */
ExReleaseResourceLock(&Resource->SpinLock, OldIrql);
KeSetEventBoostPriority(Resource->ExclusiveWaiters,
(PKTHREAD*)
&Resource->OwnerThreads[0].OwnerThread);
return;
}
/* Remove the exclusive flag */
Resource->Flag &= ~ResourceOwnedExclusive;
Resource->ActiveCount = 0;
} }
else else
{ {
@ -1827,11 +1851,6 @@ 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 on the second list, 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 */