From b21beacd604d55db14e86b2bd6c61fa34d7575c0 Mon Sep 17 00:00:00 2001 From: Aleksey Bragin Date: Wed, 5 Nov 2008 17:03:04 +0000 Subject: [PATCH] - 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). svn path=/trunk/; revision=37212 --- reactos/ntoskrnl/ke/queue.c | 44 +++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/reactos/ntoskrnl/ke/queue.c b/reactos/ntoskrnl/ke/queue.c index a548a7df098..ce131f03ab9 100644 --- a/reactos/ntoskrnl/ke/queue.c +++ b/reactos/ntoskrnl/ke/queue.c @@ -436,8 +436,7 @@ PLIST_ENTRY 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 @@ KeRundownQueue(IN PKQUEUE Queue) /* Get the Dispatcher Lock */ OldIrql = KiAcquireDispatcherLock(); - - /* Make sure the list is not empty */ - if (!IsListEmpty(&Queue->EntryListHead)) + + /* Check if the list is empty */ + FirstEntry = Queue->EntryListHead.Flink; + if (FirstEntry == &Queue->EntryListHead) { - /* Remove it */ - FirstEntry = RemoveHeadList(&Queue->EntryListHead); + /* We won't return anything */ + FirstEntry = NULL; } - - /* Unlink threads and clear their Thread->Queue */ - ListHead = &Queue->ThreadListHead; - NextEntry = ListHead->Flink; - while (ListHead != NextEntry) + else { - /* Get the Entry's Thread */ + /* 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; }