WaitForMultipleObjects: WaitAll waits were buggy

Many small fixes and cleanups

svn path=/trunk/; revision=4205
This commit is contained in:
Gunnar Dalsnes 2003-02-27 15:38:36 +00:00
parent 3013b90260
commit 5852f3f492

View file

@ -33,6 +33,9 @@ static BOOLEAN WaitSet = FALSE;
static KIRQL oldlvl = PASSIVE_LEVEL; static KIRQL oldlvl = PASSIVE_LEVEL;
static PKTHREAD Owner = NULL; static PKTHREAD Owner = NULL;
#define KeDispatcherObjectWakeOne(hdr) KeDispatcherObjectWakeOneOrAll(hdr, FALSE)
#define KeDispatcherObjectWakeAll(hdr) KeDispatcherObjectWakeOneOrAll(hdr, TRUE)
/* FUNCTIONS *****************************************************************/ /* FUNCTIONS *****************************************************************/
VOID KeInitializeDispatcherHeader(DISPATCHER_HEADER* Header, VOID KeInitializeDispatcherHeader(DISPATCHER_HEADER* Header,
@ -85,16 +88,15 @@ VOID KeReleaseDispatcherDatabaseLock(BOOLEAN Wait)
} }
} }
static VOID KiSideEffectsBeforeWake(DISPATCHER_HEADER* hdr, static BOOLEAN
PKTHREAD Thread, KiSideEffectsBeforeWake(DISPATCHER_HEADER * hdr,
PBOOLEAN Abandoned) PKTHREAD Thread)
/* /*
* FUNCTION: Perform side effects on object before a wait for a thread is * FUNCTION: Perform side effects on object before a wait for a thread is
* satisfied * satisfied
*/ */
{ {
if (Abandoned != NULL) BOOLEAN Abandoned = FALSE;
*Abandoned = FALSE;
switch (hdr->Type) switch (hdr->Type)
{ {
@ -133,14 +135,12 @@ static VOID KiSideEffectsBeforeWake(DISPATCHER_HEADER* hdr,
{ {
if (Thread == NULL) if (Thread == NULL)
{ {
DPRINT1("Thread == NULL!\n"); DPRINT("Thread == NULL!\n");
KeBugCheck(0); KeBugCheck(0);
} }
if (Abandoned != NULL) Abandoned = Mutex->Abandoned;
*Abandoned = Mutex->Abandoned;
if (Thread != NULL) if (Thread != NULL)
InsertTailList(&Thread->MutantListHead, InsertTailList(&Thread->MutantListHead, &Mutex->MutantListEntry);
&Mutex->MutantListEntry);
Mutex->OwnerThread = Thread; Mutex->OwnerThread = Thread;
Mutex->Abandoned = FALSE; Mutex->Abandoned = FALSE;
} }
@ -148,20 +148,17 @@ static VOID KiSideEffectsBeforeWake(DISPATCHER_HEADER* hdr,
break; break;
default: default:
DbgPrint("(%s:%d) Dispatcher object %x has unknown type\n", DbgPrint("(%s:%d) Dispatcher object %x has unknown type\n", __FILE__, __LINE__, hdr);
__FILE__,__LINE__,hdr);
KeBugCheck(0); KeBugCheck(0);
} }
return Abandoned;
} }
static BOOLEAN static BOOLEAN
KiIsObjectSignalled(DISPATCHER_HEADER* hdr, KiIsObjectSignalled(DISPATCHER_HEADER * hdr,
PKTHREAD Thread, PKTHREAD Thread)
PBOOLEAN Abandoned)
{ {
if (Abandoned != NULL)
*Abandoned = FALSE;
if (hdr->Type == InternalMutexType) if (hdr->Type == InternalMutexType)
{ {
PKMUTEX Mutex; PKMUTEX Mutex;
@ -169,29 +166,24 @@ KiIsObjectSignalled(DISPATCHER_HEADER* hdr,
Mutex = CONTAINING_RECORD(hdr, KMUTEX, Header); Mutex = CONTAINING_RECORD(hdr, KMUTEX, Header);
assert(hdr->SignalState <= 1); assert(hdr->SignalState <= 1);
if ((hdr->SignalState < 1 && Mutex->OwnerThread == Thread) ||
hdr->SignalState == 1) if ((hdr->SignalState < 1 && Mutex->OwnerThread == Thread) || hdr->SignalState == 1)
{ {
KiSideEffectsBeforeWake(hdr, return (TRUE);
Thread,
Abandoned);
return(TRUE);
} }
else else
{ {
return(FALSE); return (FALSE);
} }
} }
if (hdr->SignalState <= 0) if (hdr->SignalState <= 0)
{ {
return(FALSE); return (FALSE);
} }
else else
{ {
KiSideEffectsBeforeWake(hdr, return (TRUE);
Thread,
Abandoned);
return(TRUE);
} }
} }
@ -222,155 +214,113 @@ VOID KeRemoveAllWaitsThread(PETHREAD Thread, NTSTATUS WaitStatus)
KeReleaseDispatcherDatabaseLock(FALSE); KeReleaseDispatcherDatabaseLock(FALSE);
} }
static BOOLEAN KeDispatcherObjectWakeAll(DISPATCHER_HEADER* hdr) static BOOLEAN
KeDispatcherObjectWakeOneOrAll(DISPATCHER_HEADER * hdr,
BOOLEAN WakeAll)
{ {
PKWAIT_BLOCK current; PKWAIT_BLOCK Waiter;
PLIST_ENTRY current_entry; PKWAIT_BLOCK WaiterHead;
PKWAIT_BLOCK PrevBlock; PLIST_ENTRY EnumEntry;
NTSTATUS Status; NTSTATUS Status;
BOOLEAN Abandoned; BOOLEAN Abandoned;
BOOLEAN AllSignaled;
BOOLEAN WakedAny = FALSE;
DPRINT("KeDispatcherObjectWakeAll(hdr %x)\n",hdr); DPRINT("KeDispatcherObjectWakeOnOrAll(hdr %x)\n", hdr);
DPRINT ("hdr->WaitListHead.Flink %x hdr->WaitListHead.Blink %x\n",
hdr->WaitListHead.Flink, hdr->WaitListHead.Blink);
if (IsListEmpty(&hdr->WaitListHead)) if (IsListEmpty(&hdr->WaitListHead))
{ {
return(FALSE); return (FALSE);
} }
while (!IsListEmpty(&hdr->WaitListHead)) //enum waiters for this dispatcher object
EnumEntry = hdr->WaitListHead.Flink;
while (EnumEntry != &hdr->WaitListHead && (WakeAll || !WakedAny))
{ {
current_entry = RemoveHeadList(&hdr->WaitListHead); WaiterHead = CONTAINING_RECORD(EnumEntry, KWAIT_BLOCK, WaitListEntry);
current = CONTAINING_RECORD(current_entry, DPRINT("current_entry %x current %x\n", EnumEntry, WaiterHead);
KWAIT_BLOCK, EnumEntry = EnumEntry->Flink;
WaitListEntry); assert(WaiterHead->Thread->WaitBlockList != NULL);
DPRINT("Waking %x\n",current->Thread);
if (current->WaitType == WaitAny) Abandoned = FALSE;
if (WaiterHead->WaitType == WaitAny)
{ {
DPRINT("WaitAny: Remove all wait blocks.\n"); DPRINT("WaitAny: Remove all wait blocks.\n");
for(PrevBlock = current->Thread->WaitBlockList; PrevBlock; for (Waiter = WaiterHead->Thread->WaitBlockList; Waiter; Waiter = Waiter->NextWaitBlock)
PrevBlock = PrevBlock->NextWaitBlock)
{ {
if (PrevBlock != current) RemoveEntryList(&Waiter->WaitListEntry);
RemoveEntryList(&PrevBlock->WaitListEntry);
} }
current->Thread->WaitBlockList = 0;
}
else
{
DPRINT("WaitAll: Remove the current wait block only.\n");
PrevBlock = current->Thread->WaitBlockList; WaiterHead->Thread->WaitBlockList = NULL;
if (PrevBlock == current)
{ /*
DPRINT( "WaitAll: Current block is list head.\n" ); * If a WakeAll KiSideEffectsBeforeWake(hdr,.. will be called several times,
current->Thread->WaitBlockList = current->NextWaitBlock; * but thats ok since WakeAll objects has no sideeffects.
*/
Abandoned = KiSideEffectsBeforeWake(hdr, WaiterHead->Thread) ? TRUE : Abandoned;
} }
else else
{ {
DPRINT( "WaitAll: Current block is not list head.\n" ); DPRINT("WaitAll: All WaitAll objects must be signaled.\n");
while (PrevBlock && PrevBlock->NextWaitBlock != current)
AllSignaled = TRUE;
//all WaitAll obj. for thread need to be signaled to satisfy a wake
for (Waiter = WaiterHead->Thread->WaitBlockList; Waiter; Waiter = Waiter->NextWaitBlock)
{ {
PrevBlock = PrevBlock->NextWaitBlock; //no need to check hdr since it has to be signaled
} if (Waiter->WaitType == WaitAll && Waiter->Object != hdr)
if (PrevBlock)
{ {
PrevBlock->NextWaitBlock = current->NextWaitBlock; if (!KiIsObjectSignalled(Waiter->Object, Waiter->Thread))
}
current->NextWaitBlock = NULL;
/* if the last block is the timeout block then remove this block */
PrevBlock = current->Thread->WaitBlockList;
if (PrevBlock == &current->Thread->WaitBlock[3] && PrevBlock->NextWaitBlock == NULL)
{ {
RemoveEntryList(&current->Thread->WaitBlock[3].WaitListEntry); AllSignaled = FALSE;
current->Thread->WaitBlockList = NULL; break;
} }
} }
} }
KiSideEffectsBeforeWake(hdr, current->Thread, &Abandoned);
Status = current->WaitKey; if (AllSignaled)
{
for (Waiter = WaiterHead->Thread->WaitBlockList; Waiter; Waiter = Waiter->NextWaitBlock)
{
RemoveEntryList(&Waiter->WaitListEntry);
if (Waiter->WaitType == WaitAll)
{
Abandoned = KiSideEffectsBeforeWake(Waiter->Object, Waiter->Thread)
? TRUE : Abandoned;
}
//no WaitAny objects can possibly be signaled since we are here
assert(!(Waiter->WaitType == WaitAny
&& KiIsObjectSignalled(Waiter->Object, Waiter->Thread)));
}
WaiterHead->Thread->WaitBlockList = NULL;
}
}
if (WaiterHead->Thread->WaitBlockList == NULL)
{
Status = WaiterHead->WaitKey;
if (Abandoned) if (Abandoned)
Status += STATUS_ABANDONED_WAIT_0;
if (current->Thread->WaitBlockList == NULL)
{ {
PsUnblockThread(CONTAINING_RECORD(current->Thread,ETHREAD,Tcb), DPRINT("Abandoned mutex among objects");
&Status); Status += STATUS_ABANDONED_WAIT_0;
}
WakedAny = TRUE;
DPRINT("Waking %x status = %x\n", WaiterHead->Thread, Status);
PsUnblockThread(CONTAINING_RECORD(WaiterHead->Thread, ETHREAD, Tcb), &Status);
} }
} }
return(TRUE);
return WakedAny;
} }
static BOOLEAN KeDispatcherObjectWakeOne(DISPATCHER_HEADER* hdr)
{
PKWAIT_BLOCK current;
PLIST_ENTRY current_entry;
PKWAIT_BLOCK PrevBlock;
NTSTATUS Status;
BOOLEAN Abandoned;
DPRINT("KeDispatcherObjectWakeOn(hdr %x)\n",hdr);
DPRINT("hdr->WaitListHead.Flink %x hdr->WaitListHead.Blink %x\n",
hdr->WaitListHead.Flink,hdr->WaitListHead.Blink);
if (IsListEmpty(&(hdr->WaitListHead)))
{
return(FALSE);
}
current_entry = RemoveHeadList(&(hdr->WaitListHead));
current = CONTAINING_RECORD(current_entry,KWAIT_BLOCK,
WaitListEntry);
DPRINT("current_entry %x current %x\n",current_entry,current);
if (current->WaitType == WaitAny)
{
DPRINT("WaitAny: Remove all wait blocks.\n");
for( PrevBlock = current->Thread->WaitBlockList; PrevBlock; PrevBlock = PrevBlock->NextWaitBlock )
if( PrevBlock != current )
RemoveEntryList( &(PrevBlock->WaitListEntry) );
current->Thread->WaitBlockList = 0;
}
else
{
DPRINT("WaitAll: Remove the current wait block only.\n");
PrevBlock = current->Thread->WaitBlockList;
if (PrevBlock == current)
{
DPRINT( "WaitAll: Current block is list head.\n" );
current->Thread->WaitBlockList = current->NextWaitBlock;
}
else
{
DPRINT( "WaitAll: Current block is not list head.\n" );
while ( PrevBlock && PrevBlock->NextWaitBlock != current)
{
PrevBlock = PrevBlock->NextWaitBlock;
}
if (PrevBlock)
{
PrevBlock->NextWaitBlock = current->NextWaitBlock;
}
}
current->NextWaitBlock = NULL;
/* if the last block is the timeout block then remove this block */
PrevBlock = current->Thread->WaitBlockList;
if (PrevBlock == &current->Thread->WaitBlock[3] && PrevBlock->NextWaitBlock == NULL)
{
RemoveEntryList(&current->Thread->WaitBlock[3].WaitListEntry);
current->Thread->WaitBlockList = NULL;
}
}
DPRINT("Waking %x\n",current->Thread);
KiSideEffectsBeforeWake(hdr, current->Thread, &Abandoned);
Status = current->WaitKey;
if (Abandoned)
Status += STATUS_ABANDONED_WAIT_0;
if (current->Thread->WaitBlockList == NULL)
{
PsUnblockThread(CONTAINING_RECORD(current->Thread,ETHREAD,Tcb),
&Status);
}
return(TRUE);
}
BOOLEAN KeDispatcherObjectWake(DISPATCHER_HEADER* hdr) BOOLEAN KeDispatcherObjectWake(DISPATCHER_HEADER* hdr)
/* /*
@ -446,103 +396,14 @@ KeWaitForSingleObject(PVOID Object,
* RETURNS: Status * RETURNS: Status
*/ */
{ {
DISPATCHER_HEADER* hdr = (DISPATCHER_HEADER *)Object; return KeWaitForMultipleObjects(1,
PKTHREAD CurrentThread; &Object,
NTSTATUS Status; WaitAny,
KIRQL WaitIrql; WaitReason,
BOOLEAN Abandoned; WaitMode,
Alertable,
CurrentThread = KeGetCurrentThread(); Timeout,
WaitIrql = KeGetCurrentIrql(); NULL);
/*
* Set up the timeout
* FIXME: Check for zero timeout
*/
if (Timeout != NULL)
{
KeInitializeTimer(&CurrentThread->Timer);
KeSetTimer(&CurrentThread->Timer, *Timeout, NULL);
}
do
{
KeAcquireDispatcherDatabaseLock(FALSE);
/*
* If we are going to wait alertably and a user apc is pending
* then return
*/
if (Alertable && KiTestAlert())
{
KeReleaseDispatcherDatabaseLock(FALSE);
return(STATUS_USER_APC);
}
/*
* If the object is signalled
*/
if (KiIsObjectSignalled(hdr, CurrentThread, &Abandoned))
{
if (Timeout != NULL)
{
KeCancelTimer(&CurrentThread->Timer);
}
KeReleaseDispatcherDatabaseLock(FALSE);
if (Abandoned == TRUE)
return(STATUS_ABANDONED_WAIT_0);
return(STATUS_WAIT_0);
}
/*
* Check if we have already timed out
*/
if (Timeout != NULL &&
KiIsObjectSignalled(&CurrentThread->Timer.Header, CurrentThread, NULL))
{
KeCancelTimer(&CurrentThread->Timer);
KeReleaseDispatcherDatabaseLock(FALSE);
return(STATUS_TIMEOUT);
}
/*
* Set up for a wait
*/
CurrentThread->WaitStatus = STATUS_UNSUCCESSFUL;
/* Append wait block to the KTHREAD wait block list */
CurrentThread->WaitBlockList = &CurrentThread->WaitBlock[0];
CurrentThread->WaitBlock[0].Object = Object;
CurrentThread->WaitBlock[0].Thread = CurrentThread;
CurrentThread->WaitBlock[0].WaitKey = STATUS_WAIT_0;
CurrentThread->WaitBlock[0].WaitType = WaitAny;
InsertTailList(&hdr->WaitListHead,
&CurrentThread->WaitBlock[0].WaitListEntry);
if (Timeout != NULL)
{
CurrentThread->WaitBlock[0].NextWaitBlock =
&CurrentThread->WaitBlock[3];
CurrentThread->WaitBlock[3].Object = (PVOID)&CurrentThread->Timer;
CurrentThread->WaitBlock[3].Thread = CurrentThread;
CurrentThread->WaitBlock[3].WaitKey = STATUS_TIMEOUT;
CurrentThread->WaitBlock[3].WaitType = WaitAny;
CurrentThread->WaitBlock[3].NextWaitBlock = NULL;
InsertTailList(&CurrentThread->Timer.Header.WaitListHead,
&CurrentThread->WaitBlock[3].WaitListEntry);
}
else
{
CurrentThread->WaitBlock[0].NextWaitBlock = NULL;
}
PsBlockThread(&Status, (UCHAR)Alertable, WaitMode, TRUE, WaitIrql);
} while (Status == STATUS_KERNEL_APC);
if (Timeout != NULL)
{
KeCancelTimer(&CurrentThread->Timer);
}
DPRINT("Returning from KeWaitForSingleObject()\n");
return(Status);
} }
@ -556,7 +417,7 @@ KeWaitForMultipleObjects(ULONG Count,
PLARGE_INTEGER Timeout, PLARGE_INTEGER Timeout,
PKWAIT_BLOCK WaitBlockArray) PKWAIT_BLOCK WaitBlockArray)
{ {
DISPATCHER_HEADER* hdr; DISPATCHER_HEADER *hdr;
PKWAIT_BLOCK blk; PKWAIT_BLOCK blk;
PKTHREAD CurrentThread; PKTHREAD CurrentThread;
ULONG CountSignaled; ULONG CountSignaled;
@ -566,9 +427,8 @@ KeWaitForMultipleObjects(ULONG Count,
BOOLEAN Abandoned; BOOLEAN Abandoned;
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());
CountSignaled = 0;
CurrentThread = KeGetCurrentThread(); CurrentThread = KeGetCurrentThread();
WaitIrql = KeGetCurrentIrql(); WaitIrql = KeGetCurrentIrql();
@ -579,9 +439,8 @@ KeWaitForMultipleObjects(ULONG Count,
{ {
if (Count > THREAD_WAIT_OBJECTS) if (Count > THREAD_WAIT_OBJECTS)
{ {
DbgPrint("(%s:%d) Too many objects!\n", DPRINT("(%s:%d) Too many objects!\n", __FILE__, __LINE__);
__FILE__,__LINE__); return (STATUS_UNSUCCESSFUL);
return(STATUS_UNSUCCESSFUL);
} }
WaitBlockArray = &CurrentThread->WaitBlock[0]; WaitBlockArray = &CurrentThread->WaitBlock[0];
} }
@ -589,16 +448,15 @@ KeWaitForMultipleObjects(ULONG Count,
{ {
if (Count > EX_MAXIMUM_WAIT_OBJECTS) if (Count > EX_MAXIMUM_WAIT_OBJECTS)
{ {
DbgPrint("(%s:%d) Too many objects!\n", DPRINT("(%s:%d) Too many objects!\n", __FILE__, __LINE__);
__FILE__,__LINE__); return (STATUS_UNSUCCESSFUL);
return(STATUS_UNSUCCESSFUL);
} }
} }
/* /*
* Set up the timeout if required * Set up the timeout if required
*/ */
if (Timeout != NULL) if (Timeout != NULL && Timeout->QuadPart != 0)
{ {
KeInitializeTimer(&CurrentThread->Timer); KeInitializeTimer(&CurrentThread->Timer);
KeSetTimer(&CurrentThread->Timer, *Timeout, NULL); KeSetTimer(&CurrentThread->Timer, *Timeout, NULL);
@ -615,55 +473,85 @@ KeWaitForMultipleObjects(ULONG Count,
if (Alertable && KiTestAlert()) if (Alertable && KiTestAlert())
{ {
KeReleaseDispatcherDatabaseLock(FALSE); KeReleaseDispatcherDatabaseLock(FALSE);
return(STATUS_USER_APC); return (STATUS_USER_APC);
} }
/* /*
* Check if the wait is already satisfied * Check if the wait is (already) satisfied
*/ */
CountSignaled = 0;
Abandoned = FALSE;
for (i = 0; i < Count; i++) for (i = 0; i < Count; i++)
{ {
hdr = (DISPATCHER_HEADER *)Object[i]; hdr = (DISPATCHER_HEADER *) Object[i];
if (KiIsObjectSignalled(hdr, CurrentThread, &Abandoned)) if (KiIsObjectSignalled(hdr, CurrentThread))
{ {
CountSignaled++; CountSignaled++;
if (WaitType == WaitAny) if (WaitType == WaitAny)
{ {
if (Timeout != NULL) Abandoned = KiSideEffectsBeforeWake(hdr, CurrentThread) ? TRUE : Abandoned;
if (Timeout != NULL && Timeout->QuadPart != 0)
{ {
KeCancelTimer(&CurrentThread->Timer); KeCancelTimer(&CurrentThread->Timer);
} }
KeReleaseDispatcherDatabaseLock(FALSE); KeReleaseDispatcherDatabaseLock(FALSE);
DPRINT("One object is already signaled!\n");
DPRINT("One object is (already) signaled!\n");
if (Abandoned == TRUE) if (Abandoned == TRUE)
return(STATUS_ABANDONED_WAIT_0 + i); {
return(STATUS_WAIT_0 + i); return (STATUS_ABANDONED_WAIT_0 + i);
}
return (STATUS_WAIT_0 + i);
} }
} }
} }
Abandoned = FALSE;
if ((WaitType == WaitAll) && (CountSignaled == Count)) if ((WaitType == WaitAll) && (CountSignaled == Count))
{ {
if (Timeout != NULL) for (i = 0; i < Count; i++)
{
hdr = (DISPATCHER_HEADER *) Object[i];
Abandoned = KiSideEffectsBeforeWake(hdr, CurrentThread) ? TRUE : Abandoned;
}
if (Timeout != NULL && Timeout->QuadPart != 0)
{ {
KeCancelTimer(&CurrentThread->Timer); KeCancelTimer(&CurrentThread->Timer);
} }
KeReleaseDispatcherDatabaseLock(FALSE); KeReleaseDispatcherDatabaseLock(FALSE);
DPRINT("All objects are already signaled!\n"); DPRINT("All objects are (already) signaled!\n");
return(STATUS_WAIT_0);
if (Abandoned == TRUE)
{
return (STATUS_ABANDONED_WAIT_0);
}
return (STATUS_WAIT_0);
}
//zero timeout is used for testing if the object(s) can be immediately acquired
if (Timeout != NULL && Timeout->QuadPart == 0)
{
KeReleaseDispatcherDatabaseLock(FALSE);
return STATUS_TIMEOUT;
} }
/* /*
* Check if we have already timed out * Check if we have already timed out
*/ */
if (Timeout != NULL && if (Timeout != NULL && KiIsObjectSignalled(&CurrentThread->Timer.Header, CurrentThread))
KiIsObjectSignalled(&CurrentThread->Timer.Header, CurrentThread, NULL))
{ {
KiSideEffectsBeforeWake(&CurrentThread->Timer.Header, CurrentThread);
KeCancelTimer(&CurrentThread->Timer); KeCancelTimer(&CurrentThread->Timer);
KeReleaseDispatcherDatabaseLock(FALSE); KeReleaseDispatcherDatabaseLock(FALSE);
return(STATUS_TIMEOUT); return (STATUS_TIMEOUT);
} }
/* Append wait block to the KTHREAD wait block list */ /* Append wait block to the KTHREAD wait block list */
@ -673,14 +561,16 @@ KeWaitForMultipleObjects(ULONG Count,
* Set up the wait * Set up the wait
*/ */
CurrentThread->WaitStatus = STATUS_UNSUCCESSFUL; CurrentThread->WaitStatus = STATUS_UNSUCCESSFUL;
for (i = 0; i < Count; i++) for (i = 0; i < Count; i++)
{ {
hdr = (DISPATCHER_HEADER *)Object[i]; hdr = (DISPATCHER_HEADER *) Object[i];
blk->Object = Object[i]; blk->Object = Object[i];
blk->Thread = CurrentThread; blk->Thread = CurrentThread;
blk->WaitKey = STATUS_WAIT_0 + i; blk->WaitKey = STATUS_WAIT_0 + i;
blk->WaitType = WaitType; blk->WaitType = WaitType;
if (i == (Count - 1)) if (i == (Count - 1))
{ {
if (Timeout != NULL) if (Timeout != NULL)
@ -697,23 +587,27 @@ KeWaitForMultipleObjects(ULONG Count,
blk->NextWaitBlock = blk + 1; blk->NextWaitBlock = blk + 1;
} }
//add wait block to disp. obj. wait list
InsertTailList(&hdr->WaitListHead, &blk->WaitListEntry); InsertTailList(&hdr->WaitListHead, &blk->WaitListEntry);
blk = blk->NextWaitBlock; blk = blk->NextWaitBlock;
} }
if (Timeout != NULL) if (Timeout != NULL)
{ {
CurrentThread->WaitBlock[3].Object = (PVOID)&CurrentThread->Timer; CurrentThread->WaitBlock[3].Object = (PVOID) & CurrentThread->Timer;
CurrentThread->WaitBlock[3].Thread = CurrentThread; CurrentThread->WaitBlock[3].Thread = CurrentThread;
CurrentThread->WaitBlock[3].WaitKey = STATUS_TIMEOUT; CurrentThread->WaitBlock[3].WaitKey = STATUS_TIMEOUT;
CurrentThread->WaitBlock[3].WaitType = WaitAny; CurrentThread->WaitBlock[3].WaitType = WaitAny;
CurrentThread->WaitBlock[3].NextWaitBlock = NULL; CurrentThread->WaitBlock[3].NextWaitBlock = NULL;
InsertTailList(&CurrentThread->Timer.Header.WaitListHead, InsertTailList(&CurrentThread->Timer.Header.WaitListHead,
&CurrentThread->WaitBlock[3].WaitListEntry); &CurrentThread->WaitBlock[3].WaitListEntry);
} }
PsBlockThread(&Status, Alertable, WaitMode, TRUE, WaitIrql); PsBlockThread(&Status, Alertable, WaitMode, TRUE, WaitIrql);
} while(Status == STATUS_KERNEL_APC); }
while (Status == STATUS_KERNEL_APC);
if (Timeout != NULL) if (Timeout != NULL)
{ {
@ -721,7 +615,7 @@ KeWaitForMultipleObjects(ULONG Count,
} }
DPRINT("Returning from KeWaitForMultipleObjects()\n"); DPRINT("Returning from KeWaitForMultipleObjects()\n");
return(Status); return (Status);
} }
VOID KeInitializeDispatcher(VOID) VOID KeInitializeDispatcher(VOID)
@ -732,7 +626,7 @@ VOID KeInitializeDispatcher(VOID)
NTSTATUS STDCALL NTSTATUS STDCALL
NtWaitForMultipleObjects(IN ULONG Count, NtWaitForMultipleObjects(IN ULONG Count,
IN HANDLE Object [], IN HANDLE Object [],
IN CINT WaitType, IN WAIT_TYPE WaitType,
IN BOOLEAN Alertable, IN BOOLEAN Alertable,
IN PLARGE_INTEGER Time) IN PLARGE_INTEGER Time)
{ {
@ -740,6 +634,7 @@ NtWaitForMultipleObjects(IN ULONG Count,
PVOID ObjectPtrArray[EX_MAXIMUM_WAIT_OBJECTS]; PVOID ObjectPtrArray[EX_MAXIMUM_WAIT_OBJECTS];
NTSTATUS Status; NTSTATUS Status;
ULONG i, j; ULONG i, j;
KPROCESSOR_MODE WaitMode;
DPRINT("NtWaitForMultipleObjects(Count %lu Object[] %x, Alertable %d, " DPRINT("NtWaitForMultipleObjects(Count %lu Object[] %x, Alertable %d, "
"Time %x)\n", Count,Object,Alertable,Time); "Time %x)\n", Count,Object,Alertable,Time);
@ -747,13 +642,15 @@ NtWaitForMultipleObjects(IN ULONG Count,
if (Count > EX_MAXIMUM_WAIT_OBJECTS) if (Count > EX_MAXIMUM_WAIT_OBJECTS)
return STATUS_UNSUCCESSFUL; return STATUS_UNSUCCESSFUL;
WaitMode = ExGetPreviousMode();
/* reference all objects */ /* reference all objects */
for (i = 0; i < Count; i++) for (i = 0; i < Count; i++)
{ {
Status = ObReferenceObjectByHandle(Object[i], Status = ObReferenceObjectByHandle(Object[i],
SYNCHRONIZE, SYNCHRONIZE,
NULL, NULL,
UserMode, WaitMode,
&ObjectPtrArray[i], &ObjectPtrArray[i],
NULL); NULL);
if (Status != STATUS_SUCCESS) if (Status != STATUS_SUCCESS)
@ -772,7 +669,7 @@ NtWaitForMultipleObjects(IN ULONG Count,
ObjectPtrArray, ObjectPtrArray,
WaitType, WaitType,
UserRequest, UserRequest,
UserMode, WaitMode,
Alertable, Alertable,
Time, Time,
WaitBlockArray); WaitBlockArray);
@ -794,14 +691,17 @@ NtWaitForSingleObject(IN HANDLE Object,
{ {
PVOID ObjectPtr; PVOID ObjectPtr;
NTSTATUS Status; NTSTATUS Status;
KPROCESSOR_MODE WaitMode;
DPRINT("NtWaitForSingleObject(Object %x, Alertable %d, Time %x)\n", DPRINT("NtWaitForSingleObject(Object %x, Alertable %d, Time %x)\n",
Object,Alertable,Time); Object,Alertable,Time);
WaitMode = ExGetPreviousMode();
Status = ObReferenceObjectByHandle(Object, Status = ObReferenceObjectByHandle(Object,
SYNCHRONIZE, SYNCHRONIZE,
NULL, NULL,
UserMode, WaitMode,
&ObjectPtr, &ObjectPtr,
NULL); NULL);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
@ -810,8 +710,8 @@ NtWaitForSingleObject(IN HANDLE Object,
} }
Status = KeWaitForSingleObject(ObjectPtr, Status = KeWaitForSingleObject(ObjectPtr,
UserMode, UserRequest,
UserMode, WaitMode,
Alertable, Alertable,
Time); Time);
@ -827,17 +727,17 @@ NtSignalAndWaitForSingleObject(IN HANDLE SignalObject,
IN BOOLEAN Alertable, IN BOOLEAN Alertable,
IN PLARGE_INTEGER Time) IN PLARGE_INTEGER Time)
{ {
KPROCESSOR_MODE ProcessorMode; KPROCESSOR_MODE WaitMode;
DISPATCHER_HEADER* hdr; DISPATCHER_HEADER* hdr;
PVOID SignalObj; PVOID SignalObj;
PVOID WaitObj; PVOID WaitObj;
NTSTATUS Status; NTSTATUS Status;
ProcessorMode = ExGetPreviousMode(); WaitMode = ExGetPreviousMode();
Status = ObReferenceObjectByHandle(SignalObject, Status = ObReferenceObjectByHandle(SignalObject,
0, 0,
NULL, NULL,
ProcessorMode, WaitMode,
&SignalObj, &SignalObj,
NULL); NULL);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
@ -848,7 +748,7 @@ NtSignalAndWaitForSingleObject(IN HANDLE SignalObject,
Status = ObReferenceObjectByHandle(WaitObject, Status = ObReferenceObjectByHandle(WaitObject,
SYNCHRONIZE, SYNCHRONIZE,
NULL, NULL,
ProcessorMode, WaitMode,
&WaitObj, &WaitObj,
NULL); NULL);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
@ -887,7 +787,7 @@ NtSignalAndWaitForSingleObject(IN HANDLE SignalObject,
Status = KeWaitForSingleObject(WaitObj, Status = KeWaitForSingleObject(WaitObj,
UserRequest, UserRequest,
ProcessorMode, WaitMode,
Alertable, Alertable,
Time); Time);