* On UP machines, we don't actually have a spinlock, we merely raise
* IRQL to DPC level.
*/
-#ifndef CONFIG_SMP
-#define KeInitializeDispatcher()
-#define KeAcquireDispatcherDatabaseLock() KeRaiseIrqlToDpcLevel();
-#define KeReleaseDispatcherDatabaseLock(OldIrql) KiExitDispatcher(OldIrql);
-#define KeAcquireDispatcherDatabaseLockAtDpcLevel()
-#define KeReleaseDispatcherDatabaseLockFromDpcLevel()
-#else
+#ifdef CONFIG_SMP
#define KeInitializeDispatcher() KeInitializeSpinLock(&DispatcherDatabaseLock);
#define KeAcquireDispatcherDatabaseLock() KfAcquireSpinLock(&DispatcherDatabaseLock);
#define KeAcquireDispatcherDatabaseLockAtDpcLevel() \
#define KeReleaseDispatcherDatabaseLock(OldIrql) \
KeReleaseSpinLockFromDpcLevel(&DispatcherDatabaseLock); \
KiExitDispatcher(OldIrql);
+#else
+#define KeInitializeDispatcher()
+#define KeAcquireDispatcherDatabaseLock() KeRaiseIrqlToDpcLevel();
+#define KeReleaseDispatcherDatabaseLock(OldIrql) KiExitDispatcher(OldIrql);
+#define KeAcquireDispatcherDatabaseLockAtDpcLevel()
+#define KeReleaseDispatcherDatabaseLockFromDpcLevel()
#endif
/* The following macro initializes a dispatcher object's header */
STDCALL
KiDispatchThread(ULONG NewThreadStatus);
-/* Puts a Thread into a block state. */
-VOID
-STDCALL
-KiBlockThread(
- PNTSTATUS Status,
- UCHAR Alertable,
- ULONG WaitMode,
- UCHAR WaitReason
+/* Finds a new thread to run */
+NTSTATUS
+NTAPI
+KiSwapThread(
+ VOID
);
/* Removes a thread out of a block state. */
KEBUGCHECK(0);
}
-VOID
-STDCALL
-KiBlockThread(PNTSTATUS Status,
- UCHAR Alertable,
- ULONG WaitMode,
- UCHAR WaitReason)
+NTSTATUS
+NTAPI
+KiSwapThread(VOID)
{
- PKTHREAD Thread = KeGetCurrentThread();
- PKWAIT_BLOCK WaitBlock;
-
- if (Thread->ApcState.KernelApcPending) {
-
- DPRINT("Dispatching Thread as ready (APC!)\n");
-
- /* Remove Waits */
- WaitBlock = Thread->WaitBlockList;
- 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 {
+ PKTHREAD CurrentThread = KeGetCurrentThread();
- /* 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;
+ /* Find a new thread to run */
+ DPRINT("Dispatching Thread as blocked\n");
+ KiDispatchThreadNoLock(Waiting);
- /* Dispatch it and return status */
- KiDispatchThreadNoLock(Waiting);
- DPRINT("Dispatching Thread as blocked: %d\n", Thread->WaitStatus);
- if (Status != NULL) *Status = Thread->WaitStatus;
- }
+ /* Lower IRQL back */
+ DPRINT("Lowering IRQL \n");
+ KfLowerIrql(CurrentThread->WaitIrql);
- DPRINT("Releasing Dispatcher Lock\n");
- KfLowerIrql(Thread->WaitIrql);
+ /* Return the wait status */
+ return CurrentThread->WaitStatus;
}
VOID
PKTIMER ThreadTimer;
PKTHREAD CurrentThread = KeGetCurrentThread();
NTSTATUS Status;
-
DPRINT("Entering KeDelayExecutionThread\n");
/* Check if the lock is already held */
/* Start Wait Loop */
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 */
if (KiCheckAlertability(Alertable, CurrentThread, WaitMode, &Status)) break;
KiWakeQueue(CurrentThread->Queue);
}
- /* Block the Thread */
- DPRINT("Blocking the Thread: %d, %d, %x\n",
- Alertable, WaitMode, KeGetCurrentThread());
- KiBlockThread(&Status,
- Alertable,
- WaitMode,
- DelayExecution);
+ /* Setup the wait information */
+ CurrentThread->Alertable = Alertable;
+ CurrentThread->WaitMode = WaitMode;
+ CurrentThread->WaitReason = DelayExecution;
+ CurrentThread->WaitTime = 0;
+ CurrentThread->State = Waiting;
+
+ /* Find a new thread to run */
+ DPRINT("Swapping threads\n");
+ Status = KiSwapThread();
/* Check if we were executing an APC or if we timed out */
if (Status != STATUS_KERNEL_APC)
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();
}
while (TRUE);
/* Start the actual Loop */
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 */
WaitStatus = CurrentThread->WaitStatus;
KiWakeQueue(CurrentThread->Queue);
}
- /* Block the Thread */
- DPRINT("Blocking the Thread: %d, %d, %d, %x\n",
- Alertable, WaitMode, WaitReason, KeGetCurrentThread());
- KiBlockThread(&Status,
- Alertable,
- WaitMode,
- (UCHAR)WaitReason);
+ /* Setup the wait information */
+ CurrentThread->Alertable = Alertable;
+ CurrentThread->WaitMode = WaitMode;
+ CurrentThread->WaitReason = WaitReason;
+ CurrentThread->WaitTime = 0;
+ CurrentThread->State = Waiting;
+
+ /* Find a new thread to run */
+ DPRINT("Swapping threads\n");
+ Status = KiSwapThread();
/* Check if we were executing an APC */
if (Status != STATUS_KERNEL_APC)
return Status;
}
- /* Loop again and acquire the dispatcher lock */
- DPRINT("Looping Again\n"); // FIXME: Change interval
+ /* Check if we had a timeout */
+ if (Timeout)
+ {
+ /* FIXME: Fixup interval */
+ }
+
+ /* Acquire again the lock */
+SkipWait:
+ DPRINT("Looping again\n");
CurrentThread->WaitIrql = KeAcquireDispatcherDatabaseLock();
}
while (TRUE);
/* Start the actual Loop */
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 */
WaitStatus = CurrentThread->WaitStatus;
KiWakeQueue(CurrentThread->Queue);
}
- /* Block the Thread */
- DPRINT("Blocking the Thread: %d, %d, %d, %x\n",
- Alertable, WaitMode, WaitReason, KeGetCurrentThread());
- KiBlockThread(&Status,
- Alertable,
- WaitMode,
- (UCHAR)WaitReason);
+ /* Setup the wait information */
+ CurrentThread->Alertable = Alertable;
+ CurrentThread->WaitMode = WaitMode;
+ CurrentThread->WaitReason = WaitReason;
+ CurrentThread->WaitTime = 0;
+ CurrentThread->State = Waiting;
+
+ /* Find a new thread to run */
+ DPRINT("Swapping threads\n");
+ Status = KiSwapThread();
/* Check if we were executing an APC */
DPRINT("Thread is back\n");
return Status;
}
- /* Loop again and re-acquire the dispatcher lock */
- DPRINT("Looping Again\n"); // FIXME: Fix-up the interval */
+ /* Check if we had a timeout */
+ if (Timeout)
+ {
+ /* FIXME: Fixup interval */
+ }
+
+ /* Acquire again the lock */
+SkipWait:
+ DPRINT("Looping again\n");
CurrentThread->WaitIrql = KeAcquireDispatcherDatabaseLock();
}
while (TRUE);