VOID KeReleaseDispatcherDatabaseLock(BOOLEAN Wait)
{
- DPRINT("KeReleaseDispatcherDatabaseLock(Wait %x)\n",Wait);
+ DPRINT("KeReleaseDispatcherDatabaseLock(Wait %x)\n",Wait);
assert(Wait==WaitSet);
if (!Wait)
{
}
}
-VOID KiSideEffectsBeforeWake(DISPATCHER_HEADER* hdr,
- PKTHREAD Thread)
+static VOID KiSideEffectsBeforeWake(DISPATCHER_HEADER* hdr,
+ PKTHREAD Thread,
+ PBOOLEAN Abandoned)
/*
* FUNCTION: Perform side effects on object before a wait for a thread is
* satisfied
*/
{
+ if (Abandoned != NULL)
+ *Abandoned = FALSE;
+
switch (hdr->Type)
{
case InternalSynchronizationEvent:
{
if (Thread == NULL)
{
- DPRINT1("Thread == NULL!\n")
+ DPRINT1("Thread == NULL!\n");
// KeBugCheck(0);
}
+ if (Abandoned != NULL)
+ *Abandoned = Mutex->Abandoned;
if (Thread != NULL)
InsertTailList(&Thread->MutantListHead,
&Mutex->MutantListEntry);
__FILE__,__LINE__,hdr);
KeBugCheck(0);
}
-
}
-static BOOLEAN KiIsObjectSignalled(DISPATCHER_HEADER* hdr,
- PKTHREAD Thread)
+static BOOLEAN
+KiIsObjectSignalled(DISPATCHER_HEADER* hdr,
+ PKTHREAD Thread,
+ PBOOLEAN Abandoned)
{
+ if (Abandoned != NULL)
+ *Abandoned = FALSE;
+
if (hdr->Type == InternalMutexType)
{
PKMUTEX Mutex;
hdr->SignalState == 1)
{
KiSideEffectsBeforeWake(hdr,
- Thread);
+ Thread,
+ Abandoned);
return(TRUE);
}
else
}
else
{
- KiSideEffectsBeforeWake(hdr, Thread);
+ KiSideEffectsBeforeWake(hdr,
+ Thread,
+ Abandoned);
return(TRUE);
}
}
if (WaitBlock != NULL)
{
WasWaiting = TRUE;
- }
+ }
while (WaitBlock != NULL)
{
RemoveEntryList(&WaitBlock->WaitListEntry);
PLIST_ENTRY current_entry;
PKWAIT_BLOCK PrevBlock;
NTSTATUS Status;
+ BOOLEAN Abandoned;
DPRINT("KeDispatcherObjectWakeAll(hdr %x)\n",hdr);
if (current->WaitType == WaitAny)
{
DPRINT("WaitAny: Remove all wait blocks.\n");
- for(PrevBlock = current->Thread->WaitBlockList; PrevBlock;
+ for(PrevBlock = current->Thread->WaitBlockList; PrevBlock;
PrevBlock = PrevBlock->NextWaitBlock)
{
if (PrevBlock != current)
PrevBlock->NextWaitBlock = current->NextWaitBlock;
}
}
- }
- KiSideEffectsBeforeWake(hdr, 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),
+ PsUnblockThread(CONTAINING_RECORD(current->Thread,ETHREAD,Tcb),
&Status);
}
}
static BOOLEAN KeDispatcherObjectWakeOne(DISPATCHER_HEADER* hdr)
{
- PKWAIT_BLOCK current;
- PLIST_ENTRY current_entry;
- PKWAIT_BLOCK PrevBlock;
- NTSTATUS Status;
+ 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);
+ 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)
{
PrevBlock->NextWaitBlock = current->NextWaitBlock;
}
}
- }
+ }
- DPRINT("Waking %x\n",current->Thread);
- KiSideEffectsBeforeWake(hdr, current->Thread);
- Status = current->WaitKey;
- PsUnblockThread(CONTAINING_RECORD(current->Thread, ETHREAD, Tcb),
- &Status);
- return(TRUE);
+ DPRINT("Waking %x\n",current->Thread);
+ KiSideEffectsBeforeWake(hdr, current->Thread, &Abandoned);
+ Status = current->WaitKey;
+ if (Abandoned)
+ Status += STATUS_ABANDONED_WAIT_0;
+ PsUnblockThread(CONTAINING_RECORD(current->Thread, ETHREAD, Tcb),
+ &Status);
+ return(TRUE);
}
BOOLEAN KeDispatcherObjectWake(DISPATCHER_HEADER* hdr)
PKTHREAD CurrentThread;
NTSTATUS Status;
KIRQL WaitIrql;
+ BOOLEAN Abandoned;
CurrentThread = KeGetCurrentThread();
WaitIrql = KeGetCurrentIrql();
}
/*
- * If the object is signalled
+ * If the object is signalled
*/
- if (KiIsObjectSignalled(hdr, CurrentThread))
+ if (KiIsObjectSignalled(hdr, CurrentThread, &Abandoned))
{
KeReleaseDispatcherDatabaseLock(FALSE);
if (Timeout != NULL)
{
KeCancelTimer(&KeGetCurrentThread()->Timer);
}
+ 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))
+ KiIsObjectSignalled(&CurrentThread->Timer.Header, CurrentThread, NULL))
{
KeReleaseDispatcherDatabaseLock(FALSE);
if (Timeout != NULL)
CurrentThread->WaitBlockList = &CurrentThread->WaitBlock[0];
CurrentThread->WaitBlock[0].Object = Object;
CurrentThread->WaitBlock[0].Thread = CurrentThread;
- CurrentThread->WaitBlock[0].WaitKey = 0;
+ CurrentThread->WaitBlock[0].WaitKey = STATUS_WAIT_0;
CurrentThread->WaitBlock[0].WaitType = WaitAny;
InsertTailList(&hdr->WaitListHead,
&CurrentThread->WaitBlock[0].WaitListEntry);
&CurrentThread->WaitBlock[1];
CurrentThread->WaitBlock[1].Object = (PVOID)&CurrentThread->Timer;
CurrentThread->WaitBlock[1].Thread = CurrentThread;
- CurrentThread->WaitBlock[1].WaitKey = 1;
+ CurrentThread->WaitBlock[1].WaitKey = STATUS_TIMEOUT;
CurrentThread->WaitBlock[1].WaitType = WaitAny;
CurrentThread->WaitBlock[1].NextWaitBlock = NULL;
InsertTailList(&CurrentThread->Timer.Header.WaitListHead,
{
KeCancelTimer(&KeGetCurrentThread()->Timer);
}
- if (Status == (STATUS_WAIT_0 + 1))
- {
- Status = STATUS_TIMEOUT;
- }
DPRINT("Returning from KeWaitForSingleObject()\n");
return(Status);
ULONG i;
NTSTATUS Status;
KIRQL WaitIrql;
+ BOOLEAN Abandoned;
DPRINT("Entering KeWaitForMultipleObjects(Count %lu Object[] %p) "
"PsGetCurrentThread() %x\n",Count,Object,PsGetCurrentThread());
{
hdr = (DISPATCHER_HEADER *)Object[i];
- if (KiIsObjectSignalled(hdr, CurrentThread))
+ if (KiIsObjectSignalled(hdr, CurrentThread, &Abandoned))
{
CountSignaled++;
{
KeReleaseDispatcherDatabaseLock(FALSE);
DPRINT("One object is already signaled!\n");
+ if (Abandoned == TRUE)
+ return(STATUS_ABANDONED_WAIT_0 + i);
return(STATUS_WAIT_0 + i);
}
}
* Check if we have already timed out
*/
if (Timeout != NULL &&
- KiIsObjectSignalled(&CurrentThread->Timer.Header, CurrentThread))
+ KiIsObjectSignalled(&CurrentThread->Timer.Header, CurrentThread, NULL))
{
KeReleaseDispatcherDatabaseLock(FALSE);
if (Timeout != NULL)
blk->Object = Object[i];
blk->Thread = CurrentThread;
- blk->WaitKey = i;
+ blk->WaitKey = STATUS_WAIT_0 + i;
blk->WaitType = WaitType;
if (i == (Count - 1))
{
{
CurrentThread->WaitBlock[3].Object = (PVOID)&CurrentThread->Timer;
CurrentThread->WaitBlock[3].Thread = CurrentThread;
- CurrentThread->WaitBlock[3].WaitKey = Count;
+ CurrentThread->WaitBlock[3].WaitKey = STATUS_TIMEOUT;
CurrentThread->WaitBlock[3].WaitType = WaitAny;
CurrentThread->WaitBlock[3].NextWaitBlock = NULL;
InsertTailList(&CurrentThread->Timer.Header.WaitListHead,
{
KeCancelTimer(&KeGetCurrentThread()->Timer);
}
- if (Status == (STATUS_WAIT_0 + Count))
- {
- Status = STATUS_TIMEOUT;
- }
+
DPRINT("Returning from KeWaitForMultipleObjects()\n");
return(Status);
}