Fix APC problems. Thanks to Arty for finding this. This makes vncviewer work Modified: trunk/reactos/ntoskrnl/ke/wait.c _____
Modified: trunk/reactos/ntoskrnl/ke/wait.c --- trunk/reactos/ntoskrnl/ke/wait.c 2005-02-10 03:58:03 UTC (rev 13483) +++ trunk/reactos/ntoskrnl/ke/wait.c 2005-02-10 05:13:43 UTC (rev 13484) @@ -1,4 +1,4 @@
-/* $Id:$ +/* $Id$ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS project @@ -489,6 +489,7 @@ NTSTATUS Status; KIRQL OldIrql; BOOLEAN Abandoned; + NTSTATUS WaitStatus;
DPRINT("Entering KeWaitForMultipleObjects(Count %lu Object[] %p) " "PsGetCurrentThread() %x\n", Count, Object, PsGetCurrentThread()); @@ -540,40 +541,32 @@ OldIrql = KeAcquireDispatcherDatabaseLock (); }
- /* Alertability 101 - * ---------------- - * A Wait can either be Alertable, or Non-Alertable. - * An Alertable Wait means that APCs can "Wake" the Thread, also called UnWaiting - * If an APC is Pending however, we must refuse an Alertable Wait. Such a wait would - * be pointless since an APC is just about to be delivered. - * - * There are many ways to check if it's safe to be alertable, and these are the ones - * that I could think of: - * - The Thread is already Alerted. So someone beat us to the punch and we bail out. - * - The Thread is Waiting in User-Mode, the APC Queue is not-empty. - * It's defintely clear that we have incoming APCs, so we need to bail out and let the system - * know that there are Pending User APCs (so they can be Delivered and maybe we can try again) - * - * Furthermore, wether or not we want to be Alertable, if the Thread is waiting in User-Mode, and there - * are Pending User APCs, we should bail out, since APCs will be delivered any second. - */ - if (Alertable) { - if (CurrentThread->Alerted[(int)WaitMode]) { - CurrentThread->Alerted[(int)WaitMode] = FALSE; - DPRINT("Alertability failed\n"); - KeReleaseDispatcherDatabaseLock(OldIrql); - return (STATUS_ALERTED); - } else if ((!IsListEmpty(&CurrentThread->ApcState.ApcListHead[UserMode])) && (WaitMode == UserMode)) { - DPRINT1("Alertability failed\n"); - CurrentThread->ApcState.UserApcPending = TRUE; - KeReleaseDispatcherDatabaseLock(OldIrql); - return (STATUS_USER_APC); - } - } else if ((CurrentThread->ApcState.UserApcPending) && (WaitMode != KernelMode)) { - DPRINT1("Alertability failed\n"); - KeReleaseDispatcherDatabaseLock(OldIrql); - return (STATUS_USER_APC); - } + /* Get the current Wait Status */ + WaitStatus = CurrentThread->WaitStatus; + + if (Alertable) { + + /* If the Thread is Alerted, set the Wait Status accordingly */ + if (CurrentThread->Alerted[(int)WaitMode]) { + + CurrentThread->Alerted[(int)WaitMode] = FALSE; + DPRINT("Thread was Alerted\n"); + WaitStatus = STATUS_ALERTED; + + /* If there are User APCs Pending, then we can't really be alertable */ + } else if ((!IsListEmpty(&CurrentThread->ApcState.ApcListHead[UserMode])) && + (WaitMode == UserMode)) { + + DPRINT1("APCs are Pending\n"); + CurrentThread->ApcState.UserApcPending = TRUE; + WaitStatus = STATUS_USER_APC; + } + + /* If there are User APCs Pending and we are waiting in usermode, then we must notify the caller */ + } else if ((CurrentThread->ApcState.UserApcPending) && (WaitMode == UserMode)) { + DPRINT1("APCs are Pending\n"); + WaitStatus = STATUS_USER_APC; + }
/* * Check if the wait is (already) satisfied @@ -659,7 +652,7 @@ /* * Set up the wait */ - CurrentThread->WaitStatus = STATUS_UNSUCCESSFUL; + CurrentThread->WaitStatus = WaitStatus;;
for (i = 0; i < Count; i++) {