8 modified files
reactos/ntoskrnl/ke
diff -u -r1.69 -r1.70
--- apc.c 21 Nov 2004 06:51:18 -0000 1.69
+++ apc.c 21 Nov 2004 18:33:54 -0000 1.70
@@ -124,7 +124,7 @@
PLIST_ENTRY ApcListEntry;
PKAPC QueuedApc;
- ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
+ ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
DPRINT ("KeInsertQueueApc(Apc %x, SystemArgument1 %x, "
"SystemArgument2 %x)\n",Apc,SystemArgument1,
SystemArgument2);
@@ -134,7 +134,9 @@
/* Get the Thread specified in the APC */
Thread = Apc->Thread;
- /* Make sure the thread allows APC Queues */
+ /* Make sure the thread allows APC Queues.
+ * The thread is not apc queueable, for instance, when it's (about to be) terminated.
+ */
if (Thread->ApcQueueable == FALSE) {
DPRINT("Thread doesn't allow APC Queues\n");
KeReleaseDispatcherDatabaseLock(OldIrql);
@@ -194,18 +196,20 @@
/* FIXME: Use IPI */
DPRINT ("Requesting APC Interrupt for Running Thread \n");
HalRequestSoftwareInterrupt(APC_LEVEL);
- } else if ((Thread->WaitIrql < APC_LEVEL) && (Apc->NormalRoutine == NULL)) {
+ } else if ((Thread->State == THREAD_STATE_BLOCKED) &&
+ (Thread->WaitIrql < APC_LEVEL) &&
+ (Apc->NormalRoutine == NULL))
+ {
DPRINT ("Waking up Thread for Kernel-Mode APC Delivery \n");
- KeRemoveAllWaitsThread(CONTAINING_RECORD(Thread, ETHREAD, Tcb),
- STATUS_KERNEL_APC,
- TRUE);
+ KiAbortWaitThread(Thread, STATUS_KERNEL_APC);
}
- } else if ((Thread->WaitMode == UserMode) && (Thread->Alertable)) {
+ } else if ((Thread->State == THREAD_STATE_BLOCKED) &&
+ (Thread->WaitMode == UserMode) &&
+ (Thread->Alertable))
+ {
DPRINT ("Waking up Thread for User-Mode APC Delivery \n");
Thread->ApcState.UserApcPending = TRUE;
- KeRemoveAllWaitsThread(CONTAINING_RECORD(Thread, ETHREAD, Tcb),
- STATUS_USER_APC,
- TRUE);
+ KiAbortWaitThread(Thread, STATUS_USER_APC);
}
/* Return Sucess if we are here */
@@ -227,7 +231,7 @@
KIRQL OldIrql;
PKTHREAD Thread = Apc->Thread;
- ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
+ ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
DPRINT("KeRemoveQueueApc called for APC: %x \n", Apc);
OldIrql = KeAcquireDispatcherDatabaseLock();
@@ -270,7 +274,7 @@
PKTHREAD Thread = KeGetCurrentThread();
BOOLEAN OldState;
- ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
+ ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
OldIrql = KeAcquireDispatcherDatabaseLock();
KiAcquireSpinLock(&Thread->ApcQueueLock);
@@ -295,7 +299,7 @@
*/
VOID
STDCALL
-KiDeliverApc(KPROCESSOR_MODE PreviousMode,
+KiDeliverApc(KPROCESSOR_MODE DeliveryMode,
PVOID Reserved,
PKTRAP_FRAME TrapFrame)
/*
@@ -317,6 +321,8 @@
PKNORMAL_ROUTINE NormalRoutine;
PVOID SystemArgument1;
PVOID SystemArgument2;
+
+ ASSERT_IRQL_EQUAL(APC_LEVEL);
/* Lock the APC Queue and Raise IRQL to Synch */
KeAcquireSpinLock(&Thread->ApcQueueLock, &OldIrql);
@@ -339,7 +345,7 @@
SystemArgument2 = Apc->SystemArgument2;
/* Special APC */
- if (NormalRoutine == NULL) {
+ if (NormalRoutine == NULL) {
/* Remove the APC from the list */
Apc->Inserted = FALSE;
RemoveEntryList(ApcListEntry);
@@ -360,6 +366,15 @@
} else {
/* Normal Kernel APC */
if (Thread->ApcState.KernelApcInProgress || Thread->KernelApcDisable) {
+
+ /*
+ * DeliveryMode must be KernelMode in this case, since one may not
+ * return to umode while being inside a critical section or while
+ * a regular kmode apc is running (the latter should be impossible btw).
+ * -Gunnar
+ */
+ ASSERT(DeliveryMode == KernelMode);
+
KeReleaseSpinLock(&Thread->ApcQueueLock, OldIrql);
return;
}
@@ -399,7 +414,7 @@
/* Now we do the User APCs */
if ((!IsListEmpty(&Thread->ApcState.ApcListHead[UserMode])) &&
- (PreviousMode == UserMode) &&
+ (DeliveryMode == UserMode) &&
(Thread->ApcState.UserApcPending == TRUE)) {
/* It's not pending anymore */
@@ -418,6 +433,8 @@
/* Remove the APC from Queue, restore IRQL and call the APC */
RemoveEntryList(ApcListEntry);
+ Apc->Inserted = FALSE;
+
KeReleaseSpinLock(&Thread->ApcQueueLock, OldIrql);
DPRINT("Calling the Kernel Routine for for a User APC: %x\n", Apc);
KernelRoutine(Apc,
reactos/ntoskrnl/ke
diff -u -r1.10 -r1.11
--- critical.c 15 Aug 2004 16:39:05 -0000 1.10
+++ critical.c 21 Nov 2004 18:33:54 -0000 1.11
@@ -1,4 +1,4 @@
-/* $Id: critical.c,v 1.10 2004/08/15 16:39:05 chorns Exp $
+/* $Id: critical.c,v 1.11 2004/11/21 18:33:54 gdalsnes Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@@ -22,8 +22,13 @@
*/
VOID STDCALL KeEnterCriticalRegion (VOID)
{
+ PKTHREAD Thread = KeGetCurrentThread();
+
DPRINT("KeEnterCriticalRegion()\n");
- KeGetCurrentThread()->KernelApcDisable--;
+
+ if (!Thread) return; /* <-Early in the boot process the current thread is obseved to be NULL */
+
+ Thread->KernelApcDisable--;
}
/*
@@ -34,6 +39,8 @@
PKTHREAD Thread = KeGetCurrentThread();
DPRINT("KeLeaveCriticalRegion()\n");
+
+ if (!Thread) return; /* <-Early in the boot process the current thread is obseved to be NULL */
/* Reference: http://www.ntfsd.org/archive/ntfsd0104/msg0203.html */
if(++Thread->KernelApcDisable == 0)
reactos/ntoskrnl/ke
diff -u -r1.22 -r1.23
--- event.c 22 Oct 2004 20:30:47 -0000 1.22
+++ event.c 21 Nov 2004 18:33:54 -0000 1.23
@@ -67,6 +67,9 @@
*/
LONG STDCALL KeResetEvent (PKEVENT Event)
{
+ /* FIXME: must use interlocked func. everywhere! (wait.c)
+ * or use dispather lock instead
+ * -Gunnar */
return(InterlockedExchange(&(Event->Header.SignalState),0));
}
@@ -86,7 +89,7 @@
ret = InterlockedExchange(&(Event->Header.SignalState),1);
- KeDispatcherObjectWake((DISPATCHER_HEADER *)Event);
+ KiDispatcherObjectWake((DISPATCHER_HEADER *)Event);
if (Wait == FALSE)
{
@@ -115,7 +118,7 @@
DPRINT("KePulseEvent(Event %x, Wait %x)\n",Event,Wait);
OldIrql = KeAcquireDispatcherDatabaseLock();
ret = InterlockedExchange(&(Event->Header.SignalState),1);
- KeDispatcherObjectWake((DISPATCHER_HEADER *)Event);
+ KiDispatcherObjectWake((DISPATCHER_HEADER *)Event);
InterlockedExchange(&(Event->Header.SignalState),0);
if (Wait == FALSE)
@@ -143,7 +146,10 @@
)
{
PKTHREAD WaitingThread;
+ KIRQL OldIrql;
+ OldIrql = KeAcquireDispatcherDatabaseLock();
+
/* Get Thread that is currently waiting. First get the Wait Block, then the Thread */
WaitingThread = CONTAINING_RECORD(Event->Header.WaitListHead.Flink, KWAIT_BLOCK, WaitListEntry)->Thread;
@@ -152,7 +158,9 @@
/* Reset the Quantum and Unwait the Thread */
WaitingThread->Quantum = WaitingThread->ApcState.Process->ThreadQuantum;
- KeRemoveAllWaitsThread((PETHREAD)WaitingThread, STATUS_SUCCESS, TRUE);
+ KiAbortWaitThread(WaitingThread, STATUS_SUCCESS);
+
+ KeReleaseDispatcherDatabaseLock(OldIrql);
}
/* EOF */
reactos/ntoskrnl/ke
diff -u -r1.18 -r1.19
--- mutex.c 22 Oct 2004 20:30:48 -0000 1.18
+++ mutex.c 21 Nov 2004 18:33:54 -0000 1.19
@@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-/* $Id: mutex.c,v 1.18 2004/10/22 20:30:48 ekohl Exp $
+/* $Id: mutex.c,v 1.19 2004/11/21 18:33:54 gdalsnes Exp $
*
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ke/mutex.c
@@ -82,7 +82,7 @@
Mutex->OwnerThread = NULL;
if (Mutex->MutantListEntry.Flink && Mutex->MutantListEntry.Blink)
RemoveEntryList(&Mutex->MutantListEntry);
- KeDispatcherObjectWake(&Mutex->Header);
+ KiDispatcherObjectWake(&Mutex->Header);
}
if (Wait == FALSE)
@@ -191,7 +191,7 @@
Mutant->OwnerThread = NULL;
if (Mutant->MutantListEntry.Flink && Mutant->MutantListEntry.Blink)
RemoveEntryList(&Mutant->MutantListEntry);
- KeDispatcherObjectWake(&Mutant->Header);
+ KiDispatcherObjectWake(&Mutant->Header);
}
if (Wait == FALSE)
reactos/ntoskrnl/ke
diff -u -r1.11 -r1.12
--- queue.c 15 Aug 2004 16:39:05 -0000 1.11
+++ queue.c 21 Nov 2004 18:33:54 -0000 1.12
@@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-/* $Id: queue.c,v 1.11 2004/08/15 16:39:05 chorns Exp $
+/* $Id: queue.c,v 1.12 2004/11/21 18:33:54 gdalsnes Exp $
*
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ke/queue.c
@@ -34,6 +34,7 @@
/* FUNCTIONS *****************************************************************/
+
/*
* @implemented
*/
@@ -54,6 +55,8 @@
/*
* @implemented
+ *
+ * Returns number of entries in the queue
*/
LONG STDCALL
KeReadStateQueue(IN PKQUEUE Queue)
@@ -61,7 +64,9 @@
return(Queue->Header.SignalState);
}
-
+/*
+ * Returns the previous number of entries in the queue
+ */
LONG STDCALL
KiInsertQueue(
IN PKQUEUE Queue,
@@ -70,15 +75,11 @@
)
{
ULONG InitialState;
- KIRQL OldIrql;
DPRINT("KiInsertQueue(Queue %x, Entry %x)\n", Queue, Entry);
- OldIrql = KeAcquireDispatcherDatabaseLock ();
-
InitialState = Queue->Header.SignalState;
- Queue->Header.SignalState++;
-
+
if (Head)
{
InsertHeadList(&Queue->EntryListHead, Entry);
@@ -87,13 +88,21 @@
{
InsertTailList(&Queue->EntryListHead, Entry);
}
-
- if (Queue->CurrentCount < Queue->MaximumCount && InitialState == 0)
+
+ //inc. num entries in queue
+ Queue->Header.SignalState++;
+
+ /* Why the KeGetCurrentThread()->Queue != Queue?
+ * KiInsertQueue might be called from an APC for the current thread.
+ * -Gunnar
+ */
+ if (Queue->CurrentCount < Queue->MaximumCount &&
+ !IsListEmpty(&Queue->Header.WaitListHead) &&
+ KeGetCurrentThread()->Queue != Queue)
{
- KeDispatcherObjectWake(&Queue->Header);
+ KiDispatcherObjectWake(&Queue->Header);
}
- KeReleaseDispatcherDatabaseLock(OldIrql);
return InitialState;
}
@@ -106,7 +115,14 @@
KeInsertHeadQueue(IN PKQUEUE Queue,
IN PLIST_ENTRY Entry)
{
- return KiInsertQueue(Queue,Entry,TRUE);
+ LONG Result;
+ KIRQL OldIrql;
+
+ OldIrql = KeAcquireDispatcherDatabaseLock();
+ Result = KiInsertQueue(Queue,Entry,TRUE);
+ KeReleaseDispatcherDatabaseLock(OldIrql);
+
+ return Result;
}
@@ -117,7 +133,14 @@
KeInsertQueue(IN PKQUEUE Queue,
IN PLIST_ENTRY Entry)
{
- return KiInsertQueue(Queue,Entry,FALSE);
+ LONG Result;
+ KIRQL OldIrql;
+
+ OldIrql = KeAcquireDispatcherDatabaseLock();
+ Result = KiInsertQueue(Queue,Entry,FALSE);
+ KeReleaseDispatcherDatabaseLock(OldIrql);
+
+ return Result;
}
@@ -129,6 +152,7 @@
IN KPROCESSOR_MODE WaitMode,
IN PLARGE_INTEGER Timeout OPTIONAL)
{
+
PLIST_ENTRY ListEntry;
NTSTATUS Status;
PKTHREAD Thread = KeGetCurrentThread();
@@ -136,50 +160,75 @@
OldIrql = KeAcquireDispatcherDatabaseLock ();
- //assiciate new thread with queue?
if (Thread->Queue != Queue)
{
- //remove association from other queue
- if (!IsListEmpty(&Thread->QueueListEntry))
+ /*
+ * INVESTIGATE: What is the Thread->QueueListEntry used for? It's linked it into the
+ * Queue->ThreadListHead when the thread registers with the queue and unlinked when
+ * the thread registers with a new queue. The Thread->Queue already tells us what
+ * queue the thread is registered with.
+ * -Gunnar
+ */
+
+ //unregister thread from previous queue (if any)
+ if (Thread->Queue)
{
RemoveEntryList(&Thread->QueueListEntry);
+ Thread->Queue->CurrentCount--;
+
+ if (Thread->Queue->CurrentCount < Thread->Queue->MaximumCount &&
+ !IsListEmpty(&Thread->Queue->EntryListHead))
+ {
+ KiDispatcherObjectWake(&Thread->Queue->Header);
+ }
}
- //associate with this queue
- InsertHeadList(&Queue->ThreadListHead, &Thread->QueueListEntry);
- Queue->CurrentCount++;
+ // register thread with this queue
+ InsertTailList(&Queue->ThreadListHead, &Thread->QueueListEntry);
Thread->Queue = Queue;
}
-
- if (Queue->CurrentCount <= Queue->MaximumCount && !IsListEmpty(&Queue->EntryListHead))
+ else /* if (Thread->Queue == Queue) */
{
- ListEntry = RemoveHeadList(&Queue->EntryListHead);
- Queue->Header.SignalState--;
- KeReleaseDispatcherDatabaseLock (OldIrql);
- return ListEntry;
+ //dec. num running threads
+ Queue->CurrentCount--;
}
-
- //need to wait for it...
- KeReleaseDispatcherDatabaseLock (OldIrql);
-
- Status = KeWaitForSingleObject(Queue,
- WrQueue,
- WaitMode,
- TRUE,//Alertable,
- Timeout);
-
- if (Status == STATUS_TIMEOUT || Status == STATUS_USER_APC)
- {
- return (PVOID)Status;
- }
- else
+
+
+
+
+ while (TRUE)
{
- OldIrql = KeAcquireDispatcherDatabaseLock ();
- ListEntry = RemoveHeadList(&Queue->EntryListHead);
- KeReleaseDispatcherDatabaseLock (OldIrql);
- return ListEntry;
+ if (Queue->CurrentCount < Queue->MaximumCount && !IsListEmpty(&Queue->EntryListHead))
+ {
+ ListEntry = RemoveHeadList(&Queue->EntryListHead);
+ //dec. num entries in queue
+ Queue->Header.SignalState--;
+ //inc. num running threads
+ Queue->CurrentCount++;
+
+ KeReleaseDispatcherDatabaseLock(OldIrql);
+ return ListEntry;
+ }
+ else
+ {
+ //inform KeWaitXxx that we are holding disp. lock
+ Thread->WaitNext = TRUE;
+ Thread->WaitIrql = OldIrql;
+
+ Status = KeWaitForSingleObject(Queue,
+ WrQueue,
+ WaitMode,
+ TRUE, //bAlertable
+ Timeout);
+
+ if (Status == STATUS_TIMEOUT || Status == STATUS_USER_APC)
+ {
+ return (PVOID)Status;
+ }
+
+ OldIrql = KeAcquireDispatcherDatabaseLock ();
+ }
}
-
}
@@ -195,23 +244,31 @@
DPRINT("KeRundownQueue(Queue %x)\n", Queue);
- //FIXME: should we wake thread waiting on a queue?
-
+ /* I'm just guessing how this should work:-/
+ * -Gunnar
+ */
+
OldIrql = KeAcquireDispatcherDatabaseLock ();
- // Clear Queue and QueueListEntry members of all threads associated with this queue
+ //no thread must wait on queue at rundown
+ ASSERT(IsListEmpty(&Queue->Header.WaitListHead));
+
+ // unlink threads and clear their Thread->Queue
while (!IsListEmpty(&Queue->ThreadListHead))
{
EnumEntry = RemoveHeadList(&Queue->ThreadListHead);
- InitializeListHead(EnumEntry);
Thread = CONTAINING_RECORD(EnumEntry, KTHREAD, QueueListEntry);
Thread->Queue = NULL;
}
- if (!IsListEmpty(&Queue->EntryListHead))
- EnumEntry = Queue->EntryListHead.Flink;
- else
+ if (IsListEmpty(&Queue->EntryListHead))
+ {
EnumEntry = NULL;
+ }
+ else
+ {
+ EnumEntry = Queue->EntryListHead.Flink;
+ }
KeReleaseDispatcherDatabaseLock (OldIrql);
reactos/ntoskrnl/ke
diff -u -r1.15 -r1.16
--- sem.c 15 Aug 2004 16:39:05 -0000 1.15
+++ sem.c 21 Nov 2004 18:33:54 -0000 1.16
@@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-/* $Id: sem.c,v 1.15 2004/08/15 16:39:05 chorns Exp $
+/* $Id: sem.c,v 1.16 2004/11/21 18:33:54 gdalsnes Exp $
*
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ke/sem.c
@@ -105,7 +105,7 @@
Semaphore->Header.SignalState += Adjustment;
if (InitialState == 0)
{
- KeDispatcherObjectWake(&Semaphore->Header);
+ KiDispatcherObjectWake(&Semaphore->Header);
}
if (Wait == FALSE)
reactos/ntoskrnl/ke
diff -u -r1.89 -r1.90
--- timer.c 21 Nov 2004 06:51:18 -0000 1.89
+++ timer.c 21 Nov 2004 18:33:54 -0000 1.90
@@ -1,4 +1,4 @@
-/* $Id: timer.c,v 1.89 2004/11/21 06:51:18 ion Exp $
+/* $Id: timer.c,v 1.90 2004/11/21 18:33:54 gdalsnes Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@@ -526,11 +526,11 @@
DPRINT("Finished dpc routine\n");
}
- ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
+ ASSERT_IRQL_EQUAL(DISPATCH_LEVEL);
KeAcquireDispatcherDatabaseLockAtDpcLevel();
Timer->Header.SignalState = TRUE;
- KeDispatcherObjectWake(&Timer->Header);
+ KiDispatcherObjectWake(&Timer->Header);
KeReleaseDispatcherDatabaseLockFromDpcLevel();
if (Timer->Period != 0)
@@ -571,7 +571,7 @@
DPRINT("KeExpireTimers()\n");
- ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
+ ASSERT_IRQL_EQUAL(DISPATCH_LEVEL);
InitializeListHead(&TimerList);
reactos/ntoskrnl/ke
diff -u -r1.61 -r1.62
--- wait.c 11 Nov 2004 22:23:52 -0000 1.61
+++ wait.c 21 Nov 2004 18:33:54 -0000 1.62
@@ -110,6 +110,8 @@
break;
case InternalQueueType:
+ break;
+
case InternalSemaphoreType:
hdr->SignalState--;
break;
@@ -193,33 +195,31 @@
}
}
-VOID KeRemoveAllWaitsThread(PETHREAD Thread, NTSTATUS WaitStatus, BOOL Unblock)
+/* Must be called with the dispatcher lock held */
+BOOLEAN KiAbortWaitThread(PKTHREAD Thread, NTSTATUS WaitStatus)
{
- PKWAIT_BLOCK WaitBlock, PrevWaitBlock;
- BOOLEAN WasWaiting = FALSE;
+ PKWAIT_BLOCK WaitBlock;
+ BOOLEAN WasWaiting;
- WaitBlock = (PKWAIT_BLOCK)Thread->Tcb.WaitBlockList;
- if (WaitBlock != NULL)
- {
- WasWaiting = TRUE;
- }
- while (WaitBlock != NULL)
- {
- if (WaitBlock->WaitListEntry.Flink != NULL && WaitBlock->WaitListEntry.Blink != NULL)
- {
- RemoveEntryList (&WaitBlock->WaitListEntry);
- WaitBlock->WaitListEntry.Flink = WaitBlock->WaitListEntry.Blink = NULL;
- }
- PrevWaitBlock = WaitBlock;
- WaitBlock = WaitBlock->NextWaitBlock;
- PrevWaitBlock->NextWaitBlock = NULL;
- }
- Thread->Tcb.WaitBlockList = NULL;
+ /* if we are blocked, we must be waiting on something also */
+ ASSERT((Thread->State == THREAD_STATE_BLOCKED) == (Thread->WaitBlockList != NULL));
- if (WasWaiting && Unblock)
- {
- PsUnblockThread(Thread, &WaitStatus);
- }
+ WaitBlock = (PKWAIT_BLOCK)Thread->WaitBlockList;
+ WasWaiting = (WaitBlock != NULL);
+
+ while (WaitBlock)
+ {
+ RemoveEntryList(&WaitBlock->WaitListEntry);
+ WaitBlock = WaitBlock->NextWaitBlock;
+ }
+
+ Thread->WaitBlockList = NULL;
+
+ if (WasWaiting)
+ {
+ PsUnblockThread((PETHREAD)Thread, &WaitStatus);
+ }
+ return WasWaiting;
}
static BOOLEAN
@@ -260,11 +260,7 @@
DPRINT("WaitAny: Remove all wait blocks.\n");
for (Waiter = WaiterHead->Thread->WaitBlockList; Waiter; Waiter = Waiter->NextWaitBlock)
{
- if (Waiter->WaitListEntry.Flink != NULL && Waiter->WaitListEntry.Blink != NULL)
- {
- RemoveEntryList(&Waiter->WaitListEntry);
- Waiter->WaitListEntry.Flink = Waiter->WaitListEntry.Blink = NULL;
- }
+ RemoveEntryList(&Waiter->WaitListEntry);
}
WaiterHead->Thread->WaitBlockList = NULL;
@@ -273,7 +269,7 @@
* If a WakeAll KiSideEffectsBeforeWake(hdr,.. will be called several times,
* but thats ok since WakeAll objects has no sideeffects.
*/
- Abandoned = KiSideEffectsBeforeWake(hdr, WaiterHead->Thread) ? TRUE : Abandoned;
+ Abandoned |= KiSideEffectsBeforeWake(hdr, WaiterHead->Thread);
}
else
{
@@ -299,16 +295,11 @@
{
for (Waiter = WaiterHead->Thread->WaitBlockList; Waiter; Waiter = Waiter->NextWaitBlock)
{
- if (Waiter->WaitListEntry.Flink != NULL && Waiter->WaitListEntry.Blink != NULL)
- {
- RemoveEntryList(&Waiter->WaitListEntry);
- Waiter->WaitListEntry.Flink = Waiter->WaitListEntry.Blink = NULL;
- }
+ RemoveEntryList(&Waiter->WaitListEntry);
if (Waiter->WaitType == WaitAll)
{
- Abandoned = KiSideEffectsBeforeWake(Waiter->Object, Waiter->Thread)
- ? TRUE : Abandoned;
+ Abandoned |= KiSideEffectsBeforeWake(Waiter->Object, Waiter->Thread);
}
//no WaitAny objects can possibly be signaled since we are here
@@ -339,7 +330,7 @@
}
-BOOLEAN KeDispatcherObjectWake(DISPATCHER_HEADER* hdr)
+BOOLEAN KiDispatcherObjectWake(DISPATCHER_HEADER* hdr)
/*
* FUNCTION: Wake threads waiting on a dispatcher object
* NOTE: The exact semantics of waking are dependant on the type of object
@@ -366,6 +357,8 @@
return(KeDispatcherObjectWakeOne(hdr));
case InternalQueueType:
+ return(KeDispatcherObjectWakeOne(hdr));
+
case InternalSemaphoreType:
DPRINT("hdr->SignalState %d\n", hdr->SignalState);
if(hdr->SignalState>0)
@@ -483,7 +476,6 @@
ULONG CountSignaled;
ULONG i;
NTSTATUS Status;
- KIRQL WaitIrql;
KIRQL OldIrql;
BOOLEAN Abandoned;
@@ -493,7 +485,6 @@
ASSERT(0 < Count && Count <= EX_MAXIMUM_WAIT_OBJECTS);
CurrentThread = KeGetCurrentThread();
- WaitIrql = KeGetCurrentIrql();
/*
* Work out where we are going to put the wait blocks
@@ -516,6 +507,8 @@
}
}
+
+
/*
* Set up the timeout if required
*/
@@ -528,9 +521,8 @@
{
if (CurrentThread->WaitNext)
{
+ CurrentThread->WaitNext = FALSE;
OldIrql = CurrentThread->WaitIrql;
- CurrentThread->WaitNext = 0;
- CurrentThread->WaitIrql = PASSIVE_LEVEL;
}
else
{
@@ -711,28 +703,33 @@
&CurrentThread->WaitBlock[3].WaitListEntry);
}
- //io completion
- if (CurrentThread->Queue)
+ //kernel queues
+ if (CurrentThread->Queue && WaitReason != WrQueue)
{
- CurrentThread->Queue->CurrentCount--;
- if (WaitReason != WrQueue && CurrentThread->Queue->CurrentCount < CurrentThread->Queue->MaximumCount &&
+ DPRINT("queue: sleep on something else\n");
+ CurrentThread->Queue->CurrentCount--;
+
+ //wake another thread
+ if (CurrentThread->Queue->CurrentCount < CurrentThread->Queue->MaximumCount &&
!IsListEmpty(&CurrentThread->Queue->EntryListHead))
{
- KeDispatcherObjectWake(&CurrentThread->Queue->Header);
+ KiDispatcherObjectWake(&CurrentThread->Queue->Header);
}
}
- PsBlockThread(&Status, Alertable, WaitMode, TRUE, WaitIrql, (UCHAR)WaitReason);
+ PsBlockThread(&Status, Alertable, WaitMode, TRUE, OldIrql, (UCHAR)WaitReason);
- //io completion
- if (CurrentThread->Queue)
+ //kernel queues
+ //FIXME: dispatcher lock not held here!
+ if (CurrentThread->Queue && WaitReason != WrQueue)
{
+ DPRINT("queue: wake from something else\n");
CurrentThread->Queue->CurrentCount++;
}
-
-
- }
- while (Status == STATUS_KERNEL_APC);
+
+
+ } while (Status == STATUS_KERNEL_APC);
+
if (Timeout != NULL)
{
CVSspam 0.2.8