Author: fireball
Date: Wed Nov 5 18:03:04 2008
New Revision: 37212
URL:
http://svn.reactos.org/svn/reactos?rev=37212&view=rev
Log:
- Fix behavior of KeRundownQueue (save the next link before freeing it and use proper
locking and enumeration code).
- This fixes behavior of I/O completion ports (thanks to Stefan and Alex for testing,
reporting and fixing).
Modified:
trunk/reactos/ntoskrnl/ke/queue.c
Modified: trunk/reactos/ntoskrnl/ke/queue.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/queue.c?rev=37…
==============================================================================
--- trunk/reactos/ntoskrnl/ke/queue.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/ke/queue.c [iso-8859-1] Wed Nov 5 18:03:04 2008
@@ -436,8 +436,7 @@
NTAPI
KeRundownQueue(IN PKQUEUE Queue)
{
- PLIST_ENTRY ListHead, NextEntry;
- PLIST_ENTRY FirstEntry = NULL;
+ PLIST_ENTRY FirstEntry, NextEntry;
PKTHREAD Thread;
KIRQL OldIrql;
ASSERT_QUEUE(Queue);
@@ -446,34 +445,41 @@
/* Get the Dispatcher Lock */
OldIrql = KiAcquireDispatcherLock();
-
- /* Make sure the list is not empty */
- if (!IsListEmpty(&Queue->EntryListHead))
- {
- /* Remove it */
- FirstEntry = RemoveHeadList(&Queue->EntryListHead);
- }
-
- /* Unlink threads and clear their Thread->Queue */
- ListHead = &Queue->ThreadListHead;
- NextEntry = ListHead->Flink;
- while (ListHead != NextEntry)
- {
- /* Get the Entry's Thread */
+
+ /* Check if the list is empty */
+ FirstEntry = Queue->EntryListHead.Flink;
+ if (FirstEntry == &Queue->EntryListHead)
+ {
+ /* We won't return anything */
+ FirstEntry = NULL;
+ }
+ else
+ {
+ /* Remove this entry */
+ RemoveEntryList(&Queue->EntryListHead);
+ }
+
+ /* Loop the list */
+ while (!IsListEmpty(&Queue->ThreadListHead))
+ {
+ /* Get the next entry */
+ NextEntry = Queue->ThreadListHead.Flink;
+
+ /* Get the associated thread */
Thread = CONTAINING_RECORD(NextEntry, KTHREAD, QueueListEntry);
- /* Kill its Queue */
+ /* Clear its queue */
Thread->Queue = NULL;
/* Remove this entry */
RemoveEntryList(NextEntry);
-
- /* Get the next entry */
- NextEntry = NextEntry->Flink;
- }
-
- /* Release the lock and return */
- KiReleaseDispatcherLock(OldIrql);
+ }
+
+ /* Release the dispatcher lock */
+ KiReleaseDispatcherLockFromDpcLevel();
+
+ /* Exit the dispatcher and return the first entry (if any) */
+ KiExitDispatcher(OldIrql);
return FirstEntry;
}