mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 01:55:19 +00:00
fix kernel queues + misc fixes/cleanups
svn path=/trunk/; revision=11754
This commit is contained in:
parent
0f6f4de9e1
commit
0c5a9ba4f5
8 changed files with 222 additions and 136 deletions
|
@ -124,7 +124,7 @@ KeInsertQueueApc (PKAPC Apc,
|
||||||
PLIST_ENTRY ApcListEntry;
|
PLIST_ENTRY ApcListEntry;
|
||||||
PKAPC QueuedApc;
|
PKAPC QueuedApc;
|
||||||
|
|
||||||
ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
|
ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
|
||||||
DPRINT ("KeInsertQueueApc(Apc %x, SystemArgument1 %x, "
|
DPRINT ("KeInsertQueueApc(Apc %x, SystemArgument1 %x, "
|
||||||
"SystemArgument2 %x)\n",Apc,SystemArgument1,
|
"SystemArgument2 %x)\n",Apc,SystemArgument1,
|
||||||
SystemArgument2);
|
SystemArgument2);
|
||||||
|
@ -134,7 +134,9 @@ KeInsertQueueApc (PKAPC Apc,
|
||||||
/* Get the Thread specified in the APC */
|
/* Get the Thread specified in the APC */
|
||||||
Thread = Apc->Thread;
|
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) {
|
if (Thread->ApcQueueable == FALSE) {
|
||||||
DPRINT("Thread doesn't allow APC Queues\n");
|
DPRINT("Thread doesn't allow APC Queues\n");
|
||||||
KeReleaseDispatcherDatabaseLock(OldIrql);
|
KeReleaseDispatcherDatabaseLock(OldIrql);
|
||||||
|
@ -194,18 +196,20 @@ KeInsertQueueApc (PKAPC Apc,
|
||||||
/* FIXME: Use IPI */
|
/* FIXME: Use IPI */
|
||||||
DPRINT ("Requesting APC Interrupt for Running Thread \n");
|
DPRINT ("Requesting APC Interrupt for Running Thread \n");
|
||||||
HalRequestSoftwareInterrupt(APC_LEVEL);
|
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");
|
DPRINT ("Waking up Thread for Kernel-Mode APC Delivery \n");
|
||||||
KeRemoveAllWaitsThread(CONTAINING_RECORD(Thread, ETHREAD, Tcb),
|
KiAbortWaitThread(Thread, STATUS_KERNEL_APC);
|
||||||
STATUS_KERNEL_APC,
|
|
||||||
TRUE);
|
|
||||||
}
|
}
|
||||||
} 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");
|
DPRINT ("Waking up Thread for User-Mode APC Delivery \n");
|
||||||
Thread->ApcState.UserApcPending = TRUE;
|
Thread->ApcState.UserApcPending = TRUE;
|
||||||
KeRemoveAllWaitsThread(CONTAINING_RECORD(Thread, ETHREAD, Tcb),
|
KiAbortWaitThread(Thread, STATUS_USER_APC);
|
||||||
STATUS_USER_APC,
|
|
||||||
TRUE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return Sucess if we are here */
|
/* Return Sucess if we are here */
|
||||||
|
@ -227,7 +231,7 @@ KeRemoveQueueApc (PKAPC Apc)
|
||||||
KIRQL OldIrql;
|
KIRQL OldIrql;
|
||||||
PKTHREAD Thread = Apc->Thread;
|
PKTHREAD Thread = Apc->Thread;
|
||||||
|
|
||||||
ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
|
ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
|
||||||
DPRINT("KeRemoveQueueApc called for APC: %x \n", Apc);
|
DPRINT("KeRemoveQueueApc called for APC: %x \n", Apc);
|
||||||
|
|
||||||
OldIrql = KeAcquireDispatcherDatabaseLock();
|
OldIrql = KeAcquireDispatcherDatabaseLock();
|
||||||
|
@ -270,7 +274,7 @@ KeTestAlertThread(IN KPROCESSOR_MODE AlertMode)
|
||||||
PKTHREAD Thread = KeGetCurrentThread();
|
PKTHREAD Thread = KeGetCurrentThread();
|
||||||
BOOLEAN OldState;
|
BOOLEAN OldState;
|
||||||
|
|
||||||
ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
|
ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
|
||||||
|
|
||||||
OldIrql = KeAcquireDispatcherDatabaseLock();
|
OldIrql = KeAcquireDispatcherDatabaseLock();
|
||||||
KiAcquireSpinLock(&Thread->ApcQueueLock);
|
KiAcquireSpinLock(&Thread->ApcQueueLock);
|
||||||
|
@ -295,7 +299,7 @@ KeTestAlertThread(IN KPROCESSOR_MODE AlertMode)
|
||||||
*/
|
*/
|
||||||
VOID
|
VOID
|
||||||
STDCALL
|
STDCALL
|
||||||
KiDeliverApc(KPROCESSOR_MODE PreviousMode,
|
KiDeliverApc(KPROCESSOR_MODE DeliveryMode,
|
||||||
PVOID Reserved,
|
PVOID Reserved,
|
||||||
PKTRAP_FRAME TrapFrame)
|
PKTRAP_FRAME TrapFrame)
|
||||||
/*
|
/*
|
||||||
|
@ -317,6 +321,8 @@ KiDeliverApc(KPROCESSOR_MODE PreviousMode,
|
||||||
PKNORMAL_ROUTINE NormalRoutine;
|
PKNORMAL_ROUTINE NormalRoutine;
|
||||||
PVOID SystemArgument1;
|
PVOID SystemArgument1;
|
||||||
PVOID SystemArgument2;
|
PVOID SystemArgument2;
|
||||||
|
|
||||||
|
ASSERT_IRQL_EQUAL(APC_LEVEL);
|
||||||
|
|
||||||
/* Lock the APC Queue and Raise IRQL to Synch */
|
/* Lock the APC Queue and Raise IRQL to Synch */
|
||||||
KeAcquireSpinLock(&Thread->ApcQueueLock, &OldIrql);
|
KeAcquireSpinLock(&Thread->ApcQueueLock, &OldIrql);
|
||||||
|
@ -339,7 +345,7 @@ KiDeliverApc(KPROCESSOR_MODE PreviousMode,
|
||||||
SystemArgument2 = Apc->SystemArgument2;
|
SystemArgument2 = Apc->SystemArgument2;
|
||||||
|
|
||||||
/* Special APC */
|
/* Special APC */
|
||||||
if (NormalRoutine == NULL) {
|
if (NormalRoutine == NULL) {
|
||||||
/* Remove the APC from the list */
|
/* Remove the APC from the list */
|
||||||
Apc->Inserted = FALSE;
|
Apc->Inserted = FALSE;
|
||||||
RemoveEntryList(ApcListEntry);
|
RemoveEntryList(ApcListEntry);
|
||||||
|
@ -360,6 +366,15 @@ KiDeliverApc(KPROCESSOR_MODE PreviousMode,
|
||||||
} else {
|
} else {
|
||||||
/* Normal Kernel APC */
|
/* Normal Kernel APC */
|
||||||
if (Thread->ApcState.KernelApcInProgress || Thread->KernelApcDisable) {
|
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);
|
KeReleaseSpinLock(&Thread->ApcQueueLock, OldIrql);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -399,7 +414,7 @@ KiDeliverApc(KPROCESSOR_MODE PreviousMode,
|
||||||
|
|
||||||
/* Now we do the User APCs */
|
/* Now we do the User APCs */
|
||||||
if ((!IsListEmpty(&Thread->ApcState.ApcListHead[UserMode])) &&
|
if ((!IsListEmpty(&Thread->ApcState.ApcListHead[UserMode])) &&
|
||||||
(PreviousMode == UserMode) &&
|
(DeliveryMode == UserMode) &&
|
||||||
(Thread->ApcState.UserApcPending == TRUE)) {
|
(Thread->ApcState.UserApcPending == TRUE)) {
|
||||||
|
|
||||||
/* It's not pending anymore */
|
/* It's not pending anymore */
|
||||||
|
@ -418,6 +433,8 @@ KiDeliverApc(KPROCESSOR_MODE PreviousMode,
|
||||||
|
|
||||||
/* Remove the APC from Queue, restore IRQL and call the APC */
|
/* Remove the APC from Queue, restore IRQL and call the APC */
|
||||||
RemoveEntryList(ApcListEntry);
|
RemoveEntryList(ApcListEntry);
|
||||||
|
Apc->Inserted = FALSE;
|
||||||
|
|
||||||
KeReleaseSpinLock(&Thread->ApcQueueLock, OldIrql);
|
KeReleaseSpinLock(&Thread->ApcQueueLock, OldIrql);
|
||||||
DPRINT("Calling the Kernel Routine for for a User APC: %x\n", Apc);
|
DPRINT("Calling the Kernel Routine for for a User APC: %x\n", Apc);
|
||||||
KernelRoutine(Apc,
|
KernelRoutine(Apc,
|
||||||
|
|
|
@ -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
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
|
@ -22,8 +22,13 @@
|
||||||
*/
|
*/
|
||||||
VOID STDCALL KeEnterCriticalRegion (VOID)
|
VOID STDCALL KeEnterCriticalRegion (VOID)
|
||||||
{
|
{
|
||||||
|
PKTHREAD Thread = KeGetCurrentThread();
|
||||||
|
|
||||||
DPRINT("KeEnterCriticalRegion()\n");
|
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();
|
PKTHREAD Thread = KeGetCurrentThread();
|
||||||
|
|
||||||
DPRINT("KeLeaveCriticalRegion()\n");
|
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 */
|
/* Reference: http://www.ntfsd.org/archive/ntfsd0104/msg0203.html */
|
||||||
if(++Thread->KernelApcDisable == 0)
|
if(++Thread->KernelApcDisable == 0)
|
||||||
|
|
|
@ -67,6 +67,9 @@ LONG STDCALL KeReadStateEvent (PKEVENT Event)
|
||||||
*/
|
*/
|
||||||
LONG STDCALL KeResetEvent (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));
|
return(InterlockedExchange(&(Event->Header.SignalState),0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,7 +89,7 @@ LONG STDCALL KeSetEvent (PKEVENT Event,
|
||||||
|
|
||||||
ret = InterlockedExchange(&(Event->Header.SignalState),1);
|
ret = InterlockedExchange(&(Event->Header.SignalState),1);
|
||||||
|
|
||||||
KeDispatcherObjectWake((DISPATCHER_HEADER *)Event);
|
KiDispatcherObjectWake((DISPATCHER_HEADER *)Event);
|
||||||
|
|
||||||
if (Wait == FALSE)
|
if (Wait == FALSE)
|
||||||
{
|
{
|
||||||
|
@ -115,7 +118,7 @@ NTSTATUS STDCALL KePulseEvent (PKEVENT Event,
|
||||||
DPRINT("KePulseEvent(Event %x, Wait %x)\n",Event,Wait);
|
DPRINT("KePulseEvent(Event %x, Wait %x)\n",Event,Wait);
|
||||||
OldIrql = KeAcquireDispatcherDatabaseLock();
|
OldIrql = KeAcquireDispatcherDatabaseLock();
|
||||||
ret = InterlockedExchange(&(Event->Header.SignalState),1);
|
ret = InterlockedExchange(&(Event->Header.SignalState),1);
|
||||||
KeDispatcherObjectWake((DISPATCHER_HEADER *)Event);
|
KiDispatcherObjectWake((DISPATCHER_HEADER *)Event);
|
||||||
InterlockedExchange(&(Event->Header.SignalState),0);
|
InterlockedExchange(&(Event->Header.SignalState),0);
|
||||||
|
|
||||||
if (Wait == FALSE)
|
if (Wait == FALSE)
|
||||||
|
@ -143,7 +146,10 @@ KeSetEventBoostPriority(
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
PKTHREAD WaitingThread;
|
PKTHREAD WaitingThread;
|
||||||
|
KIRQL OldIrql;
|
||||||
|
|
||||||
|
OldIrql = KeAcquireDispatcherDatabaseLock();
|
||||||
|
|
||||||
/* Get Thread that is currently waiting. First get the Wait Block, then the Thread */
|
/* 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;
|
WaitingThread = CONTAINING_RECORD(Event->Header.WaitListHead.Flink, KWAIT_BLOCK, WaitListEntry)->Thread;
|
||||||
|
|
||||||
|
@ -152,7 +158,9 @@ KeSetEventBoostPriority(
|
||||||
|
|
||||||
/* Reset the Quantum and Unwait the Thread */
|
/* Reset the Quantum and Unwait the Thread */
|
||||||
WaitingThread->Quantum = WaitingThread->ApcState.Process->ThreadQuantum;
|
WaitingThread->Quantum = WaitingThread->ApcState.Process->ThreadQuantum;
|
||||||
KeRemoveAllWaitsThread((PETHREAD)WaitingThread, STATUS_SUCCESS, TRUE);
|
KiAbortWaitThread(WaitingThread, STATUS_SUCCESS);
|
||||||
|
|
||||||
|
KeReleaseDispatcherDatabaseLock(OldIrql);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* 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
|
* PROJECT: ReactOS kernel
|
||||||
* FILE: ntoskrnl/ke/mutex.c
|
* FILE: ntoskrnl/ke/mutex.c
|
||||||
|
@ -82,7 +82,7 @@ KeReleaseMutex(IN PKMUTEX Mutex,
|
||||||
Mutex->OwnerThread = NULL;
|
Mutex->OwnerThread = NULL;
|
||||||
if (Mutex->MutantListEntry.Flink && Mutex->MutantListEntry.Blink)
|
if (Mutex->MutantListEntry.Flink && Mutex->MutantListEntry.Blink)
|
||||||
RemoveEntryList(&Mutex->MutantListEntry);
|
RemoveEntryList(&Mutex->MutantListEntry);
|
||||||
KeDispatcherObjectWake(&Mutex->Header);
|
KiDispatcherObjectWake(&Mutex->Header);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Wait == FALSE)
|
if (Wait == FALSE)
|
||||||
|
@ -191,7 +191,7 @@ KeReleaseMutant(IN PKMUTANT Mutant,
|
||||||
Mutant->OwnerThread = NULL;
|
Mutant->OwnerThread = NULL;
|
||||||
if (Mutant->MutantListEntry.Flink && Mutant->MutantListEntry.Blink)
|
if (Mutant->MutantListEntry.Flink && Mutant->MutantListEntry.Blink)
|
||||||
RemoveEntryList(&Mutant->MutantListEntry);
|
RemoveEntryList(&Mutant->MutantListEntry);
|
||||||
KeDispatcherObjectWake(&Mutant->Header);
|
KiDispatcherObjectWake(&Mutant->Header);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Wait == FALSE)
|
if (Wait == FALSE)
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* 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
|
* PROJECT: ReactOS kernel
|
||||||
* FILE: ntoskrnl/ke/queue.c
|
* FILE: ntoskrnl/ke/queue.c
|
||||||
|
@ -34,6 +34,7 @@
|
||||||
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
|
@ -54,6 +55,8 @@ KeInitializeQueue(IN PKQUEUE Queue,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
|
*
|
||||||
|
* Returns number of entries in the queue
|
||||||
*/
|
*/
|
||||||
LONG STDCALL
|
LONG STDCALL
|
||||||
KeReadStateQueue(IN PKQUEUE Queue)
|
KeReadStateQueue(IN PKQUEUE Queue)
|
||||||
|
@ -61,7 +64,9 @@ KeReadStateQueue(IN PKQUEUE Queue)
|
||||||
return(Queue->Header.SignalState);
|
return(Queue->Header.SignalState);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns the previous number of entries in the queue
|
||||||
|
*/
|
||||||
LONG STDCALL
|
LONG STDCALL
|
||||||
KiInsertQueue(
|
KiInsertQueue(
|
||||||
IN PKQUEUE Queue,
|
IN PKQUEUE Queue,
|
||||||
|
@ -70,15 +75,11 @@ KiInsertQueue(
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
ULONG InitialState;
|
ULONG InitialState;
|
||||||
KIRQL OldIrql;
|
|
||||||
|
|
||||||
DPRINT("KiInsertQueue(Queue %x, Entry %x)\n", Queue, Entry);
|
DPRINT("KiInsertQueue(Queue %x, Entry %x)\n", Queue, Entry);
|
||||||
|
|
||||||
OldIrql = KeAcquireDispatcherDatabaseLock ();
|
|
||||||
|
|
||||||
InitialState = Queue->Header.SignalState;
|
InitialState = Queue->Header.SignalState;
|
||||||
Queue->Header.SignalState++;
|
|
||||||
|
|
||||||
if (Head)
|
if (Head)
|
||||||
{
|
{
|
||||||
InsertHeadList(&Queue->EntryListHead, Entry);
|
InsertHeadList(&Queue->EntryListHead, Entry);
|
||||||
|
@ -87,13 +88,21 @@ KiInsertQueue(
|
||||||
{
|
{
|
||||||
InsertTailList(&Queue->EntryListHead, Entry);
|
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;
|
return InitialState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,7 +115,14 @@ LONG STDCALL
|
||||||
KeInsertHeadQueue(IN PKQUEUE Queue,
|
KeInsertHeadQueue(IN PKQUEUE Queue,
|
||||||
IN PLIST_ENTRY Entry)
|
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,
|
KeInsertQueue(IN PKQUEUE Queue,
|
||||||
IN PLIST_ENTRY Entry)
|
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 KPROCESSOR_MODE WaitMode,
|
||||||
IN PLARGE_INTEGER Timeout OPTIONAL)
|
IN PLARGE_INTEGER Timeout OPTIONAL)
|
||||||
{
|
{
|
||||||
|
|
||||||
PLIST_ENTRY ListEntry;
|
PLIST_ENTRY ListEntry;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
PKTHREAD Thread = KeGetCurrentThread();
|
PKTHREAD Thread = KeGetCurrentThread();
|
||||||
|
@ -136,50 +160,75 @@ KeRemoveQueue(IN PKQUEUE Queue,
|
||||||
|
|
||||||
OldIrql = KeAcquireDispatcherDatabaseLock ();
|
OldIrql = KeAcquireDispatcherDatabaseLock ();
|
||||||
|
|
||||||
//assiciate new thread with queue?
|
|
||||||
if (Thread->Queue != 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);
|
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
|
// register thread with this queue
|
||||||
InsertHeadList(&Queue->ThreadListHead, &Thread->QueueListEntry);
|
InsertTailList(&Queue->ThreadListHead, &Thread->QueueListEntry);
|
||||||
Queue->CurrentCount++;
|
|
||||||
Thread->Queue = Queue;
|
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);
|
if (Queue->CurrentCount < Queue->MaximumCount && !IsListEmpty(&Queue->EntryListHead))
|
||||||
Queue->Header.SignalState--;
|
{
|
||||||
KeReleaseDispatcherDatabaseLock (OldIrql);
|
ListEntry = RemoveHeadList(&Queue->EntryListHead);
|
||||||
return ListEntry;
|
//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);
|
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 ();
|
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))
|
while (!IsListEmpty(&Queue->ThreadListHead))
|
||||||
{
|
{
|
||||||
EnumEntry = RemoveHeadList(&Queue->ThreadListHead);
|
EnumEntry = RemoveHeadList(&Queue->ThreadListHead);
|
||||||
InitializeListHead(EnumEntry);
|
|
||||||
Thread = CONTAINING_RECORD(EnumEntry, KTHREAD, QueueListEntry);
|
Thread = CONTAINING_RECORD(EnumEntry, KTHREAD, QueueListEntry);
|
||||||
Thread->Queue = NULL;
|
Thread->Queue = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IsListEmpty(&Queue->EntryListHead))
|
if (IsListEmpty(&Queue->EntryListHead))
|
||||||
EnumEntry = Queue->EntryListHead.Flink;
|
{
|
||||||
else
|
|
||||||
EnumEntry = NULL;
|
EnumEntry = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
EnumEntry = Queue->EntryListHead.Flink;
|
||||||
|
}
|
||||||
|
|
||||||
KeReleaseDispatcherDatabaseLock (OldIrql);
|
KeReleaseDispatcherDatabaseLock (OldIrql);
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* 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
|
* PROJECT: ReactOS kernel
|
||||||
* FILE: ntoskrnl/ke/sem.c
|
* FILE: ntoskrnl/ke/sem.c
|
||||||
|
@ -105,7 +105,7 @@ KeReleaseSemaphore (PKSEMAPHORE Semaphore,
|
||||||
Semaphore->Header.SignalState += Adjustment;
|
Semaphore->Header.SignalState += Adjustment;
|
||||||
if (InitialState == 0)
|
if (InitialState == 0)
|
||||||
{
|
{
|
||||||
KeDispatcherObjectWake(&Semaphore->Header);
|
KiDispatcherObjectWake(&Semaphore->Header);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Wait == FALSE)
|
if (Wait == FALSE)
|
||||||
|
|
|
@ -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
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
|
@ -526,11 +526,11 @@ HandleExpiredTimer(PKTIMER Timer)
|
||||||
DPRINT("Finished dpc routine\n");
|
DPRINT("Finished dpc routine\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
|
ASSERT_IRQL_EQUAL(DISPATCH_LEVEL);
|
||||||
|
|
||||||
KeAcquireDispatcherDatabaseLockAtDpcLevel();
|
KeAcquireDispatcherDatabaseLockAtDpcLevel();
|
||||||
Timer->Header.SignalState = TRUE;
|
Timer->Header.SignalState = TRUE;
|
||||||
KeDispatcherObjectWake(&Timer->Header);
|
KiDispatcherObjectWake(&Timer->Header);
|
||||||
KeReleaseDispatcherDatabaseLockFromDpcLevel();
|
KeReleaseDispatcherDatabaseLockFromDpcLevel();
|
||||||
|
|
||||||
if (Timer->Period != 0)
|
if (Timer->Period != 0)
|
||||||
|
@ -571,7 +571,7 @@ KeExpireTimers(PKDPC Dpc,
|
||||||
|
|
||||||
DPRINT("KeExpireTimers()\n");
|
DPRINT("KeExpireTimers()\n");
|
||||||
|
|
||||||
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
|
ASSERT_IRQL_EQUAL(DISPATCH_LEVEL);
|
||||||
|
|
||||||
InitializeListHead(&TimerList);
|
InitializeListHead(&TimerList);
|
||||||
|
|
||||||
|
|
|
@ -110,6 +110,8 @@ KiSideEffectsBeforeWake(DISPATCHER_HEADER * hdr,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case InternalQueueType:
|
case InternalQueueType:
|
||||||
|
break;
|
||||||
|
|
||||||
case InternalSemaphoreType:
|
case InternalSemaphoreType:
|
||||||
hdr->SignalState--;
|
hdr->SignalState--;
|
||||||
break;
|
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;
|
PKWAIT_BLOCK WaitBlock;
|
||||||
BOOLEAN WasWaiting = FALSE;
|
BOOLEAN WasWaiting;
|
||||||
|
|
||||||
WaitBlock = (PKWAIT_BLOCK)Thread->Tcb.WaitBlockList;
|
/* if we are blocked, we must be waiting on something also */
|
||||||
if (WaitBlock != NULL)
|
ASSERT((Thread->State == THREAD_STATE_BLOCKED) == (Thread->WaitBlockList != 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 (WasWaiting && Unblock)
|
WaitBlock = (PKWAIT_BLOCK)Thread->WaitBlockList;
|
||||||
{
|
WasWaiting = (WaitBlock != NULL);
|
||||||
PsUnblockThread(Thread, &WaitStatus);
|
|
||||||
}
|
while (WaitBlock)
|
||||||
|
{
|
||||||
|
RemoveEntryList(&WaitBlock->WaitListEntry);
|
||||||
|
WaitBlock = WaitBlock->NextWaitBlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
Thread->WaitBlockList = NULL;
|
||||||
|
|
||||||
|
if (WasWaiting)
|
||||||
|
{
|
||||||
|
PsUnblockThread((PETHREAD)Thread, &WaitStatus);
|
||||||
|
}
|
||||||
|
return WasWaiting;
|
||||||
}
|
}
|
||||||
|
|
||||||
static BOOLEAN
|
static BOOLEAN
|
||||||
|
@ -260,11 +260,7 @@ KeDispatcherObjectWakeOneOrAll(DISPATCHER_HEADER * hdr,
|
||||||
DPRINT("WaitAny: Remove all wait blocks.\n");
|
DPRINT("WaitAny: Remove all wait blocks.\n");
|
||||||
for (Waiter = WaiterHead->Thread->WaitBlockList; Waiter; Waiter = Waiter->NextWaitBlock)
|
for (Waiter = WaiterHead->Thread->WaitBlockList; Waiter; Waiter = Waiter->NextWaitBlock)
|
||||||
{
|
{
|
||||||
if (Waiter->WaitListEntry.Flink != NULL && Waiter->WaitListEntry.Blink != NULL)
|
RemoveEntryList(&Waiter->WaitListEntry);
|
||||||
{
|
|
||||||
RemoveEntryList(&Waiter->WaitListEntry);
|
|
||||||
Waiter->WaitListEntry.Flink = Waiter->WaitListEntry.Blink = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
WaiterHead->Thread->WaitBlockList = NULL;
|
WaiterHead->Thread->WaitBlockList = NULL;
|
||||||
|
@ -273,7 +269,7 @@ KeDispatcherObjectWakeOneOrAll(DISPATCHER_HEADER * hdr,
|
||||||
* If a WakeAll KiSideEffectsBeforeWake(hdr,.. will be called several times,
|
* If a WakeAll KiSideEffectsBeforeWake(hdr,.. will be called several times,
|
||||||
* but thats ok since WakeAll objects has no sideeffects.
|
* but thats ok since WakeAll objects has no sideeffects.
|
||||||
*/
|
*/
|
||||||
Abandoned = KiSideEffectsBeforeWake(hdr, WaiterHead->Thread) ? TRUE : Abandoned;
|
Abandoned |= KiSideEffectsBeforeWake(hdr, WaiterHead->Thread);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -299,16 +295,11 @@ KeDispatcherObjectWakeOneOrAll(DISPATCHER_HEADER * hdr,
|
||||||
{
|
{
|
||||||
for (Waiter = WaiterHead->Thread->WaitBlockList; Waiter; Waiter = Waiter->NextWaitBlock)
|
for (Waiter = WaiterHead->Thread->WaitBlockList; Waiter; Waiter = Waiter->NextWaitBlock)
|
||||||
{
|
{
|
||||||
if (Waiter->WaitListEntry.Flink != NULL && Waiter->WaitListEntry.Blink != NULL)
|
RemoveEntryList(&Waiter->WaitListEntry);
|
||||||
{
|
|
||||||
RemoveEntryList(&Waiter->WaitListEntry);
|
|
||||||
Waiter->WaitListEntry.Flink = Waiter->WaitListEntry.Blink = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Waiter->WaitType == WaitAll)
|
if (Waiter->WaitType == WaitAll)
|
||||||
{
|
{
|
||||||
Abandoned = KiSideEffectsBeforeWake(Waiter->Object, Waiter->Thread)
|
Abandoned |= KiSideEffectsBeforeWake(Waiter->Object, Waiter->Thread);
|
||||||
? TRUE : Abandoned;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//no WaitAny objects can possibly be signaled since we are here
|
//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
|
* FUNCTION: Wake threads waiting on a dispatcher object
|
||||||
* NOTE: The exact semantics of waking are dependant on the type of 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));
|
return(KeDispatcherObjectWakeOne(hdr));
|
||||||
|
|
||||||
case InternalQueueType:
|
case InternalQueueType:
|
||||||
|
return(KeDispatcherObjectWakeOne(hdr));
|
||||||
|
|
||||||
case InternalSemaphoreType:
|
case InternalSemaphoreType:
|
||||||
DPRINT("hdr->SignalState %d\n", hdr->SignalState);
|
DPRINT("hdr->SignalState %d\n", hdr->SignalState);
|
||||||
if(hdr->SignalState>0)
|
if(hdr->SignalState>0)
|
||||||
|
@ -483,7 +476,6 @@ KeWaitForMultipleObjects(ULONG Count,
|
||||||
ULONG CountSignaled;
|
ULONG CountSignaled;
|
||||||
ULONG i;
|
ULONG i;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
KIRQL WaitIrql;
|
|
||||||
KIRQL OldIrql;
|
KIRQL OldIrql;
|
||||||
BOOLEAN Abandoned;
|
BOOLEAN Abandoned;
|
||||||
|
|
||||||
|
@ -493,7 +485,6 @@ KeWaitForMultipleObjects(ULONG Count,
|
||||||
ASSERT(0 < Count && Count <= EX_MAXIMUM_WAIT_OBJECTS);
|
ASSERT(0 < Count && Count <= EX_MAXIMUM_WAIT_OBJECTS);
|
||||||
|
|
||||||
CurrentThread = KeGetCurrentThread();
|
CurrentThread = KeGetCurrentThread();
|
||||||
WaitIrql = KeGetCurrentIrql();
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Work out where we are going to put the wait blocks
|
* Work out where we are going to put the wait blocks
|
||||||
|
@ -516,6 +507,8 @@ KeWaitForMultipleObjects(ULONG Count,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set up the timeout if required
|
* Set up the timeout if required
|
||||||
*/
|
*/
|
||||||
|
@ -528,9 +521,8 @@ KeWaitForMultipleObjects(ULONG Count,
|
||||||
{
|
{
|
||||||
if (CurrentThread->WaitNext)
|
if (CurrentThread->WaitNext)
|
||||||
{
|
{
|
||||||
|
CurrentThread->WaitNext = FALSE;
|
||||||
OldIrql = CurrentThread->WaitIrql;
|
OldIrql = CurrentThread->WaitIrql;
|
||||||
CurrentThread->WaitNext = 0;
|
|
||||||
CurrentThread->WaitIrql = PASSIVE_LEVEL;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -711,28 +703,33 @@ KeWaitForMultipleObjects(ULONG Count,
|
||||||
&CurrentThread->WaitBlock[3].WaitListEntry);
|
&CurrentThread->WaitBlock[3].WaitListEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
//io completion
|
//kernel queues
|
||||||
if (CurrentThread->Queue)
|
if (CurrentThread->Queue && WaitReason != WrQueue)
|
||||||
{
|
{
|
||||||
CurrentThread->Queue->CurrentCount--;
|
DPRINT("queue: sleep on something else\n");
|
||||||
if (WaitReason != WrQueue && CurrentThread->Queue->CurrentCount < CurrentThread->Queue->MaximumCount &&
|
CurrentThread->Queue->CurrentCount--;
|
||||||
|
|
||||||
|
//wake another thread
|
||||||
|
if (CurrentThread->Queue->CurrentCount < CurrentThread->Queue->MaximumCount &&
|
||||||
!IsListEmpty(&CurrentThread->Queue->EntryListHead))
|
!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
|
//kernel queues
|
||||||
if (CurrentThread->Queue)
|
//FIXME: dispatcher lock not held here!
|
||||||
|
if (CurrentThread->Queue && WaitReason != WrQueue)
|
||||||
{
|
{
|
||||||
|
DPRINT("queue: wake from something else\n");
|
||||||
CurrentThread->Queue->CurrentCount++;
|
CurrentThread->Queue->CurrentCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
} while (Status == STATUS_KERNEL_APC);
|
||||||
while (Status == STATUS_KERNEL_APC);
|
|
||||||
|
|
||||||
if (Timeout != NULL)
|
if (Timeout != NULL)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue