/* GLOBALS ********************************************************************/
+typedef struct _KSWITCHFRAME
+{
+ PVOID ExceptionList;
+ BOOLEAN ApcBypassDisable;
+ PVOID RetAddr;
+} KSWITCHFRAME, *PKSWITCHFRAME;
+
typedef struct _KUINIT_FRAME
{
KEXCEPTION_FRAME CtxSwitchFrame;
NTAPI
KiThreadStartup(VOID);
+VOID
+FASTCALL
+KiSwitchThreads(
+ IN PKTHREAD OldThread,
+ IN PKTHREAD NewThread
+);
+
+
+/* FIXME: THIS IS TOTALLY BUSTED NOW */
VOID
NTAPI
KiInitializeContextThread(IN PKTHREAD Thread,
//
Thread->KernelStack = (PVOID)CtxSwitchFrame;
}
+
+VOID
+FASTCALL
+KiIdleLoop(VOID)
+{
+ PKPRCB Prcb = KeGetCurrentPrcb();
+ PKTHREAD OldThread, NewThread;
+
+ /* Initialize the idle loop: disable interrupts */
+ _enable();
+ YieldProcessor();
+ YieldProcessor();
+ _disable();
+
+ /* Now loop forever */
+ while (TRUE)
+ {
+ /* Check for pending timers, pending DPCs, or pending ready threads */
+ if ((Prcb->DpcData[0].DpcQueueDepth) ||
+ (Prcb->TimerRequest) ||
+ (Prcb->DeferredReadyListHead.Next))
+ {
+ /* Quiesce the DPC software interrupt */
+ HalClearSoftwareInterrupt(DISPATCH_LEVEL);
+
+ /* Handle it */
+ KiRetireDpcList(Prcb);
+ }
+
+ /* Check if a new thread is scheduled for execution */
+ if (Prcb->NextThread)
+ {
+ /* Enable interupts */
+ _enable();
+
+ /* Capture current thread data */
+ OldThread = Prcb->CurrentThread;
+ NewThread = Prcb->NextThread;
+
+ /* Set new thread data */
+ Prcb->NextThread = NULL;
+ Prcb->CurrentThread = NewThread;
+
+ /* The thread is now running */
+ NewThread->State = Running;
+
+ /* Switch away from the idle thread */
+ KiSwapContext(APC_LEVEL, OldThread);
+
+ /* We are back in the idle thread -- disable interrupts again */
+ _enable();
+ YieldProcessor();
+ YieldProcessor();
+ _disable();
+ }
+ else
+ {
+ /* Continue staying idle. Note the HAL returns with interrupts on */
+ Prcb->PowerState.IdleFunction(&Prcb->PowerState);
+ }
+ }
+}
+
+BOOLEAN
+FASTCALL
+KiSwapContextExit(IN PKTHREAD OldThread,
+ IN PKSWITCHFRAME SwitchFrame)
+{
+ PKIPCR Pcr = (PKIPCR)KeGetPcr();
+ PKPROCESS OldProcess, NewProcess;
+ PKTHREAD NewThread;
+ ARM_TTB_REGISTER TtbRegister;
+
+ /* We are on the new thread stack now */
+ NewThread = Pcr->PrcbData.CurrentThread;
+
+ /* Now we are the new thread. Check if it's in a new process */
+ OldProcess = OldThread->ApcState.Process;
+ NewProcess = NewThread->ApcState.Process;
+ if (OldProcess != NewProcess)
+ {
+ TtbRegister.AsUlong = NewProcess->DirectoryTableBase[0];
+ ASSERT(TtbRegister.Reserved == 0);
+ KeArmTranslationTableRegisterSet(TtbRegister);
+ }
+
+ /* Increase thread context switches */
+ NewThread->ContextSwitches++;
+
+ /* Load data from switch frame */
+ Pcr->NtTib.ExceptionList = SwitchFrame->ExceptionList;
+
+ /* DPCs shouldn't be active */
+ if (Pcr->PrcbData.DpcRoutineActive)
+ {
+ /* Crash the machine */
+ KeBugCheckEx(ATTEMPTED_SWITCH_FROM_DPC,
+ (ULONG_PTR)OldThread,
+ (ULONG_PTR)NewThread,
+ (ULONG_PTR)OldThread->InitialStack,
+ 0);
+ }
+
+ /* Kernel APCs may be pending */
+ if (NewThread->ApcState.KernelApcPending)
+ {
+ /* Are APCs enabled? */
+ if (!NewThread->SpecialApcDisable)
+ {
+ /* Request APC delivery */
+ if (SwitchFrame->ApcBypassDisable) HalRequestSoftwareInterrupt(APC_LEVEL);
+ return TRUE;
+ }
+ }
+
+ /* Return */
+ return FALSE;
+}
+
+VOID
+FASTCALL
+KiSwapContextEntry(IN PKSWITCHFRAME SwitchFrame,
+ IN ULONG_PTR OldThreadAndApcFlag)
+{
+ PKIPCR Pcr = (PKIPCR)KeGetPcr();
+ PKTHREAD OldThread, NewThread;
+
+ /* Save APC bypass disable */
+ SwitchFrame->ApcBypassDisable = OldThreadAndApcFlag & 3;
+ SwitchFrame->ExceptionList = Pcr->NtTib.ExceptionList;
+
+ /* Increase context switch count and check if tracing is enabled */
+ Pcr->ContextSwitches++;
+ if (Pcr->PerfGlobalGroupMask)
+ {
+ /* We don't support this yet on x86 either */
+ DPRINT1("WMI Tracing not supported\n");
+ ASSERT(FALSE);
+ }
+
+ /* Get thread pointers */
+ OldThread = (PKTHREAD)(OldThreadAndApcFlag & ~3);
+ NewThread = Pcr->PrcbData.CurrentThread;
+
+ /* Get the old thread and set its kernel stack */
+ OldThread->KernelStack = SwitchFrame;
+
+ /* Do the switch */
+ KiSwitchThreads(OldThread, NewThread->KernelStack);
+}
+
+VOID
+NTAPI
+KiDispatchInterrupt(VOID)
+{
+ PKIPCR Pcr = (PKIPCR)KeGetPcr();
+ PKPRCB Prcb = &Pcr->PrcbData;
+ PVOID OldHandler;
+ PKTHREAD NewThread, OldThread;
+
+ /* Disable interrupts */
+ _disable();
+
+ /* Check for pending timers, pending DPCs, or pending ready threads */
+ if ((Prcb->DpcData[0].DpcQueueDepth) ||
+ (Prcb->TimerRequest) ||
+ (Prcb->DeferredReadyListHead.Next))
+ {
+ /* Switch to safe execution context */
+ OldHandler = Pcr->NtTib.ExceptionList;
+ Pcr->NtTib.ExceptionList = EXCEPTION_CHAIN_END;
+
+ /* Retire DPCs while under the DPC stack */
+ //KiRetireDpcListInDpcStack(Prcb, Prcb->DpcStack);
+ // FIXME!!! //
+ KiRetireDpcList(Prcb);
+
+ /* Restore context */
+ Pcr->NtTib.ExceptionList = OldHandler;
+ }
+
+ /* Re-enable interrupts */
+ _enable();
+
+ /* Check for quantum end */
+ if (Prcb->QuantumEnd)
+ {
+ /* Handle quantum end */
+ Prcb->QuantumEnd = FALSE;
+ KiQuantumEnd();
+ }
+ else if (Prcb->NextThread)
+ {
+ /* Capture current thread data */
+ OldThread = Prcb->CurrentThread;
+ NewThread = Prcb->NextThread;
+
+ /* Set new thread data */
+ Prcb->NextThread = NULL;
+ Prcb->CurrentThread = NewThread;
+
+ /* The thread is now running */
+ NewThread->State = Running;
+ OldThread->WaitReason = WrDispatchInt;
+
+ /* Make the old thread ready */
+ KxQueueReadyThread(OldThread, Prcb);
+
+ /* Swap to the new thread */
+ KiSwapContext(APC_LEVEL, OldThread);
+ }
+}
+
+/* EOF */