mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 18:15:11 +00:00
WaitForMultipleObjects: WaitAll waits were buggy
Many small fixes and cleanups svn path=/trunk/; revision=4205
This commit is contained in:
parent
3013b90260
commit
5852f3f492
1 changed files with 415 additions and 515 deletions
|
@ -33,6 +33,9 @@ static BOOLEAN WaitSet = FALSE;
|
|||
static KIRQL oldlvl = PASSIVE_LEVEL;
|
||||
static PKTHREAD Owner = NULL;
|
||||
|
||||
#define KeDispatcherObjectWakeOne(hdr) KeDispatcherObjectWakeOneOrAll(hdr, FALSE)
|
||||
#define KeDispatcherObjectWakeAll(hdr) KeDispatcherObjectWakeOneOrAll(hdr, TRUE)
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
VOID KeInitializeDispatcherHeader(DISPATCHER_HEADER* Header,
|
||||
|
@ -85,16 +88,15 @@ VOID KeReleaseDispatcherDatabaseLock(BOOLEAN Wait)
|
|||
}
|
||||
}
|
||||
|
||||
static VOID KiSideEffectsBeforeWake(DISPATCHER_HEADER* hdr,
|
||||
PKTHREAD Thread,
|
||||
PBOOLEAN Abandoned)
|
||||
static BOOLEAN
|
||||
KiSideEffectsBeforeWake(DISPATCHER_HEADER * hdr,
|
||||
PKTHREAD Thread)
|
||||
/*
|
||||
* FUNCTION: Perform side effects on object before a wait for a thread is
|
||||
* satisfied
|
||||
*/
|
||||
{
|
||||
if (Abandoned != NULL)
|
||||
*Abandoned = FALSE;
|
||||
BOOLEAN Abandoned = FALSE;
|
||||
|
||||
switch (hdr->Type)
|
||||
{
|
||||
|
@ -133,14 +135,12 @@ static VOID KiSideEffectsBeforeWake(DISPATCHER_HEADER* hdr,
|
|||
{
|
||||
if (Thread == NULL)
|
||||
{
|
||||
DPRINT1("Thread == NULL!\n");
|
||||
DPRINT("Thread == NULL!\n");
|
||||
KeBugCheck(0);
|
||||
}
|
||||
if (Abandoned != NULL)
|
||||
*Abandoned = Mutex->Abandoned;
|
||||
Abandoned = Mutex->Abandoned;
|
||||
if (Thread != NULL)
|
||||
InsertTailList(&Thread->MutantListHead,
|
||||
&Mutex->MutantListEntry);
|
||||
InsertTailList(&Thread->MutantListHead, &Mutex->MutantListEntry);
|
||||
Mutex->OwnerThread = Thread;
|
||||
Mutex->Abandoned = FALSE;
|
||||
}
|
||||
|
@ -148,20 +148,17 @@ static VOID KiSideEffectsBeforeWake(DISPATCHER_HEADER* hdr,
|
|||
break;
|
||||
|
||||
default:
|
||||
DbgPrint("(%s:%d) Dispatcher object %x has unknown type\n",
|
||||
__FILE__,__LINE__,hdr);
|
||||
DbgPrint("(%s:%d) Dispatcher object %x has unknown type\n", __FILE__, __LINE__, hdr);
|
||||
KeBugCheck(0);
|
||||
}
|
||||
|
||||
return Abandoned;
|
||||
}
|
||||
|
||||
static BOOLEAN
|
||||
KiIsObjectSignalled(DISPATCHER_HEADER * hdr,
|
||||
PKTHREAD Thread,
|
||||
PBOOLEAN Abandoned)
|
||||
PKTHREAD Thread)
|
||||
{
|
||||
if (Abandoned != NULL)
|
||||
*Abandoned = FALSE;
|
||||
|
||||
if (hdr->Type == InternalMutexType)
|
||||
{
|
||||
PKMUTEX Mutex;
|
||||
|
@ -169,12 +166,9 @@ KiIsObjectSignalled(DISPATCHER_HEADER* hdr,
|
|||
Mutex = CONTAINING_RECORD(hdr, KMUTEX, Header);
|
||||
|
||||
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,
|
||||
Thread,
|
||||
Abandoned);
|
||||
return (TRUE);
|
||||
}
|
||||
else
|
||||
|
@ -182,15 +176,13 @@ KiIsObjectSignalled(DISPATCHER_HEADER* hdr,
|
|||
return (FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
if (hdr->SignalState <= 0)
|
||||
{
|
||||
return (FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
KiSideEffectsBeforeWake(hdr,
|
||||
Thread,
|
||||
Abandoned);
|
||||
return (TRUE);
|
||||
}
|
||||
}
|
||||
|
@ -222,156 +214,114 @@ VOID KeRemoveAllWaitsThread(PETHREAD Thread, NTSTATUS WaitStatus)
|
|||
KeReleaseDispatcherDatabaseLock(FALSE);
|
||||
}
|
||||
|
||||
static BOOLEAN KeDispatcherObjectWakeAll(DISPATCHER_HEADER* hdr)
|
||||
static BOOLEAN
|
||||
KeDispatcherObjectWakeOneOrAll(DISPATCHER_HEADER * hdr,
|
||||
BOOLEAN WakeAll)
|
||||
{
|
||||
PKWAIT_BLOCK current;
|
||||
PLIST_ENTRY current_entry;
|
||||
PKWAIT_BLOCK PrevBlock;
|
||||
PKWAIT_BLOCK Waiter;
|
||||
PKWAIT_BLOCK WaiterHead;
|
||||
PLIST_ENTRY EnumEntry;
|
||||
NTSTATUS Status;
|
||||
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))
|
||||
{
|
||||
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);
|
||||
current = CONTAINING_RECORD(current_entry,
|
||||
KWAIT_BLOCK,
|
||||
WaitListEntry);
|
||||
DPRINT("Waking %x\n",current->Thread);
|
||||
if (current->WaitType == WaitAny)
|
||||
WaiterHead = CONTAINING_RECORD(EnumEntry, KWAIT_BLOCK, WaitListEntry);
|
||||
DPRINT("current_entry %x current %x\n", EnumEntry, WaiterHead);
|
||||
EnumEntry = EnumEntry->Flink;
|
||||
assert(WaiterHead->Thread->WaitBlockList != NULL);
|
||||
|
||||
Abandoned = FALSE;
|
||||
|
||||
if (WaiterHead->WaitType == WaitAny)
|
||||
{
|
||||
DPRINT("WaitAny: Remove all wait blocks.\n");
|
||||
for(PrevBlock = current->Thread->WaitBlockList; PrevBlock;
|
||||
PrevBlock = PrevBlock->NextWaitBlock)
|
||||
for (Waiter = WaiterHead->Thread->WaitBlockList; Waiter; Waiter = Waiter->NextWaitBlock)
|
||||
{
|
||||
if (PrevBlock != current)
|
||||
RemoveEntryList(&PrevBlock->WaitListEntry);
|
||||
RemoveEntryList(&Waiter->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;
|
||||
WaiterHead->Thread->WaitBlockList = NULL;
|
||||
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINT( "WaitAll: Current block is not list head.\n" );
|
||||
while (PrevBlock && PrevBlock->NextWaitBlock != current)
|
||||
DPRINT("WaitAll: All WaitAll objects must be signaled.\n");
|
||||
|
||||
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;
|
||||
}
|
||||
if (PrevBlock)
|
||||
//no need to check hdr since it has to be signaled
|
||||
if (Waiter->WaitType == WaitAll && Waiter->Object != hdr)
|
||||
{
|
||||
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 == ¤t->Thread->WaitBlock[3] && PrevBlock->NextWaitBlock == NULL)
|
||||
if (!KiIsObjectSignalled(Waiter->Object, Waiter->Thread))
|
||||
{
|
||||
RemoveEntryList(¤t->Thread->WaitBlock[3].WaitListEntry);
|
||||
current->Thread->WaitBlockList = NULL;
|
||||
AllSignaled = FALSE;
|
||||
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)
|
||||
{
|
||||
DPRINT("Abandoned mutex among objects");
|
||||
Status += STATUS_ABANDONED_WAIT_0;
|
||||
if (current->Thread->WaitBlockList == NULL)
|
||||
{
|
||||
PsUnblockThread(CONTAINING_RECORD(current->Thread,ETHREAD,Tcb),
|
||||
&Status);
|
||||
}
|
||||
}
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
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 == ¤t->Thread->WaitBlock[3] && PrevBlock->NextWaitBlock == NULL)
|
||||
{
|
||||
RemoveEntryList(¤t->Thread->WaitBlock[3].WaitListEntry);
|
||||
current->Thread->WaitBlockList = NULL;
|
||||
WakedAny = TRUE;
|
||||
DPRINT("Waking %x status = %x\n", WaiterHead->Thread, Status);
|
||||
PsUnblockThread(CONTAINING_RECORD(WaiterHead->Thread, ETHREAD, Tcb), &Status);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
return WakedAny;
|
||||
}
|
||||
|
||||
|
||||
BOOLEAN KeDispatcherObjectWake(DISPATCHER_HEADER* hdr)
|
||||
/*
|
||||
* FUNCTION: Wake threads waiting on a dispatcher object
|
||||
|
@ -446,103 +396,14 @@ KeWaitForSingleObject(PVOID Object,
|
|||
* RETURNS: Status
|
||||
*/
|
||||
{
|
||||
DISPATCHER_HEADER* hdr = (DISPATCHER_HEADER *)Object;
|
||||
PKTHREAD CurrentThread;
|
||||
NTSTATUS Status;
|
||||
KIRQL WaitIrql;
|
||||
BOOLEAN Abandoned;
|
||||
|
||||
CurrentThread = KeGetCurrentThread();
|
||||
WaitIrql = KeGetCurrentIrql();
|
||||
|
||||
/*
|
||||
* 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);
|
||||
return KeWaitForMultipleObjects(1,
|
||||
&Object,
|
||||
WaitAny,
|
||||
WaitReason,
|
||||
WaitMode,
|
||||
Alertable,
|
||||
Timeout,
|
||||
NULL);
|
||||
}
|
||||
|
||||
|
||||
|
@ -568,7 +429,6 @@ KeWaitForMultipleObjects(ULONG Count,
|
|||
DPRINT("Entering KeWaitForMultipleObjects(Count %lu Object[] %p) "
|
||||
"PsGetCurrentThread() %x\n", Count, Object, PsGetCurrentThread());
|
||||
|
||||
CountSignaled = 0;
|
||||
CurrentThread = KeGetCurrentThread();
|
||||
WaitIrql = KeGetCurrentIrql();
|
||||
|
||||
|
@ -579,8 +439,7 @@ KeWaitForMultipleObjects(ULONG Count,
|
|||
{
|
||||
if (Count > THREAD_WAIT_OBJECTS)
|
||||
{
|
||||
DbgPrint("(%s:%d) Too many objects!\n",
|
||||
__FILE__,__LINE__);
|
||||
DPRINT("(%s:%d) Too many objects!\n", __FILE__, __LINE__);
|
||||
return (STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
WaitBlockArray = &CurrentThread->WaitBlock[0];
|
||||
|
@ -589,8 +448,7 @@ KeWaitForMultipleObjects(ULONG Count,
|
|||
{
|
||||
if (Count > EX_MAXIMUM_WAIT_OBJECTS)
|
||||
{
|
||||
DbgPrint("(%s:%d) Too many objects!\n",
|
||||
__FILE__,__LINE__);
|
||||
DPRINT("(%s:%d) Too many objects!\n", __FILE__, __LINE__);
|
||||
return (STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
}
|
||||
|
@ -598,7 +456,7 @@ KeWaitForMultipleObjects(ULONG Count,
|
|||
/*
|
||||
* Set up the timeout if required
|
||||
*/
|
||||
if (Timeout != NULL)
|
||||
if (Timeout != NULL && Timeout->QuadPart != 0)
|
||||
{
|
||||
KeInitializeTimer(&CurrentThread->Timer);
|
||||
KeSetTimer(&CurrentThread->Timer, *Timeout, NULL);
|
||||
|
@ -619,48 +477,78 @@ KeWaitForMultipleObjects(ULONG Count,
|
|||
}
|
||||
|
||||
/*
|
||||
* Check if the wait is already satisfied
|
||||
* Check if the wait is (already) satisfied
|
||||
*/
|
||||
CountSignaled = 0;
|
||||
Abandoned = FALSE;
|
||||
for (i = 0; i < Count; i++)
|
||||
{
|
||||
hdr = (DISPATCHER_HEADER *) Object[i];
|
||||
|
||||
if (KiIsObjectSignalled(hdr, CurrentThread, &Abandoned))
|
||||
if (KiIsObjectSignalled(hdr, CurrentThread))
|
||||
{
|
||||
CountSignaled++;
|
||||
|
||||
if (WaitType == WaitAny)
|
||||
{
|
||||
if (Timeout != NULL)
|
||||
Abandoned = KiSideEffectsBeforeWake(hdr, CurrentThread) ? TRUE : Abandoned;
|
||||
|
||||
if (Timeout != NULL && Timeout->QuadPart != 0)
|
||||
{
|
||||
KeCancelTimer(&CurrentThread->Timer);
|
||||
}
|
||||
|
||||
KeReleaseDispatcherDatabaseLock(FALSE);
|
||||
DPRINT("One object is already signaled!\n");
|
||||
|
||||
DPRINT("One object is (already) signaled!\n");
|
||||
if (Abandoned == TRUE)
|
||||
{
|
||||
return (STATUS_ABANDONED_WAIT_0 + i);
|
||||
}
|
||||
|
||||
return (STATUS_WAIT_0 + i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Abandoned = FALSE;
|
||||
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);
|
||||
}
|
||||
|
||||
KeReleaseDispatcherDatabaseLock(FALSE);
|
||||
DPRINT("All objects are already signaled!\n");
|
||||
DPRINT("All objects are (already) signaled!\n");
|
||||
|
||||
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
|
||||
*/
|
||||
if (Timeout != NULL &&
|
||||
KiIsObjectSignalled(&CurrentThread->Timer.Header, CurrentThread, NULL))
|
||||
if (Timeout != NULL && KiIsObjectSignalled(&CurrentThread->Timer.Header, CurrentThread))
|
||||
{
|
||||
KiSideEffectsBeforeWake(&CurrentThread->Timer.Header, CurrentThread);
|
||||
KeCancelTimer(&CurrentThread->Timer);
|
||||
KeReleaseDispatcherDatabaseLock(FALSE);
|
||||
return (STATUS_TIMEOUT);
|
||||
|
@ -673,6 +561,7 @@ KeWaitForMultipleObjects(ULONG Count,
|
|||
* Set up the wait
|
||||
*/
|
||||
CurrentThread->WaitStatus = STATUS_UNSUCCESSFUL;
|
||||
|
||||
for (i = 0; i < Count; i++)
|
||||
{
|
||||
hdr = (DISPATCHER_HEADER *) Object[i];
|
||||
|
@ -681,6 +570,7 @@ KeWaitForMultipleObjects(ULONG Count,
|
|||
blk->Thread = CurrentThread;
|
||||
blk->WaitKey = STATUS_WAIT_0 + i;
|
||||
blk->WaitType = WaitType;
|
||||
|
||||
if (i == (Count - 1))
|
||||
{
|
||||
if (Timeout != NULL)
|
||||
|
@ -697,10 +587,12 @@ KeWaitForMultipleObjects(ULONG Count,
|
|||
blk->NextWaitBlock = blk + 1;
|
||||
}
|
||||
|
||||
//add wait block to disp. obj. wait list
|
||||
InsertTailList(&hdr->WaitListHead, &blk->WaitListEntry);
|
||||
|
||||
blk = blk->NextWaitBlock;
|
||||
}
|
||||
|
||||
if (Timeout != NULL)
|
||||
{
|
||||
CurrentThread->WaitBlock[3].Object = (PVOID) & CurrentThread->Timer;
|
||||
|
@ -708,12 +600,14 @@ KeWaitForMultipleObjects(ULONG Count,
|
|||
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);
|
||||
}
|
||||
|
||||
PsBlockThread(&Status, Alertable, WaitMode, TRUE, WaitIrql);
|
||||
} while(Status == STATUS_KERNEL_APC);
|
||||
}
|
||||
while (Status == STATUS_KERNEL_APC);
|
||||
|
||||
if (Timeout != NULL)
|
||||
{
|
||||
|
@ -732,7 +626,7 @@ VOID KeInitializeDispatcher(VOID)
|
|||
NTSTATUS STDCALL
|
||||
NtWaitForMultipleObjects(IN ULONG Count,
|
||||
IN HANDLE Object [],
|
||||
IN CINT WaitType,
|
||||
IN WAIT_TYPE WaitType,
|
||||
IN BOOLEAN Alertable,
|
||||
IN PLARGE_INTEGER Time)
|
||||
{
|
||||
|
@ -740,6 +634,7 @@ NtWaitForMultipleObjects(IN ULONG Count,
|
|||
PVOID ObjectPtrArray[EX_MAXIMUM_WAIT_OBJECTS];
|
||||
NTSTATUS Status;
|
||||
ULONG i, j;
|
||||
KPROCESSOR_MODE WaitMode;
|
||||
|
||||
DPRINT("NtWaitForMultipleObjects(Count %lu Object[] %x, Alertable %d, "
|
||||
"Time %x)\n", Count,Object,Alertable,Time);
|
||||
|
@ -747,13 +642,15 @@ NtWaitForMultipleObjects(IN ULONG Count,
|
|||
if (Count > EX_MAXIMUM_WAIT_OBJECTS)
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
|
||||
WaitMode = ExGetPreviousMode();
|
||||
|
||||
/* reference all objects */
|
||||
for (i = 0; i < Count; i++)
|
||||
{
|
||||
Status = ObReferenceObjectByHandle(Object[i],
|
||||
SYNCHRONIZE,
|
||||
NULL,
|
||||
UserMode,
|
||||
WaitMode,
|
||||
&ObjectPtrArray[i],
|
||||
NULL);
|
||||
if (Status != STATUS_SUCCESS)
|
||||
|
@ -772,7 +669,7 @@ NtWaitForMultipleObjects(IN ULONG Count,
|
|||
ObjectPtrArray,
|
||||
WaitType,
|
||||
UserRequest,
|
||||
UserMode,
|
||||
WaitMode,
|
||||
Alertable,
|
||||
Time,
|
||||
WaitBlockArray);
|
||||
|
@ -794,14 +691,17 @@ NtWaitForSingleObject(IN HANDLE Object,
|
|||
{
|
||||
PVOID ObjectPtr;
|
||||
NTSTATUS Status;
|
||||
KPROCESSOR_MODE WaitMode;
|
||||
|
||||
DPRINT("NtWaitForSingleObject(Object %x, Alertable %d, Time %x)\n",
|
||||
Object,Alertable,Time);
|
||||
|
||||
WaitMode = ExGetPreviousMode();
|
||||
|
||||
Status = ObReferenceObjectByHandle(Object,
|
||||
SYNCHRONIZE,
|
||||
NULL,
|
||||
UserMode,
|
||||
WaitMode,
|
||||
&ObjectPtr,
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
|
@ -810,8 +710,8 @@ NtWaitForSingleObject(IN HANDLE Object,
|
|||
}
|
||||
|
||||
Status = KeWaitForSingleObject(ObjectPtr,
|
||||
UserMode,
|
||||
UserMode,
|
||||
UserRequest,
|
||||
WaitMode,
|
||||
Alertable,
|
||||
Time);
|
||||
|
||||
|
@ -827,17 +727,17 @@ NtSignalAndWaitForSingleObject(IN HANDLE SignalObject,
|
|||
IN BOOLEAN Alertable,
|
||||
IN PLARGE_INTEGER Time)
|
||||
{
|
||||
KPROCESSOR_MODE ProcessorMode;
|
||||
KPROCESSOR_MODE WaitMode;
|
||||
DISPATCHER_HEADER* hdr;
|
||||
PVOID SignalObj;
|
||||
PVOID WaitObj;
|
||||
NTSTATUS Status;
|
||||
|
||||
ProcessorMode = ExGetPreviousMode();
|
||||
WaitMode = ExGetPreviousMode();
|
||||
Status = ObReferenceObjectByHandle(SignalObject,
|
||||
0,
|
||||
NULL,
|
||||
ProcessorMode,
|
||||
WaitMode,
|
||||
&SignalObj,
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
|
@ -848,7 +748,7 @@ NtSignalAndWaitForSingleObject(IN HANDLE SignalObject,
|
|||
Status = ObReferenceObjectByHandle(WaitObject,
|
||||
SYNCHRONIZE,
|
||||
NULL,
|
||||
ProcessorMode,
|
||||
WaitMode,
|
||||
&WaitObj,
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
|
@ -887,7 +787,7 @@ NtSignalAndWaitForSingleObject(IN HANDLE SignalObject,
|
|||
|
||||
Status = KeWaitForSingleObject(WaitObj,
|
||||
UserRequest,
|
||||
ProcessorMode,
|
||||
WaitMode,
|
||||
Alertable,
|
||||
Time);
|
||||
|
||||
|
|
Loading…
Reference in a new issue