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=372... ============================================================================== --- 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; }