[NTOSKRNL]

Some keyed event fixes: disable APCs before acquiring the pushlock, close handle on exception, check if a wait was aborted and remove the wait list entry from the list in that case.

svn path=/trunk/; revision=58200
This commit is contained in:
Timo Kreuzer
2013-01-21 20:58:23 +00:00
parent 154f585353
commit 7bc3ce6d8e
+37 -4
View File
@@ -142,6 +142,7 @@ ExpReleaseOrWaitForKeyedEvent(
HashIndex %= NUM_KEY_HASH_BUCKETS;
/* Lock the lists */
KeEnterCriticalRegion();
ExAcquirePushLockExclusive(&KeyedEvent->HashTable[HashIndex].Lock);
/* Get the lists for search and wait, depending on whether
@@ -161,6 +162,10 @@ ExpReleaseOrWaitForKeyedEvent(
ListEntry = WaitListHead1->Flink;
while (ListEntry != WaitListHead1)
{
/* Get the waiting thread. Note that this thread cannot be terminated
as long as we hold the list lock, since it either needs to wait to
be signaled by this thread or, when the wait is aborted due to thread
termination, then it first needs to acquire the list lock. */
Thread = CONTAINING_RECORD(ListEntry, ETHREAD, KeyedWaitChain);
/* Check if this thread is a correct waiter */
@@ -170,11 +175,16 @@ ExpReleaseOrWaitForKeyedEvent(
/* Remove the thread from the list */
RemoveEntryList(&Thread->KeyedWaitChain);
/* Initialize the list entry to show that it was removed */
InitializeListHead(&Thread->KeyedWaitChain);
/* Wake the thread */
KeReleaseSemaphore(&Thread->KeyedWaitSemaphore, 0, 1, FALSE);
Thread = NULL;
/* Unlock the lists */
/* Unlock the list. After this it is not safe to access Thread */
ExReleasePushLockExclusive(&KeyedEvent->HashTable[HashIndex].Lock);
KeLeaveCriticalRegion();
return STATUS_SUCCESS;
}
@@ -192,8 +202,9 @@ ExpReleaseOrWaitForKeyedEvent(
/* Insert the current thread into the secondary wait list */
InsertTailList(WaitListHead2, &CurrentThread->KeyedWaitChain);
/* Unlock the lists */
/* Unlock the list */
ExReleasePushLockExclusive(&KeyedEvent->HashTable[HashIndex].Lock);
KeLeaveCriticalRegion();
/* Wait for the keyed wait semaphore */
Status = KeWaitForSingleObject(&CurrentThread->KeyedWaitSemaphore,
@@ -202,7 +213,26 @@ ExpReleaseOrWaitForKeyedEvent(
Alertable,
Timeout);
return STATUS_SUCCESS;
/* Check if the wait was aborted or timed out */
if (Status != STATUS_SUCCESS)
{
/* Lock the lists to make sure no one else messes with the entry */
KeEnterCriticalRegion();
ExAcquirePushLockExclusive(&KeyedEvent->HashTable[HashIndex].Lock);
/* Check if the wait list entry is still in the list */
if (CurrentThread->KeyedWaitChain.Flink != &CurrentThread->KeyedWaitChain)
{
/* Remove the thread from the list */
RemoveEntryList(&CurrentThread->KeyedWaitChain);
}
/* Unlock the list */
ExReleasePushLockExclusive(&KeyedEvent->HashTable[HashIndex].Lock);
KeLeaveCriticalRegion();
}
return Status;
}
_IRQL_requires_max_(APC_LEVEL)
@@ -274,7 +304,7 @@ NtCreateKeyedEvent(
/* Check for success */
if (!NT_SUCCESS(Status)) return Status;
/* Initalize the keyed event */
/* Initialize the keyed event */
ExpInitializeKeyedEvent(KeyedEvent);
/* Insert it */
@@ -353,6 +383,9 @@ NtOpenKeyedEvent(
{
/* Get the exception code */
Status = _SEH2_GetExceptionCode();
/* Cleanup */
ObCloseHandle(KeyedEventHandle, PreviousMode);
}
_SEH2_END;
}