Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenthrdini.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS Kernel 00003 * LICENSE: BSD - See COPYING.ARM in the top level directory 00004 * FILE: ntoskrnl/ke/arm/thrdini.c 00005 * PURPOSE: Implements thread context setup and startup for ARM machines 00006 * PROGRAMMERS: ReactOS Portable Systems Group 00007 */ 00008 00009 /* INCLUDES *******************************************************************/ 00010 00011 #include <ntoskrnl.h> 00012 #define NDEBUG 00013 #include <debug.h> 00014 00015 /* GLOBALS ********************************************************************/ 00016 00017 typedef struct _KSWITCHFRAME 00018 { 00019 PVOID ExceptionList; 00020 BOOLEAN ApcBypassDisable; 00021 PVOID RetAddr; 00022 } KSWITCHFRAME, *PKSWITCHFRAME; 00023 00024 typedef struct _KUINIT_FRAME 00025 { 00026 KEXCEPTION_FRAME CtxSwitchFrame; 00027 KEXCEPTION_FRAME ExceptionFrame; 00028 KTRAP_FRAME TrapFrame; 00029 } KUINIT_FRAME, *PKUINIT_FRAME; 00030 00031 typedef struct _KKINIT_FRAME 00032 { 00033 KEXCEPTION_FRAME CtxSwitchFrame; 00034 } KKINIT_FRAME, *PKKINIT_FRAME; 00035 00036 /* FUNCTIONS ******************************************************************/ 00037 00038 VOID 00039 NTAPI 00040 KiThreadStartup(VOID); 00041 00042 VOID 00043 FASTCALL 00044 KiSwitchThreads( 00045 IN PKTHREAD OldThread, 00046 IN PKTHREAD NewThread 00047 ); 00048 00049 00050 /* FIXME: THIS IS TOTALLY BUSTED NOW */ 00051 VOID 00052 NTAPI 00053 KiInitializeContextThread(IN PKTHREAD Thread, 00054 IN PKSYSTEM_ROUTINE SystemRoutine, 00055 IN PKSTART_ROUTINE StartRoutine, 00056 IN PVOID StartContext, 00057 IN PCONTEXT ContextPointer) 00058 { 00059 PKTRAP_FRAME TrapFrame; 00060 PKEXCEPTION_FRAME ExceptionFrame = NULL, CtxSwitchFrame; 00061 00062 // 00063 // Check if this is a user thread 00064 // 00065 if (ContextPointer) 00066 { 00067 // 00068 // Setup the initial frame 00069 // 00070 PKUINIT_FRAME InitFrame; 00071 InitFrame = (PKUINIT_FRAME)((ULONG_PTR)Thread->InitialStack - 00072 sizeof(KUINIT_FRAME)); 00073 00074 // 00075 // Setup the Trap Frame and Exception frame 00076 // 00077 TrapFrame = &InitFrame->TrapFrame; 00078 ExceptionFrame = &InitFrame->ExceptionFrame; 00079 00081 // Zero out the trap frame and exception frame 00082 // 00083 RtlZeroMemory(TrapFrame, sizeof(KTRAP_FRAME)); 00084 RtlZeroMemory(ExceptionFrame, sizeof(KEXCEPTION_FRAME)); 00085 00086 // 00087 // Set up a trap frame from the context 00088 // 00089 KeContextToTrapFrame(ContextPointer, 00090 ExceptionFrame, 00091 TrapFrame, 00092 ContextPointer->ContextFlags | CONTEXT_CONTROL, 00093 UserMode); 00094 00095 // 00096 // Set the previous mode as user 00097 // 00098 //TrapFrame->PreviousMode = UserMode; 00099 Thread->PreviousMode = UserMode; 00100 00101 // 00102 // Clear the return address 00103 // 00104 ExceptionFrame->Lr = 0; 00105 00106 // 00107 // Context switch frame to setup below 00108 // 00109 CtxSwitchFrame = &InitFrame->CtxSwitchFrame; 00110 } 00111 else 00112 { 00113 // 00114 // Set up the Initial Frame for the system thread 00115 // 00116 PKKINIT_FRAME InitFrame; 00117 InitFrame = (PKKINIT_FRAME)((ULONG_PTR)Thread->InitialStack - 00118 sizeof(KKINIT_FRAME)); 00119 00120 // 00121 // Set the previous mode as kernel 00122 // 00123 Thread->PreviousMode = KernelMode; 00124 00125 // 00126 // Context switch frame to setup below 00127 // 00128 CtxSwitchFrame = &InitFrame->CtxSwitchFrame; 00129 } 00130 00131 // 00132 // Now setup the context switch frame 00133 // 00134 CtxSwitchFrame->Lr = (ULONG)KiThreadStartup; 00135 CtxSwitchFrame->R11 = (ULONG)(ExceptionFrame ? ExceptionFrame : CtxSwitchFrame); 00136 00137 // 00138 // Set the parameters 00139 // 00140 CtxSwitchFrame->R4 = (ULONG)ContextPointer; 00141 CtxSwitchFrame->R5 = (ULONG)StartContext; 00142 CtxSwitchFrame->R6 = (ULONG)StartRoutine; 00143 CtxSwitchFrame->R7 = (ULONG)SystemRoutine; 00144 00145 // 00146 // Save back the new value of the kernel stack 00147 // 00148 Thread->KernelStack = (PVOID)CtxSwitchFrame; 00149 } 00150 00151 VOID 00152 FASTCALL 00153 KiIdleLoop(VOID) 00154 { 00155 PKPRCB Prcb = KeGetCurrentPrcb(); 00156 PKTHREAD OldThread, NewThread; 00157 00158 /* Initialize the idle loop: disable interrupts */ 00159 _enable(); 00160 YieldProcessor(); 00161 YieldProcessor(); 00162 _disable(); 00163 00164 /* Now loop forever */ 00165 while (TRUE) 00166 { 00167 /* Check for pending timers, pending DPCs, or pending ready threads */ 00168 if ((Prcb->DpcData[0].DpcQueueDepth) || 00169 (Prcb->TimerRequest) || 00170 (Prcb->DeferredReadyListHead.Next)) 00171 { 00172 /* Quiesce the DPC software interrupt */ 00173 HalClearSoftwareInterrupt(DISPATCH_LEVEL); 00174 00175 /* Handle it */ 00176 KiRetireDpcList(Prcb); 00177 } 00178 00179 /* Check if a new thread is scheduled for execution */ 00180 if (Prcb->NextThread) 00181 { 00182 /* Enable interupts */ 00183 _enable(); 00184 00185 /* Capture current thread data */ 00186 OldThread = Prcb->CurrentThread; 00187 NewThread = Prcb->NextThread; 00188 00189 /* Set new thread data */ 00190 Prcb->NextThread = NULL; 00191 Prcb->CurrentThread = NewThread; 00192 00193 /* The thread is now running */ 00194 NewThread->State = Running; 00195 00196 /* Switch away from the idle thread */ 00197 KiSwapContext(APC_LEVEL, OldThread); 00198 00199 /* We are back in the idle thread -- disable interrupts again */ 00200 _enable(); 00201 YieldProcessor(); 00202 YieldProcessor(); 00203 _disable(); 00204 } 00205 else 00206 { 00207 /* Continue staying idle. Note the HAL returns with interrupts on */ 00208 Prcb->PowerState.IdleFunction(&Prcb->PowerState); 00209 } 00210 } 00211 } 00212 00213 BOOLEAN 00214 FASTCALL 00215 KiSwapContextExit(IN PKTHREAD OldThread, 00216 IN PKSWITCHFRAME SwitchFrame) 00217 { 00218 PKIPCR Pcr = (PKIPCR)KeGetPcr(); 00219 PKPROCESS OldProcess, NewProcess; 00220 PKTHREAD NewThread; 00221 ARM_TTB_REGISTER TtbRegister; 00222 00223 /* We are on the new thread stack now */ 00224 NewThread = Pcr->PrcbData.CurrentThread; 00225 00226 /* Now we are the new thread. Check if it's in a new process */ 00227 OldProcess = OldThread->ApcState.Process; 00228 NewProcess = NewThread->ApcState.Process; 00229 if (OldProcess != NewProcess) 00230 { 00231 TtbRegister.AsUlong = NewProcess->DirectoryTableBase[0]; 00232 ASSERT(TtbRegister.Reserved == 0); 00233 KeArmTranslationTableRegisterSet(TtbRegister); 00234 } 00235 00236 /* Increase thread context switches */ 00237 NewThread->ContextSwitches++; 00238 00239 /* Load data from switch frame */ 00240 Pcr->NtTib.ExceptionList = SwitchFrame->ExceptionList; 00241 00242 /* DPCs shouldn't be active */ 00243 if (Pcr->PrcbData.DpcRoutineActive) 00244 { 00245 /* Crash the machine */ 00246 KeBugCheckEx(ATTEMPTED_SWITCH_FROM_DPC, 00247 (ULONG_PTR)OldThread, 00248 (ULONG_PTR)NewThread, 00249 (ULONG_PTR)OldThread->InitialStack, 00250 0); 00251 } 00252 00253 /* Kernel APCs may be pending */ 00254 if (NewThread->ApcState.KernelApcPending) 00255 { 00256 /* Are APCs enabled? */ 00257 if (!NewThread->SpecialApcDisable) 00258 { 00259 /* Request APC delivery */ 00260 if (SwitchFrame->ApcBypassDisable) HalRequestSoftwareInterrupt(APC_LEVEL); 00261 return TRUE; 00262 } 00263 } 00264 00265 /* Return */ 00266 return FALSE; 00267 } 00268 00269 VOID 00270 FASTCALL 00271 KiSwapContextEntry(IN PKSWITCHFRAME SwitchFrame, 00272 IN ULONG_PTR OldThreadAndApcFlag) 00273 { 00274 PKIPCR Pcr = (PKIPCR)KeGetPcr(); 00275 PKTHREAD OldThread, NewThread; 00276 00277 /* Save APC bypass disable */ 00278 SwitchFrame->ApcBypassDisable = OldThreadAndApcFlag & 3; 00279 SwitchFrame->ExceptionList = Pcr->NtTib.ExceptionList; 00280 00281 /* Increase context switch count and check if tracing is enabled */ 00282 Pcr->ContextSwitches++; 00283 if (Pcr->PerfGlobalGroupMask) 00284 { 00285 /* We don't support this yet on x86 either */ 00286 DPRINT1("WMI Tracing not supported\n"); 00287 ASSERT(FALSE); 00288 } 00289 00290 /* Get thread pointers */ 00291 OldThread = (PKTHREAD)(OldThreadAndApcFlag & ~3); 00292 NewThread = Pcr->PrcbData.CurrentThread; 00293 00294 /* Get the old thread and set its kernel stack */ 00295 OldThread->KernelStack = SwitchFrame; 00296 00297 /* Do the switch */ 00298 KiSwitchThreads(OldThread, NewThread->KernelStack); 00299 } 00300 00301 VOID 00302 NTAPI 00303 KiDispatchInterrupt(VOID) 00304 { 00305 PKIPCR Pcr = (PKIPCR)KeGetPcr(); 00306 PKPRCB Prcb = &Pcr->PrcbData; 00307 PVOID OldHandler; 00308 PKTHREAD NewThread, OldThread; 00309 00310 /* Disable interrupts */ 00311 _disable(); 00312 00313 /* Check for pending timers, pending DPCs, or pending ready threads */ 00314 if ((Prcb->DpcData[0].DpcQueueDepth) || 00315 (Prcb->TimerRequest) || 00316 (Prcb->DeferredReadyListHead.Next)) 00317 { 00318 /* Switch to safe execution context */ 00319 OldHandler = Pcr->NtTib.ExceptionList; 00320 Pcr->NtTib.ExceptionList = EXCEPTION_CHAIN_END; 00321 00322 /* Retire DPCs while under the DPC stack */ 00323 //KiRetireDpcListInDpcStack(Prcb, Prcb->DpcStack); 00324 // FIXME!!! // 00325 KiRetireDpcList(Prcb); 00326 00327 /* Restore context */ 00328 Pcr->NtTib.ExceptionList = OldHandler; 00329 } 00330 00331 /* Re-enable interrupts */ 00332 _enable(); 00333 00334 /* Check for quantum end */ 00335 if (Prcb->QuantumEnd) 00336 { 00337 /* Handle quantum end */ 00338 Prcb->QuantumEnd = FALSE; 00339 KiQuantumEnd(); 00340 } 00341 else if (Prcb->NextThread) 00342 { 00343 /* Capture current thread data */ 00344 OldThread = Prcb->CurrentThread; 00345 NewThread = Prcb->NextThread; 00346 00347 /* Set new thread data */ 00348 Prcb->NextThread = NULL; 00349 Prcb->CurrentThread = NewThread; 00350 00351 /* The thread is now running */ 00352 NewThread->State = Running; 00353 OldThread->WaitReason = WrDispatchInt; 00354 00355 /* Make the old thread ready */ 00356 KxQueueReadyThread(OldThread, Prcb); 00357 00358 /* Swap to the new thread */ 00359 KiSwapContext(APC_LEVEL, OldThread); 00360 } 00361 } 00362 00363 /* EOF */ Generated on Sat May 26 2012 04:36:19 for ReactOS by
1.7.6.1
|