PKTRAP_FRAME TrapFrame;
PKSTART_FRAME StartFrame;
PKUINIT_FRAME InitFrame;
-
+
/* Get the start and trap frames */
InitFrame = KeGetCurrentThread()->KernelStack;
StartFrame = &InitFrame->StartFrame;
/* Lower to APC level */
KfLowerIrql(APC_LEVEL);
-
+
/* Call the system routine */
StartFrame->SystemRoutine(StartFrame->StartRoutine, StartFrame->StartContext);
-
+
/* If we returned, we better be a user thread */
if (!StartFrame->UserThread) DbgBreakPoint();
-
+
/* Exit to user-mode */
KiServiceExit2(TrapFrame);
}
YieldProcessor();
YieldProcessor();
_disable();
-
+
/* Now loop forever */
while (TRUE)
{
{
/* 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();
PKGDTENTRY GdtEntry;
PKTHREAD NewThread;
PKUINIT_FRAME InitFrame;
-
+
/* We are on the new thread stack now */
NewThread = Pcr->PrcbData.CurrentThread;
/* Switch address space and flush TLB */
__writecr3(NewProcess->DirectoryTableBase[0]);
}
-
+
/* Clear GS */
Ke386SetGs(0);
-
+
/* Set the TEB */
Pcr->NtTib.Self = (PVOID)NewThread->Teb;
GdtEntry = &Pcr->GDT[KGDT_R3_TEB / sizeof(KGDTENTRY)];
GdtEntry->BaseLow = (USHORT)((ULONG_PTR)NewThread->Teb & 0xFFFF);
GdtEntry->HighWord.Bytes.BaseMid = (UCHAR)((ULONG_PTR)NewThread->Teb >> 16);
GdtEntry->HighWord.Bytes.BaseHi = (UCHAR)((ULONG_PTR)NewThread->Teb >> 24);
-
+
/* Set new TSS fields */
InitFrame = (PKUINIT_FRAME)NewThread->InitialStack - 1;
Pcr->TSS->Esp0 = (ULONG_PTR)&InitFrame->TrapFrame;
Pcr->TSS->Esp0 -= (FIELD_OFFSET(KTRAP_FRAME, V86Gs) - FIELD_OFFSET(KTRAP_FRAME, HardwareSegSs));
}
Pcr->TSS->IoMapBase = NewProcess->IopmOffset;
-
+
/* Increase thread context switches */
NewThread->ContextSwitches++;
(ULONG_PTR)OldThread->InitialStack,
0);
}
-
+
/* Kernel APCs may be pending */
if (NewThread->ApcState.KernelApcPending)
{
return TRUE;
}
}
-
+
/* Return */
return FALSE;
}
/* Get thread pointers */
OldThread = (PKTHREAD)(OldThreadAndApcFlag & ~3);
NewThread = Pcr->PrcbData.CurrentThread;
-
+
/* Get the old thread and set its kernel stack */
OldThread->KernelStack = SwitchFrame;
/* ISRs can change FPU state, so disable interrupts while checking */
_disable();
-
+
/* Get current and new CR0 and check if they've changed */
Cr0 = __readcr0();
NewCr0 = NewThread->NpxState |
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) ||
/* 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);
-
+
/* Restore context */
Pcr->NtTib.ExceptionList = OldHandler;
}
-
+
/* Re-enable interrupts */
_enable();
-
+
/* Check for quantum end */
if (Prcb->QuantumEnd)
{
/* 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);
}