Fix APC problems. Thanks to Arty for finding this. This makes vncviewer work

svn path=/trunk/; revision=13484
This commit is contained in:
Alex Ionescu 2005-02-10 05:13:43 +00:00
parent 73f1d215e0
commit ef53ccc2a8

View file

@ -1,4 +1,4 @@
/* $Id:$ /* $Id$
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS project * PROJECT: ReactOS project
@ -489,6 +489,7 @@ KeWaitForMultipleObjects(ULONG Count,
NTSTATUS Status; NTSTATUS Status;
KIRQL OldIrql; KIRQL OldIrql;
BOOLEAN Abandoned; BOOLEAN Abandoned;
NTSTATUS WaitStatus;
DPRINT("Entering KeWaitForMultipleObjects(Count %lu Object[] %p) " DPRINT("Entering KeWaitForMultipleObjects(Count %lu Object[] %p) "
"PsGetCurrentThread() %x\n", Count, Object, PsGetCurrentThread()); "PsGetCurrentThread() %x\n", Count, Object, PsGetCurrentThread());
@ -540,40 +541,32 @@ KeWaitForMultipleObjects(ULONG Count,
OldIrql = KeAcquireDispatcherDatabaseLock (); OldIrql = KeAcquireDispatcherDatabaseLock ();
} }
/* Alertability 101 /* Get the current Wait Status */
* ---------------- WaitStatus = CurrentThread->WaitStatus;
* A Wait can either be Alertable, or Non-Alertable.
* An Alertable Wait means that APCs can "Wake" the Thread, also called UnWaiting if (Alertable) {
* 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. /* If the Thread is Alerted, set the Wait Status accordingly */
* if (CurrentThread->Alerted[(int)WaitMode]) {
* There are many ways to check if it's safe to be alertable, and these are the ones
* that I could think of: CurrentThread->Alerted[(int)WaitMode] = FALSE;
* - The Thread is already Alerted. So someone beat us to the punch and we bail out. DPRINT("Thread was Alerted\n");
* - The Thread is Waiting in User-Mode, the APC Queue is not-empty. WaitStatus = STATUS_ALERTED;
* 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) /* If there are User APCs Pending, then we can't really be alertable */
* } else if ((!IsListEmpty(&CurrentThread->ApcState.ApcListHead[UserMode])) &&
* Furthermore, wether or not we want to be Alertable, if the Thread is waiting in User-Mode, and there (WaitMode == UserMode)) {
* are Pending User APCs, we should bail out, since APCs will be delivered any second.
*/ DPRINT1("APCs are Pending\n");
if (Alertable) { CurrentThread->ApcState.UserApcPending = TRUE;
if (CurrentThread->Alerted[(int)WaitMode]) { WaitStatus = STATUS_USER_APC;
CurrentThread->Alerted[(int)WaitMode] = FALSE; }
DPRINT("Alertability failed\n");
KeReleaseDispatcherDatabaseLock(OldIrql); /* If there are User APCs Pending and we are waiting in usermode, then we must notify the caller */
return (STATUS_ALERTED); } else if ((CurrentThread->ApcState.UserApcPending) && (WaitMode == UserMode)) {
} else if ((!IsListEmpty(&CurrentThread->ApcState.ApcListHead[UserMode])) && (WaitMode == UserMode)) { DPRINT1("APCs are Pending\n");
DPRINT1("Alertability failed\n"); WaitStatus = STATUS_USER_APC;
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);
}
/* /*
* Check if the wait is (already) satisfied * Check if the wait is (already) satisfied
@ -659,7 +652,7 @@ KeWaitForMultipleObjects(ULONG Count,
/* /*
* Set up the wait * Set up the wait
*/ */
CurrentThread->WaitStatus = STATUS_UNSUCCESSFUL; CurrentThread->WaitStatus = WaitStatus;;
for (i = 0; i < Count; i++) for (i = 0; i < Count; i++)
{ {