- Invert CONFIG_SMP defines as requested by Hartmut

- Remove KiBlockThread and replace by more elegant KiSwapThread which will also make moving to the new scheduler easier.
- Handle special case where we have kernel apcs pending and your previous irql was below apc_level during the wait code.
- Remove hack to manually unwait a thread during a status of kernel apc.

svn path=/trunk/; revision=20605
This commit is contained in:
Alex Ionescu 2006-01-06 08:00:09 +00:00
parent afc39c0267
commit 92f9f2e23b
5 changed files with 123 additions and 92 deletions

View file

@ -48,13 +48,7 @@ extern ULONG_PTR KERNEL_BASE;
* On UP machines, we don't actually have a spinlock, we merely raise * On UP machines, we don't actually have a spinlock, we merely raise
* IRQL to DPC level. * IRQL to DPC level.
*/ */
#ifndef CONFIG_SMP #ifdef CONFIG_SMP
#define KeInitializeDispatcher()
#define KeAcquireDispatcherDatabaseLock() KeRaiseIrqlToDpcLevel();
#define KeReleaseDispatcherDatabaseLock(OldIrql) KiExitDispatcher(OldIrql);
#define KeAcquireDispatcherDatabaseLockAtDpcLevel()
#define KeReleaseDispatcherDatabaseLockFromDpcLevel()
#else
#define KeInitializeDispatcher() KeInitializeSpinLock(&DispatcherDatabaseLock); #define KeInitializeDispatcher() KeInitializeSpinLock(&DispatcherDatabaseLock);
#define KeAcquireDispatcherDatabaseLock() KfAcquireSpinLock(&DispatcherDatabaseLock); #define KeAcquireDispatcherDatabaseLock() KfAcquireSpinLock(&DispatcherDatabaseLock);
#define KeAcquireDispatcherDatabaseLockAtDpcLevel() \ #define KeAcquireDispatcherDatabaseLockAtDpcLevel() \
@ -64,6 +58,12 @@ extern ULONG_PTR KERNEL_BASE;
#define KeReleaseDispatcherDatabaseLock(OldIrql) \ #define KeReleaseDispatcherDatabaseLock(OldIrql) \
KeReleaseSpinLockFromDpcLevel(&DispatcherDatabaseLock); \ KeReleaseSpinLockFromDpcLevel(&DispatcherDatabaseLock); \
KiExitDispatcher(OldIrql); KiExitDispatcher(OldIrql);
#else
#define KeInitializeDispatcher()
#define KeAcquireDispatcherDatabaseLock() KeRaiseIrqlToDpcLevel();
#define KeReleaseDispatcherDatabaseLock(OldIrql) KiExitDispatcher(OldIrql);
#define KeAcquireDispatcherDatabaseLockAtDpcLevel()
#define KeReleaseDispatcherDatabaseLockFromDpcLevel()
#endif #endif
/* The following macro initializes a dispatcher object's header */ /* The following macro initializes a dispatcher object's header */
@ -232,14 +232,11 @@ VOID
STDCALL STDCALL
KiDispatchThread(ULONG NewThreadStatus); KiDispatchThread(ULONG NewThreadStatus);
/* Puts a Thread into a block state. */ /* Finds a new thread to run */
VOID NTSTATUS
STDCALL NTAPI
KiBlockThread( KiSwapThread(
PNTSTATUS Status, VOID
UCHAR Alertable,
ULONG WaitMode,
UCHAR WaitReason
); );
/* Removes a thread out of a block state. */ /* Removes a thread out of a block state. */

View file

@ -78,12 +78,15 @@ KeWaitForGate(PKGATE Gate,
KiWakeQueue(CurrentThread->Queue); KiWakeQueue(CurrentThread->Queue);
} }
/* Block the Thread */ /* Setup the wait information */
DPRINT("Blocking the Thread: %x\n", CurrentThread); CurrentThread->WaitMode = WaitMode;
KiBlockThread(&Status, CurrentThread->WaitReason = WaitReason;
CurrentThread->Alertable, CurrentThread->WaitTime = 0;
WaitMode, CurrentThread->State = Waiting;
WaitReason);
/* Find a new thread to run */
DPRINT("Swapping threads\n");
Status = KiSwapThread();
/* Check if we were executing an APC */ /* Check if we were executing an APC */
if (Status != STATUS_KERNEL_APC) return; if (Status != STATUS_KERNEL_APC) return;

View file

@ -172,48 +172,22 @@ KiDispatchThreadNoLock(ULONG NewThreadStatus)
KEBUGCHECK(0); KEBUGCHECK(0);
} }
VOID NTSTATUS
STDCALL NTAPI
KiBlockThread(PNTSTATUS Status, KiSwapThread(VOID)
UCHAR Alertable,
ULONG WaitMode,
UCHAR WaitReason)
{ {
PKTHREAD Thread = KeGetCurrentThread(); PKTHREAD CurrentThread = KeGetCurrentThread();
PKWAIT_BLOCK WaitBlock;
if (Thread->ApcState.KernelApcPending) { /* Find a new thread to run */
DPRINT("Dispatching Thread as blocked\n");
KiDispatchThreadNoLock(Waiting);
DPRINT("Dispatching Thread as ready (APC!)\n"); /* Lower IRQL back */
DPRINT("Lowering IRQL \n");
KfLowerIrql(CurrentThread->WaitIrql);
/* Remove Waits */ /* Return the wait status */
WaitBlock = Thread->WaitBlockList; return CurrentThread->WaitStatus;
do {
RemoveEntryList (&WaitBlock->WaitListEntry);
WaitBlock = WaitBlock->NextWaitBlock;
} while (WaitBlock != Thread->WaitBlockList);
Thread->WaitBlockList = NULL;
/* Dispatch it and return status */
KiDispatchThreadNoLock (Ready);
if (Status != NULL) *Status = STATUS_KERNEL_APC;
} else {
/* Set the Thread Data as Requested */
DPRINT("Dispatching Thread as blocked: %d\n", Thread->WaitStatus);
Thread->Alertable = Alertable;
Thread->WaitMode = (UCHAR)WaitMode;
Thread->WaitReason = WaitReason;
/* Dispatch it and return status */
KiDispatchThreadNoLock(Waiting);
DPRINT("Dispatching Thread as blocked: %d\n", Thread->WaitStatus);
if (Status != NULL) *Status = Thread->WaitStatus;
}
DPRINT("Releasing Dispatcher Lock\n");
KfLowerIrql(Thread->WaitIrql);
} }
VOID VOID

View file

@ -286,12 +286,16 @@ KeRemoveQueue(IN PKQUEUE Queue,
InsertTailList(&Queue->Header.WaitListHead, InsertTailList(&Queue->Header.WaitListHead,
&WaitBlock->WaitListEntry); &WaitBlock->WaitListEntry);
/* Block the Thread */ /* Setup the wait information */
DPRINT("Blocking the Thread: %x %x!\n", KeGetCurrentThread(), Thread); Thread->WaitMode = WaitMode;
KiBlockThread(&Status, Thread->WaitReason = WrQueue;
FALSE, Thread->Alertable = FALSE;
WaitMode, Thread->WaitTime = 0;
WrQueue); Thread->State = Waiting;
/* Find a new thread to run */
DPRINT("Swapping threads\n");
Status = KiSwapThread();
/* Reset the wait reason */ /* Reset the wait reason */
Thread->WaitReason = 0; Thread->WaitReason = 0;

View file

@ -106,7 +106,6 @@ KeDelayExecutionThread(KPROCESSOR_MODE WaitMode,
PKTIMER ThreadTimer; PKTIMER ThreadTimer;
PKTHREAD CurrentThread = KeGetCurrentThread(); PKTHREAD CurrentThread = KeGetCurrentThread();
NTSTATUS Status; NTSTATUS Status;
DPRINT("Entering KeDelayExecutionThread\n"); DPRINT("Entering KeDelayExecutionThread\n");
/* Check if the lock is already held */ /* Check if the lock is already held */
@ -129,6 +128,15 @@ KeDelayExecutionThread(KPROCESSOR_MODE WaitMode,
/* Start Wait Loop */ /* Start Wait Loop */
do do
{ {
/* Check if a kernel APC is pending and we were below APC_LEVEL */
if ((CurrentThread->ApcState.KernelApcPending) &&
(CurrentThread->WaitIrql < APC_LEVEL))
{
/* Unlock the dispatcher */
KeReleaseDispatcherDatabaseLock(CurrentThread->WaitIrql);
goto SkipWait;
}
/* Chceck if we can do an alertable wait, if requested */ /* Chceck if we can do an alertable wait, if requested */
if (KiCheckAlertability(Alertable, CurrentThread, WaitMode, &Status)) break; if (KiCheckAlertability(Alertable, CurrentThread, WaitMode, &Status)) break;
@ -162,13 +170,16 @@ KeDelayExecutionThread(KPROCESSOR_MODE WaitMode,
KiWakeQueue(CurrentThread->Queue); KiWakeQueue(CurrentThread->Queue);
} }
/* Block the Thread */ /* Setup the wait information */
DPRINT("Blocking the Thread: %d, %d, %x\n", CurrentThread->Alertable = Alertable;
Alertable, WaitMode, KeGetCurrentThread()); CurrentThread->WaitMode = WaitMode;
KiBlockThread(&Status, CurrentThread->WaitReason = DelayExecution;
Alertable, CurrentThread->WaitTime = 0;
WaitMode, CurrentThread->State = Waiting;
DelayExecution);
/* Find a new thread to run */
DPRINT("Swapping threads\n");
Status = KiSwapThread();
/* Check if we were executing an APC or if we timed out */ /* Check if we were executing an APC or if we timed out */
if (Status != STATUS_KERNEL_APC) if (Status != STATUS_KERNEL_APC)
@ -180,7 +191,11 @@ KeDelayExecutionThread(KPROCESSOR_MODE WaitMode,
return Status; return Status;
} }
DPRINT("Looping Again\n"); // FIXME: Need to modify interval /* FIXME: Fixup interval */
/* Acquire again the lock */
SkipWait:
DPRINT("Looping again\n");
CurrentThread->WaitIrql = KeAcquireDispatcherDatabaseLock(); CurrentThread->WaitIrql = KeAcquireDispatcherDatabaseLock();
} }
while (TRUE); while (TRUE);
@ -241,6 +256,15 @@ KeWaitForSingleObject(PVOID Object,
/* Start the actual Loop */ /* Start the actual Loop */
do do
{ {
/* Check if a kernel APC is pending and we were below APC_LEVEL */
if ((CurrentThread->ApcState.KernelApcPending) &&
(CurrentThread->WaitIrql < APC_LEVEL))
{
/* Unlock the dispatcher */
KeReleaseDispatcherDatabaseLock(CurrentThread->WaitIrql);
goto SkipWait;
}
/* Get the current Wait Status */ /* Get the current Wait Status */
WaitStatus = CurrentThread->WaitStatus; WaitStatus = CurrentThread->WaitStatus;
@ -344,13 +368,16 @@ KeWaitForSingleObject(PVOID Object,
KiWakeQueue(CurrentThread->Queue); KiWakeQueue(CurrentThread->Queue);
} }
/* Block the Thread */ /* Setup the wait information */
DPRINT("Blocking the Thread: %d, %d, %d, %x\n", CurrentThread->Alertable = Alertable;
Alertable, WaitMode, WaitReason, KeGetCurrentThread()); CurrentThread->WaitMode = WaitMode;
KiBlockThread(&Status, CurrentThread->WaitReason = WaitReason;
Alertable, CurrentThread->WaitTime = 0;
WaitMode, CurrentThread->State = Waiting;
(UCHAR)WaitReason);
/* Find a new thread to run */
DPRINT("Swapping threads\n");
Status = KiSwapThread();
/* Check if we were executing an APC */ /* Check if we were executing an APC */
if (Status != STATUS_KERNEL_APC) if (Status != STATUS_KERNEL_APC)
@ -359,8 +386,15 @@ KeWaitForSingleObject(PVOID Object,
return Status; return Status;
} }
/* Loop again and acquire the dispatcher lock */ /* Check if we had a timeout */
DPRINT("Looping Again\n"); // FIXME: Change interval if (Timeout)
{
/* FIXME: Fixup interval */
}
/* Acquire again the lock */
SkipWait:
DPRINT("Looping again\n");
CurrentThread->WaitIrql = KeAcquireDispatcherDatabaseLock(); CurrentThread->WaitIrql = KeAcquireDispatcherDatabaseLock();
} }
while (TRUE); while (TRUE);
@ -443,6 +477,15 @@ KeWaitForMultipleObjects(ULONG Count,
/* Start the actual Loop */ /* Start the actual Loop */
do do
{ {
/* Check if a kernel APC is pending and we were below APC_LEVEL */
if ((CurrentThread->ApcState.KernelApcPending) &&
(CurrentThread->WaitIrql < APC_LEVEL))
{
/* Unlock the dispatcher */
KeReleaseDispatcherDatabaseLock(CurrentThread->WaitIrql);
goto SkipWait;
}
/* Get the current Wait Status */ /* Get the current Wait Status */
WaitStatus = CurrentThread->WaitStatus; WaitStatus = CurrentThread->WaitStatus;
@ -612,13 +655,16 @@ KeWaitForMultipleObjects(ULONG Count,
KiWakeQueue(CurrentThread->Queue); KiWakeQueue(CurrentThread->Queue);
} }
/* Block the Thread */ /* Setup the wait information */
DPRINT("Blocking the Thread: %d, %d, %d, %x\n", CurrentThread->Alertable = Alertable;
Alertable, WaitMode, WaitReason, KeGetCurrentThread()); CurrentThread->WaitMode = WaitMode;
KiBlockThread(&Status, CurrentThread->WaitReason = WaitReason;
Alertable, CurrentThread->WaitTime = 0;
WaitMode, CurrentThread->State = Waiting;
(UCHAR)WaitReason);
/* Find a new thread to run */
DPRINT("Swapping threads\n");
Status = KiSwapThread();
/* Check if we were executing an APC */ /* Check if we were executing an APC */
DPRINT("Thread is back\n"); DPRINT("Thread is back\n");
@ -628,8 +674,15 @@ KeWaitForMultipleObjects(ULONG Count,
return Status; return Status;
} }
/* Loop again and re-acquire the dispatcher lock */ /* Check if we had a timeout */
DPRINT("Looping Again\n"); // FIXME: Fix-up the interval */ if (Timeout)
{
/* FIXME: Fixup interval */
}
/* Acquire again the lock */
SkipWait:
DPRINT("Looping again\n");
CurrentThread->WaitIrql = KeAcquireDispatcherDatabaseLock(); CurrentThread->WaitIrql = KeAcquireDispatcherDatabaseLock();
} }
while (TRUE); while (TRUE);