fix kernel queues + misc fixes/cleanups

svn path=/trunk/; revision=11754
This commit is contained in:
Gunnar Dalsnes 2004-11-21 18:33:54 +00:00
parent 0f6f4de9e1
commit 0c5a9ba4f5
8 changed files with 222 additions and 136 deletions

View file

@ -124,7 +124,7 @@ KeInsertQueueApc (PKAPC Apc,
PLIST_ENTRY ApcListEntry;
PKAPC QueuedApc;
ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
DPRINT ("KeInsertQueueApc(Apc %x, SystemArgument1 %x, "
"SystemArgument2 %x)\n",Apc,SystemArgument1,
SystemArgument2);
@ -134,7 +134,9 @@ KeInsertQueueApc (PKAPC Apc,
/* Get the Thread specified in the APC */
Thread = Apc->Thread;
/* Make sure the thread allows APC Queues */
/* Make sure the thread allows APC Queues.
* The thread is not apc queueable, for instance, when it's (about to be) terminated.
*/
if (Thread->ApcQueueable == FALSE) {
DPRINT("Thread doesn't allow APC Queues\n");
KeReleaseDispatcherDatabaseLock(OldIrql);
@ -194,18 +196,20 @@ KeInsertQueueApc (PKAPC Apc,
/* FIXME: Use IPI */
DPRINT ("Requesting APC Interrupt for Running Thread \n");
HalRequestSoftwareInterrupt(APC_LEVEL);
} else if ((Thread->WaitIrql < APC_LEVEL) && (Apc->NormalRoutine == NULL)) {
} else if ((Thread->State == THREAD_STATE_BLOCKED) &&
(Thread->WaitIrql < APC_LEVEL) &&
(Apc->NormalRoutine == NULL))
{
DPRINT ("Waking up Thread for Kernel-Mode APC Delivery \n");
KeRemoveAllWaitsThread(CONTAINING_RECORD(Thread, ETHREAD, Tcb),
STATUS_KERNEL_APC,
TRUE);
KiAbortWaitThread(Thread, STATUS_KERNEL_APC);
}
} else if ((Thread->WaitMode == UserMode) && (Thread->Alertable)) {
} else if ((Thread->State == THREAD_STATE_BLOCKED) &&
(Thread->WaitMode == UserMode) &&
(Thread->Alertable))
{
DPRINT ("Waking up Thread for User-Mode APC Delivery \n");
Thread->ApcState.UserApcPending = TRUE;
KeRemoveAllWaitsThread(CONTAINING_RECORD(Thread, ETHREAD, Tcb),
STATUS_USER_APC,
TRUE);
KiAbortWaitThread(Thread, STATUS_USER_APC);
}
/* Return Sucess if we are here */
@ -227,7 +231,7 @@ KeRemoveQueueApc (PKAPC Apc)
KIRQL OldIrql;
PKTHREAD Thread = Apc->Thread;
ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
DPRINT("KeRemoveQueueApc called for APC: %x \n", Apc);
OldIrql = KeAcquireDispatcherDatabaseLock();
@ -270,7 +274,7 @@ KeTestAlertThread(IN KPROCESSOR_MODE AlertMode)
PKTHREAD Thread = KeGetCurrentThread();
BOOLEAN OldState;
ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
OldIrql = KeAcquireDispatcherDatabaseLock();
KiAcquireSpinLock(&Thread->ApcQueueLock);
@ -295,7 +299,7 @@ KeTestAlertThread(IN KPROCESSOR_MODE AlertMode)
*/
VOID
STDCALL
KiDeliverApc(KPROCESSOR_MODE PreviousMode,
KiDeliverApc(KPROCESSOR_MODE DeliveryMode,
PVOID Reserved,
PKTRAP_FRAME TrapFrame)
/*
@ -317,6 +321,8 @@ KiDeliverApc(KPROCESSOR_MODE PreviousMode,
PKNORMAL_ROUTINE NormalRoutine;
PVOID SystemArgument1;
PVOID SystemArgument2;
ASSERT_IRQL_EQUAL(APC_LEVEL);
/* Lock the APC Queue and Raise IRQL to Synch */
KeAcquireSpinLock(&Thread->ApcQueueLock, &OldIrql);
@ -339,7 +345,7 @@ KiDeliverApc(KPROCESSOR_MODE PreviousMode,
SystemArgument2 = Apc->SystemArgument2;
/* Special APC */
if (NormalRoutine == NULL) {
if (NormalRoutine == NULL) {
/* Remove the APC from the list */
Apc->Inserted = FALSE;
RemoveEntryList(ApcListEntry);
@ -360,6 +366,15 @@ KiDeliverApc(KPROCESSOR_MODE PreviousMode,
} else {
/* Normal Kernel APC */
if (Thread->ApcState.KernelApcInProgress || Thread->KernelApcDisable) {
/*
* DeliveryMode must be KernelMode in this case, since one may not
* return to umode while being inside a critical section or while
* a regular kmode apc is running (the latter should be impossible btw).
* -Gunnar
*/
ASSERT(DeliveryMode == KernelMode);
KeReleaseSpinLock(&Thread->ApcQueueLock, OldIrql);
return;
}
@ -399,7 +414,7 @@ KiDeliverApc(KPROCESSOR_MODE PreviousMode,
/* Now we do the User APCs */
if ((!IsListEmpty(&Thread->ApcState.ApcListHead[UserMode])) &&
(PreviousMode == UserMode) &&
(DeliveryMode == UserMode) &&
(Thread->ApcState.UserApcPending == TRUE)) {
/* It's not pending anymore */
@ -418,6 +433,8 @@ KiDeliverApc(KPROCESSOR_MODE PreviousMode,
/* Remove the APC from Queue, restore IRQL and call the APC */
RemoveEntryList(ApcListEntry);
Apc->Inserted = FALSE;
KeReleaseSpinLock(&Thread->ApcQueueLock, OldIrql);
DPRINT("Calling the Kernel Routine for for a User APC: %x\n", Apc);
KernelRoutine(Apc,

View file

@ -1,4 +1,4 @@
/* $Id: critical.c,v 1.10 2004/08/15 16:39:05 chorns Exp $
/* $Id: critical.c,v 1.11 2004/11/21 18:33:54 gdalsnes Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -22,8 +22,13 @@
*/
VOID STDCALL KeEnterCriticalRegion (VOID)
{
PKTHREAD Thread = KeGetCurrentThread();
DPRINT("KeEnterCriticalRegion()\n");
KeGetCurrentThread()->KernelApcDisable--;
if (!Thread) return; /* <-Early in the boot process the current thread is obseved to be NULL */
Thread->KernelApcDisable--;
}
/*
@ -34,6 +39,8 @@ VOID STDCALL KeLeaveCriticalRegion (VOID)
PKTHREAD Thread = KeGetCurrentThread();
DPRINT("KeLeaveCriticalRegion()\n");
if (!Thread) return; /* <-Early in the boot process the current thread is obseved to be NULL */
/* Reference: http://www.ntfsd.org/archive/ntfsd0104/msg0203.html */
if(++Thread->KernelApcDisable == 0)

View file

@ -67,6 +67,9 @@ LONG STDCALL KeReadStateEvent (PKEVENT Event)
*/
LONG STDCALL KeResetEvent (PKEVENT Event)
{
/* FIXME: must use interlocked func. everywhere! (wait.c)
* or use dispather lock instead
* -Gunnar */
return(InterlockedExchange(&(Event->Header.SignalState),0));
}
@ -86,7 +89,7 @@ LONG STDCALL KeSetEvent (PKEVENT Event,
ret = InterlockedExchange(&(Event->Header.SignalState),1);
KeDispatcherObjectWake((DISPATCHER_HEADER *)Event);
KiDispatcherObjectWake((DISPATCHER_HEADER *)Event);
if (Wait == FALSE)
{
@ -115,7 +118,7 @@ NTSTATUS STDCALL KePulseEvent (PKEVENT Event,
DPRINT("KePulseEvent(Event %x, Wait %x)\n",Event,Wait);
OldIrql = KeAcquireDispatcherDatabaseLock();
ret = InterlockedExchange(&(Event->Header.SignalState),1);
KeDispatcherObjectWake((DISPATCHER_HEADER *)Event);
KiDispatcherObjectWake((DISPATCHER_HEADER *)Event);
InterlockedExchange(&(Event->Header.SignalState),0);
if (Wait == FALSE)
@ -143,7 +146,10 @@ KeSetEventBoostPriority(
)
{
PKTHREAD WaitingThread;
KIRQL OldIrql;
OldIrql = KeAcquireDispatcherDatabaseLock();
/* Get Thread that is currently waiting. First get the Wait Block, then the Thread */
WaitingThread = CONTAINING_RECORD(Event->Header.WaitListHead.Flink, KWAIT_BLOCK, WaitListEntry)->Thread;
@ -152,7 +158,9 @@ KeSetEventBoostPriority(
/* Reset the Quantum and Unwait the Thread */
WaitingThread->Quantum = WaitingThread->ApcState.Process->ThreadQuantum;
KeRemoveAllWaitsThread((PETHREAD)WaitingThread, STATUS_SUCCESS, TRUE);
KiAbortWaitThread(WaitingThread, STATUS_SUCCESS);
KeReleaseDispatcherDatabaseLock(OldIrql);
}
/* EOF */

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: mutex.c,v 1.18 2004/10/22 20:30:48 ekohl Exp $
/* $Id: mutex.c,v 1.19 2004/11/21 18:33:54 gdalsnes Exp $
*
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ke/mutex.c
@ -82,7 +82,7 @@ KeReleaseMutex(IN PKMUTEX Mutex,
Mutex->OwnerThread = NULL;
if (Mutex->MutantListEntry.Flink && Mutex->MutantListEntry.Blink)
RemoveEntryList(&Mutex->MutantListEntry);
KeDispatcherObjectWake(&Mutex->Header);
KiDispatcherObjectWake(&Mutex->Header);
}
if (Wait == FALSE)
@ -191,7 +191,7 @@ KeReleaseMutant(IN PKMUTANT Mutant,
Mutant->OwnerThread = NULL;
if (Mutant->MutantListEntry.Flink && Mutant->MutantListEntry.Blink)
RemoveEntryList(&Mutant->MutantListEntry);
KeDispatcherObjectWake(&Mutant->Header);
KiDispatcherObjectWake(&Mutant->Header);
}
if (Wait == FALSE)

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: queue.c,v 1.11 2004/08/15 16:39:05 chorns Exp $
/* $Id: queue.c,v 1.12 2004/11/21 18:33:54 gdalsnes Exp $
*
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ke/queue.c
@ -34,6 +34,7 @@
/* FUNCTIONS *****************************************************************/
/*
* @implemented
*/
@ -54,6 +55,8 @@ KeInitializeQueue(IN PKQUEUE Queue,
/*
* @implemented
*
* Returns number of entries in the queue
*/
LONG STDCALL
KeReadStateQueue(IN PKQUEUE Queue)
@ -61,7 +64,9 @@ KeReadStateQueue(IN PKQUEUE Queue)
return(Queue->Header.SignalState);
}
/*
* Returns the previous number of entries in the queue
*/
LONG STDCALL
KiInsertQueue(
IN PKQUEUE Queue,
@ -70,15 +75,11 @@ KiInsertQueue(
)
{
ULONG InitialState;
KIRQL OldIrql;
DPRINT("KiInsertQueue(Queue %x, Entry %x)\n", Queue, Entry);
OldIrql = KeAcquireDispatcherDatabaseLock ();
InitialState = Queue->Header.SignalState;
Queue->Header.SignalState++;
if (Head)
{
InsertHeadList(&Queue->EntryListHead, Entry);
@ -87,13 +88,21 @@ KiInsertQueue(
{
InsertTailList(&Queue->EntryListHead, Entry);
}
if (Queue->CurrentCount < Queue->MaximumCount && InitialState == 0)
//inc. num entries in queue
Queue->Header.SignalState++;
/* Why the KeGetCurrentThread()->Queue != Queue?
* KiInsertQueue might be called from an APC for the current thread.
* -Gunnar
*/
if (Queue->CurrentCount < Queue->MaximumCount &&
!IsListEmpty(&Queue->Header.WaitListHead) &&
KeGetCurrentThread()->Queue != Queue)
{
KeDispatcherObjectWake(&Queue->Header);
KiDispatcherObjectWake(&Queue->Header);
}
KeReleaseDispatcherDatabaseLock(OldIrql);
return InitialState;
}
@ -106,7 +115,14 @@ LONG STDCALL
KeInsertHeadQueue(IN PKQUEUE Queue,
IN PLIST_ENTRY Entry)
{
return KiInsertQueue(Queue,Entry,TRUE);
LONG Result;
KIRQL OldIrql;
OldIrql = KeAcquireDispatcherDatabaseLock();
Result = KiInsertQueue(Queue,Entry,TRUE);
KeReleaseDispatcherDatabaseLock(OldIrql);
return Result;
}
@ -117,7 +133,14 @@ LONG STDCALL
KeInsertQueue(IN PKQUEUE Queue,
IN PLIST_ENTRY Entry)
{
return KiInsertQueue(Queue,Entry,FALSE);
LONG Result;
KIRQL OldIrql;
OldIrql = KeAcquireDispatcherDatabaseLock();
Result = KiInsertQueue(Queue,Entry,FALSE);
KeReleaseDispatcherDatabaseLock(OldIrql);
return Result;
}
@ -129,6 +152,7 @@ KeRemoveQueue(IN PKQUEUE Queue,
IN KPROCESSOR_MODE WaitMode,
IN PLARGE_INTEGER Timeout OPTIONAL)
{
PLIST_ENTRY ListEntry;
NTSTATUS Status;
PKTHREAD Thread = KeGetCurrentThread();
@ -136,50 +160,75 @@ KeRemoveQueue(IN PKQUEUE Queue,
OldIrql = KeAcquireDispatcherDatabaseLock ();
//assiciate new thread with queue?
if (Thread->Queue != Queue)
{
//remove association from other queue
if (!IsListEmpty(&Thread->QueueListEntry))
/*
* INVESTIGATE: What is the Thread->QueueListEntry used for? It's linked it into the
* Queue->ThreadListHead when the thread registers with the queue and unlinked when
* the thread registers with a new queue. The Thread->Queue already tells us what
* queue the thread is registered with.
* -Gunnar
*/
//unregister thread from previous queue (if any)
if (Thread->Queue)
{
RemoveEntryList(&Thread->QueueListEntry);
Thread->Queue->CurrentCount--;
if (Thread->Queue->CurrentCount < Thread->Queue->MaximumCount &&
!IsListEmpty(&Thread->Queue->EntryListHead))
{
KiDispatcherObjectWake(&Thread->Queue->Header);
}
}
//associate with this queue
InsertHeadList(&Queue->ThreadListHead, &Thread->QueueListEntry);
Queue->CurrentCount++;
// register thread with this queue
InsertTailList(&Queue->ThreadListHead, &Thread->QueueListEntry);
Thread->Queue = Queue;
}
else /* if (Thread->Queue == Queue) */
{
//dec. num running threads
Queue->CurrentCount--;
}
if (Queue->CurrentCount <= Queue->MaximumCount && !IsListEmpty(&Queue->EntryListHead))
while (TRUE)
{
ListEntry = RemoveHeadList(&Queue->EntryListHead);
Queue->Header.SignalState--;
KeReleaseDispatcherDatabaseLock (OldIrql);
return ListEntry;
if (Queue->CurrentCount < Queue->MaximumCount && !IsListEmpty(&Queue->EntryListHead))
{
ListEntry = RemoveHeadList(&Queue->EntryListHead);
//dec. num entries in queue
Queue->Header.SignalState--;
//inc. num running threads
Queue->CurrentCount++;
KeReleaseDispatcherDatabaseLock(OldIrql);
return ListEntry;
}
else
{
//inform KeWaitXxx that we are holding disp. lock
Thread->WaitNext = TRUE;
Thread->WaitIrql = OldIrql;
Status = KeWaitForSingleObject(Queue,
WrQueue,
WaitMode,
TRUE, //bAlertable
Timeout);
if (Status == STATUS_TIMEOUT || Status == STATUS_USER_APC)
{
return (PVOID)Status;
}
OldIrql = KeAcquireDispatcherDatabaseLock ();
}
}
//need to wait for it...
KeReleaseDispatcherDatabaseLock (OldIrql);
Status = KeWaitForSingleObject(Queue,
WrQueue,
WaitMode,
TRUE,//Alertable,
Timeout);
if (Status == STATUS_TIMEOUT || Status == STATUS_USER_APC)
{
return (PVOID)Status;
}
else
{
OldIrql = KeAcquireDispatcherDatabaseLock ();
ListEntry = RemoveHeadList(&Queue->EntryListHead);
KeReleaseDispatcherDatabaseLock (OldIrql);
return ListEntry;
}
}
@ -195,23 +244,31 @@ KeRundownQueue(IN PKQUEUE Queue)
DPRINT("KeRundownQueue(Queue %x)\n", Queue);
//FIXME: should we wake thread waiting on a queue?
/* I'm just guessing how this should work:-/
* -Gunnar
*/
OldIrql = KeAcquireDispatcherDatabaseLock ();
// Clear Queue and QueueListEntry members of all threads associated with this queue
//no thread must wait on queue at rundown
ASSERT(IsListEmpty(&Queue->Header.WaitListHead));
// unlink threads and clear their Thread->Queue
while (!IsListEmpty(&Queue->ThreadListHead))
{
EnumEntry = RemoveHeadList(&Queue->ThreadListHead);
InitializeListHead(EnumEntry);
Thread = CONTAINING_RECORD(EnumEntry, KTHREAD, QueueListEntry);
Thread->Queue = NULL;
}
if (!IsListEmpty(&Queue->EntryListHead))
EnumEntry = Queue->EntryListHead.Flink;
else
if (IsListEmpty(&Queue->EntryListHead))
{
EnumEntry = NULL;
}
else
{
EnumEntry = Queue->EntryListHead.Flink;
}
KeReleaseDispatcherDatabaseLock (OldIrql);

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: sem.c,v 1.15 2004/08/15 16:39:05 chorns Exp $
/* $Id: sem.c,v 1.16 2004/11/21 18:33:54 gdalsnes Exp $
*
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ke/sem.c
@ -105,7 +105,7 @@ KeReleaseSemaphore (PKSEMAPHORE Semaphore,
Semaphore->Header.SignalState += Adjustment;
if (InitialState == 0)
{
KeDispatcherObjectWake(&Semaphore->Header);
KiDispatcherObjectWake(&Semaphore->Header);
}
if (Wait == FALSE)

View file

@ -1,4 +1,4 @@
/* $Id: timer.c,v 1.89 2004/11/21 06:51:18 ion Exp $
/* $Id: timer.c,v 1.90 2004/11/21 18:33:54 gdalsnes Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -526,11 +526,11 @@ HandleExpiredTimer(PKTIMER Timer)
DPRINT("Finished dpc routine\n");
}
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
ASSERT_IRQL_EQUAL(DISPATCH_LEVEL);
KeAcquireDispatcherDatabaseLockAtDpcLevel();
Timer->Header.SignalState = TRUE;
KeDispatcherObjectWake(&Timer->Header);
KiDispatcherObjectWake(&Timer->Header);
KeReleaseDispatcherDatabaseLockFromDpcLevel();
if (Timer->Period != 0)
@ -571,7 +571,7 @@ KeExpireTimers(PKDPC Dpc,
DPRINT("KeExpireTimers()\n");
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
ASSERT_IRQL_EQUAL(DISPATCH_LEVEL);
InitializeListHead(&TimerList);

View file

@ -110,6 +110,8 @@ KiSideEffectsBeforeWake(DISPATCHER_HEADER * hdr,
break;
case InternalQueueType:
break;
case InternalSemaphoreType:
hdr->SignalState--;
break;
@ -193,33 +195,31 @@ KiIsObjectSignalled(DISPATCHER_HEADER * hdr,
}
}
VOID KeRemoveAllWaitsThread(PETHREAD Thread, NTSTATUS WaitStatus, BOOL Unblock)
/* Must be called with the dispatcher lock held */
BOOLEAN KiAbortWaitThread(PKTHREAD Thread, NTSTATUS WaitStatus)
{
PKWAIT_BLOCK WaitBlock, PrevWaitBlock;
BOOLEAN WasWaiting = FALSE;
PKWAIT_BLOCK WaitBlock;
BOOLEAN WasWaiting;
WaitBlock = (PKWAIT_BLOCK)Thread->Tcb.WaitBlockList;
if (WaitBlock != NULL)
{
WasWaiting = TRUE;
}
while (WaitBlock != NULL)
{
if (WaitBlock->WaitListEntry.Flink != NULL && WaitBlock->WaitListEntry.Blink != NULL)
{
RemoveEntryList (&WaitBlock->WaitListEntry);
WaitBlock->WaitListEntry.Flink = WaitBlock->WaitListEntry.Blink = NULL;
}
PrevWaitBlock = WaitBlock;
WaitBlock = WaitBlock->NextWaitBlock;
PrevWaitBlock->NextWaitBlock = NULL;
}
Thread->Tcb.WaitBlockList = NULL;
/* if we are blocked, we must be waiting on something also */
ASSERT((Thread->State == THREAD_STATE_BLOCKED) == (Thread->WaitBlockList != NULL));
if (WasWaiting && Unblock)
{
PsUnblockThread(Thread, &WaitStatus);
}
WaitBlock = (PKWAIT_BLOCK)Thread->WaitBlockList;
WasWaiting = (WaitBlock != NULL);
while (WaitBlock)
{
RemoveEntryList(&WaitBlock->WaitListEntry);
WaitBlock = WaitBlock->NextWaitBlock;
}
Thread->WaitBlockList = NULL;
if (WasWaiting)
{
PsUnblockThread((PETHREAD)Thread, &WaitStatus);
}
return WasWaiting;
}
static BOOLEAN
@ -260,11 +260,7 @@ KeDispatcherObjectWakeOneOrAll(DISPATCHER_HEADER * hdr,
DPRINT("WaitAny: Remove all wait blocks.\n");
for (Waiter = WaiterHead->Thread->WaitBlockList; Waiter; Waiter = Waiter->NextWaitBlock)
{
if (Waiter->WaitListEntry.Flink != NULL && Waiter->WaitListEntry.Blink != NULL)
{
RemoveEntryList(&Waiter->WaitListEntry);
Waiter->WaitListEntry.Flink = Waiter->WaitListEntry.Blink = NULL;
}
RemoveEntryList(&Waiter->WaitListEntry);
}
WaiterHead->Thread->WaitBlockList = NULL;
@ -273,7 +269,7 @@ KeDispatcherObjectWakeOneOrAll(DISPATCHER_HEADER * hdr,
* 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;
Abandoned |= KiSideEffectsBeforeWake(hdr, WaiterHead->Thread);
}
else
{
@ -299,16 +295,11 @@ KeDispatcherObjectWakeOneOrAll(DISPATCHER_HEADER * hdr,
{
for (Waiter = WaiterHead->Thread->WaitBlockList; Waiter; Waiter = Waiter->NextWaitBlock)
{
if (Waiter->WaitListEntry.Flink != NULL && Waiter->WaitListEntry.Blink != NULL)
{
RemoveEntryList(&Waiter->WaitListEntry);
Waiter->WaitListEntry.Flink = Waiter->WaitListEntry.Blink = NULL;
}
RemoveEntryList(&Waiter->WaitListEntry);
if (Waiter->WaitType == WaitAll)
{
Abandoned = KiSideEffectsBeforeWake(Waiter->Object, Waiter->Thread)
? TRUE : Abandoned;
Abandoned |= KiSideEffectsBeforeWake(Waiter->Object, Waiter->Thread);
}
//no WaitAny objects can possibly be signaled since we are here
@ -339,7 +330,7 @@ KeDispatcherObjectWakeOneOrAll(DISPATCHER_HEADER * hdr,
}
BOOLEAN KeDispatcherObjectWake(DISPATCHER_HEADER* hdr)
BOOLEAN KiDispatcherObjectWake(DISPATCHER_HEADER* hdr)
/*
* FUNCTION: Wake threads waiting on a dispatcher object
* NOTE: The exact semantics of waking are dependant on the type of object
@ -366,6 +357,8 @@ BOOLEAN KeDispatcherObjectWake(DISPATCHER_HEADER* hdr)
return(KeDispatcherObjectWakeOne(hdr));
case InternalQueueType:
return(KeDispatcherObjectWakeOne(hdr));
case InternalSemaphoreType:
DPRINT("hdr->SignalState %d\n", hdr->SignalState);
if(hdr->SignalState>0)
@ -483,7 +476,6 @@ KeWaitForMultipleObjects(ULONG Count,
ULONG CountSignaled;
ULONG i;
NTSTATUS Status;
KIRQL WaitIrql;
KIRQL OldIrql;
BOOLEAN Abandoned;
@ -493,7 +485,6 @@ KeWaitForMultipleObjects(ULONG Count,
ASSERT(0 < Count && Count <= EX_MAXIMUM_WAIT_OBJECTS);
CurrentThread = KeGetCurrentThread();
WaitIrql = KeGetCurrentIrql();
/*
* Work out where we are going to put the wait blocks
@ -516,6 +507,8 @@ KeWaitForMultipleObjects(ULONG Count,
}
}
/*
* Set up the timeout if required
*/
@ -528,9 +521,8 @@ KeWaitForMultipleObjects(ULONG Count,
{
if (CurrentThread->WaitNext)
{
CurrentThread->WaitNext = FALSE;
OldIrql = CurrentThread->WaitIrql;
CurrentThread->WaitNext = 0;
CurrentThread->WaitIrql = PASSIVE_LEVEL;
}
else
{
@ -711,28 +703,33 @@ KeWaitForMultipleObjects(ULONG Count,
&CurrentThread->WaitBlock[3].WaitListEntry);
}
//io completion
if (CurrentThread->Queue)
//kernel queues
if (CurrentThread->Queue && WaitReason != WrQueue)
{
CurrentThread->Queue->CurrentCount--;
if (WaitReason != WrQueue && CurrentThread->Queue->CurrentCount < CurrentThread->Queue->MaximumCount &&
DPRINT("queue: sleep on something else\n");
CurrentThread->Queue->CurrentCount--;
//wake another thread
if (CurrentThread->Queue->CurrentCount < CurrentThread->Queue->MaximumCount &&
!IsListEmpty(&CurrentThread->Queue->EntryListHead))
{
KeDispatcherObjectWake(&CurrentThread->Queue->Header);
KiDispatcherObjectWake(&CurrentThread->Queue->Header);
}
}
PsBlockThread(&Status, Alertable, WaitMode, TRUE, WaitIrql, (UCHAR)WaitReason);
PsBlockThread(&Status, Alertable, WaitMode, TRUE, OldIrql, (UCHAR)WaitReason);
//io completion
if (CurrentThread->Queue)
//kernel queues
//FIXME: dispatcher lock not held here!
if (CurrentThread->Queue && WaitReason != WrQueue)
{
DPRINT("queue: wake from something else\n");
CurrentThread->Queue->CurrentCount++;
}
}
while (Status == STATUS_KERNEL_APC);
} while (Status == STATUS_KERNEL_APC);
if (Timeout != NULL)
{