mirror of
https://github.com/reactos/reactos.git
synced 2025-02-22 16:36:33 +00:00
- 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:
parent
afc39c0267
commit
92f9f2e23b
5 changed files with 123 additions and 92 deletions
|
@ -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. */
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue