ReactOS 0.4.15-dev-6042-g2eb6700
thrdini.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: ntoskrnl/ke/arm/thrdini.c
5 * PURPOSE: Implements thread context setup and startup for ARM machines
6 * PROGRAMMERS: ReactOS Portable Systems Group
7 */
8
9/* INCLUDES *******************************************************************/
10
11#include <ntoskrnl.h>
12#define NDEBUG
13#include <debug.h>
14
15/* GLOBALS ********************************************************************/
16
17typedef struct _KSWITCHFRAME
18{
23
24typedef struct _KUINIT_FRAME
25{
30
31typedef struct _KKINIT_FRAME
32{
35
36/* FUNCTIONS ******************************************************************/
37
38VOID
41
42VOID
45 IN PKTHREAD OldThread,
46 IN PKTHREAD NewThread
47);
48
49
50/* FIXME: THIS IS TOTALLY BUSTED NOW */
51VOID
54 IN PKSYSTEM_ROUTINE SystemRoutine,
56 IN PVOID StartContext,
58{
59 PKTRAP_FRAME TrapFrame;
60 PKEXCEPTION_FRAME ExceptionFrame = NULL, CtxSwitchFrame;
61
62 //
63 // Check if this is a user thread
64 //
66 {
67 //
68 // Setup the initial frame
69 //
70 PKUINIT_FRAME InitFrame;
71 InitFrame = (PKUINIT_FRAME)((ULONG_PTR)Thread->InitialStack -
72 sizeof(KUINIT_FRAME));
73
74 //
75 // Setup the Trap Frame and Exception frame
76 //
77 TrapFrame = &InitFrame->TrapFrame;
78 ExceptionFrame = &InitFrame->ExceptionFrame;
79
81 // Zero out the trap frame and exception frame
82 //
83 RtlZeroMemory(TrapFrame, sizeof(KTRAP_FRAME));
84 RtlZeroMemory(ExceptionFrame, sizeof(KEXCEPTION_FRAME));
85
86 //
87 // Set up a trap frame from the context
88 //
90 ExceptionFrame,
91 TrapFrame,
92 ContextPointer->ContextFlags | CONTEXT_CONTROL,
93 UserMode);
94
95 //
96 // Set the previous mode as user
97 //
98 //TrapFrame->PreviousMode = UserMode;
99 Thread->PreviousMode = UserMode;
100
101 //
102 // Clear the return address
103 //
104 ExceptionFrame->Return = 0;
105
106 //
107 // Context switch frame to setup below
108 //
109 CtxSwitchFrame = &InitFrame->CtxSwitchFrame;
110 }
111 else
112 {
113 //
114 // Set up the Initial Frame for the system thread
115 //
116 PKKINIT_FRAME InitFrame;
117 InitFrame = (PKKINIT_FRAME)((ULONG_PTR)Thread->InitialStack -
118 sizeof(KKINIT_FRAME));
119
120 //
121 // Set the previous mode as kernel
122 //
123 Thread->PreviousMode = KernelMode;
124
125 //
126 // Context switch frame to setup below
127 //
128 CtxSwitchFrame = &InitFrame->CtxSwitchFrame;
129 }
130
131 //
132 // Now setup the context switch frame
133 //
134 CtxSwitchFrame->Return = (ULONG)KiThreadStartup;
135 CtxSwitchFrame->R11 = (ULONG)(ExceptionFrame ? ExceptionFrame : CtxSwitchFrame);
136
137 //
138 // Set the parameters
139 //
140 CtxSwitchFrame->R4 = (ULONG)ContextPointer;
141 CtxSwitchFrame->R5 = (ULONG)StartContext;
142 CtxSwitchFrame->R6 = (ULONG)StartRoutine;
143 CtxSwitchFrame->R7 = (ULONG)SystemRoutine;
144
145 //
146 // Save back the new value of the kernel stack
147 //
148 Thread->KernelStack = (PVOID)CtxSwitchFrame;
149}
150
152VOID
154{
155 PKPRCB Prcb = KeGetCurrentPrcb();
156 PKTHREAD OldThread, NewThread;
157
158 /* Now loop forever */
159 while (TRUE)
160 {
161 /* Start of the idle loop: disable interrupts */
162 _enable();
165 _disable();
166
167 /* Check for pending timers, pending DPCs, or pending ready threads */
168 if ((Prcb->DpcData[0].DpcQueueDepth) ||
169 (Prcb->TimerRequest) ||
171 {
172 /* Quiesce the DPC software interrupt */
174
175 /* Handle it */
176 KiRetireDpcList(Prcb);
177 }
178
179 /* Check if a new thread is scheduled for execution */
180 if (Prcb->NextThread)
181 {
182 /* Enable interrupts */
183 _enable();
184
185 /* Capture current thread data */
186 OldThread = Prcb->CurrentThread;
187 NewThread = Prcb->NextThread;
188
189 /* Set new thread data */
190 Prcb->NextThread = NULL;
191 Prcb->CurrentThread = NewThread;
192
193 /* The thread is now running */
194 NewThread->State = Running;
195
196 /* Switch away from the idle thread */
197 KiSwapContext(APC_LEVEL, OldThread);
198 }
199 else
200 {
201 /* Continue staying idle. Note the HAL returns with interrupts on */
202 Prcb->PowerState.IdleFunction(&Prcb->PowerState);
203 }
204 }
205}
206
210 IN PKSWITCHFRAME SwitchFrame)
211{
212 PKIPCR Pcr = (PKIPCR)KeGetPcr();
213 PKPROCESS OldProcess, NewProcess;
214 PKTHREAD NewThread;
215 ARM_TTB_REGISTER TtbRegister;
216
217 /* We are on the new thread stack now */
218 NewThread = Pcr->Prcb.CurrentThread;
219
220 /* Now we are the new thread. Check if it's in a new process */
221 OldProcess = OldThread->ApcState.Process;
222 NewProcess = NewThread->ApcState.Process;
223 if (OldProcess != NewProcess)
224 {
225 TtbRegister.AsUlong = NewProcess->DirectoryTableBase[0];
226 ASSERT(TtbRegister.Reserved == 0);
228 }
229
230 /* Increase thread context switches */
231 NewThread->ContextSwitches++;
232
233 /* DPCs shouldn't be active */
234 if (Pcr->Prcb.DpcRoutineActive)
235 {
236 /* Crash the machine */
237 KeBugCheckEx(ATTEMPTED_SWITCH_FROM_DPC,
238 (ULONG_PTR)OldThread,
239 (ULONG_PTR)NewThread,
240 (ULONG_PTR)OldThread->InitialStack,
241 0);
242 }
243
244 /* Kernel APCs may be pending */
245 if (NewThread->ApcState.KernelApcPending)
246 {
247 /* Are APCs enabled? */
248 if (!NewThread->SpecialApcDisable)
249 {
250 /* Request APC delivery */
251 if (SwitchFrame->ApcBypassDisable) HalRequestSoftwareInterrupt(APC_LEVEL);
252 return TRUE;
253 }
254 }
255
256 /* Return */
257 return FALSE;
258}
259
260VOID
263 IN ULONG_PTR OldThreadAndApcFlag)
264{
265 PKIPCR Pcr = (PKIPCR)KeGetPcr();
266 PKTHREAD OldThread, NewThread;
267
268 /* Save APC bypass disable */
269 SwitchFrame->ApcBypassDisable = OldThreadAndApcFlag & 3;
270
271 /* Increase context switch count and check if tracing is enabled */
272 Pcr->Prcb.KeContextSwitches++;
273#if 0
274 if (Pcr->PerfGlobalGroupMask)
275 {
276 /* We don't support this yet on x86 either */
277 DPRINT1("WMI Tracing not supported\n");
278 ASSERT(FALSE);
279 }
280#endif // 0
281
282 /* Get thread pointers */
283 OldThread = (PKTHREAD)(OldThreadAndApcFlag & ~3);
284 NewThread = Pcr->Prcb.CurrentThread;
285
286 /* Get the old thread and set its kernel stack */
287 OldThread->KernelStack = SwitchFrame;
288
289 /* Do the switch */
290 KiSwitchThreads(OldThread, NewThread->KernelStack);
291}
292
293VOID
294NTAPI
296{
297 PKIPCR Pcr = (PKIPCR)KeGetPcr();
298 PKPRCB Prcb = &Pcr->Prcb;
299 PKTHREAD NewThread, OldThread;
300
301 /* Disable interrupts */
302 _disable();
303
304 /* Check for pending timers, pending DPCs, or pending ready threads */
305 if ((Prcb->DpcData[0].DpcQueueDepth) ||
306 (Prcb->TimerRequest) ||
308 {
309 /* Retire DPCs while under the DPC stack */
310 //KiRetireDpcListInDpcStack(Prcb, Prcb->DpcStack);
311 // FIXME!!! //
312 KiRetireDpcList(Prcb);
313 }
314
315 /* Re-enable interrupts */
316 _enable();
317
318 /* Check for quantum end */
319 if (Prcb->QuantumEnd)
320 {
321 /* Handle quantum end */
322 Prcb->QuantumEnd = FALSE;
323 KiQuantumEnd();
324 }
325 else if (Prcb->NextThread)
326 {
327 /* Capture current thread data */
328 OldThread = Prcb->CurrentThread;
329 NewThread = Prcb->NextThread;
330
331 /* Set new thread data */
332 Prcb->NextThread = NULL;
333 Prcb->CurrentThread = NewThread;
334
335 /* The thread is now running */
336 NewThread->State = Running;
337 OldThread->WaitReason = WrDispatchInt;
338
339 /* Make the old thread ready */
340 KxQueueReadyThread(OldThread, Prcb);
341
342 /* Swap to the new thread */
343 KiSwapContext(APC_LEVEL, OldThread);
344 }
345}
346
347/* EOF */
unsigned char BOOLEAN
VOID NTAPI KiInitializeContextThread(IN PKTHREAD Thread, IN PKSYSTEM_ROUTINE SystemRoutine, IN PKSTART_ROUTINE StartRoutine, IN PVOID StartContext, IN PCONTEXT Context)
Definition: thrdini.c:40
struct _KKINIT_FRAME KKINIT_FRAME
struct _KUINIT_FRAME * PKUINIT_FRAME
struct _KKINIT_FRAME * PKKINIT_FRAME
struct _KUINIT_FRAME KUINIT_FRAME
FORCEINLINE VOID KeArmTranslationTableRegisterSet(IN ARM_TTB_REGISTER Ttb)
Definition: intrin_i.h:145
BOOLEAN FASTCALL KiSwapContextExit(IN PKTHREAD OldThread, IN PKSWITCHFRAME SwitchFrame)
Definition: thrdini.c:209
DECLSPEC_NORETURN VOID KiIdleLoop(VOID)
Definition: thrdini.c:153
VOID NTAPI KiDispatchInterrupt(VOID)
Definition: thrdini.c:295
struct _KSWITCHFRAME KSWITCHFRAME
struct _KSWITCHFRAME * PKSWITCHFRAME
VOID FASTCALL KiSwapContextEntry(IN PKSWITCHFRAME SwitchFrame, IN ULONG_PTR OldThreadAndApcFlag)
Definition: thrdini.c:262
VOID FASTCALL KiSwitchThreads(IN PKTHREAD OldThread, IN PKTHREAD NewThread)
#define DPRINT1
Definition: precomp.h:8
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define APC_LEVEL
Definition: env_spec_w32.h:695
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
VOID FASTCALL HalRequestSoftwareInterrupt(IN KIRQL Irql)
Definition: pic.c:271
VOID FASTCALL HalClearSoftwareInterrupt(IN KIRQL Irql)
Definition: pic.c:282
__in PVOID ContextPointer
Definition: handleapi.cpp:679
void __cdecl _disable(void)
Definition: intrin_arm.h:365
void __cdecl _enable(void)
Definition: intrin_arm.h:373
#define ASSERT(a)
Definition: mode.c:44
#define KernelMode
Definition: asm.h:34
#define UserMode
Definition: asm.h:35
FORCEINLINE struct _KPRCB * KeGetCurrentPrcb(VOID)
Definition: ketypes.h:1080
struct _KIPCR * PKIPCR
VOID(NTAPI * PKSYSTEM_ROUTINE)(PKSTART_ROUTINE StartRoutine, PVOID StartContext)
Definition: ketypes.h:677
@ Running
Definition: ketypes.h:423
struct _KTHREAD * PKTHREAD
Definition: nt_native.h:28
#define CONTEXT_CONTROL
Definition: nt_native.h:1369
#define FASTCALL
Definition: nt_native.h:50
#define DECLSPEC_NORETURN
Definition: ntbasedef.h:176
VOID NTAPI KiThreadStartup(VOID)
Definition: thrdini.c:63
BOOLEAN FASTCALL KiSwapContext(IN KIRQL WaitIrql, IN PKTHREAD CurrentThread)
VOID NTAPI KiQuantumEnd(VOID)
VOID NTAPI KeContextToTrapFrame(PCONTEXT Context, PKEXCEPTION_FRAME ExeptionFrame, PKTRAP_FRAME TrapFrame, ULONG ContextFlags, KPROCESSOR_MODE PreviousMode)
VOID FASTCALL KiRetireDpcList(IN PKPRCB Prcb)
Definition: dpc.c:562
VOID NTAPI KeBugCheckEx(_In_ ULONG BugCheckCode, _In_ ULONG_PTR BugCheckParameter1, _In_ ULONG_PTR BugCheckParameter2, _In_ ULONG_PTR BugCheckParameter3, _In_ ULONG_PTR BugCheckParameter4)
Definition: rtlcompat.c:108
#define YieldProcessor
Definition: ke.h:48
#define KeGetPcr()
Definition: ke.h:26
volatile ULONG DpcQueueDepth
Definition: ketypes.h:798
ULONG64 Return
Definition: ketypes.h:971
KPRCB Prcb
Definition: ketypes.h:894
PVOID PerfGlobalGroupMask
Definition: ketypes.h:745
KSWITCH_FRAME CtxSwitchFrame
Definition: thrdini.c:31
KEXCEPTION_FRAME CtxSwitchFrame
Definition: thrdini.c:33
UCHAR QuantumEnd
Definition: ketypes.h:701
PROCESSOR_POWER_STATE PowerState
Definition: ketypes.h:800
UCHAR DpcRoutineActive
Definition: ketypes.h:693
ULONG KeContextSwitches
Definition: ketypes.h:653
KDPC_DATA DpcData[2]
Definition: ketypes.h:681
struct _KTHREAD * CurrentThread
Definition: ketypes.h:571
struct _KTHREAD * NextThread
Definition: ketypes.h:572
UINT64 TimerRequest
Definition: ketypes.h:696
SINGLE_LIST_ENTRY DeferredReadyListHead
Definition: ketypes.h:633
ULONG_PTR DirectoryTableBase
Definition: ketypes.h:2027
PVOID ExceptionList
Definition: thrdini.c:19
BOOLEAN ApcBypassDisable
Definition: thrdini.c:20
PVOID RetAddr
Definition: thrdini.c:21
ULONG64 Return
Definition: ketypes.h:1053
PVOID InitialStack
Definition: ketypes.h:1604
SHORT SpecialApcDisable
Definition: ketypes.h:1821
PVOID KernelStack
Definition: ketypes.h:1615
UCHAR WaitReason
Definition: ketypes.h:1904
ULONG ContextSwitches
Definition: ketypes.h:1728
KAPC_STATE ApcState
Definition: ketypes.h:1718
volatile UCHAR State
Definition: ketypes.h:1729
KTRAP_FRAME TrapFrame
Definition: thrdini.c:25
KEXCEPTION_FRAME CtxSwitchFrame
Definition: thrdini.c:26
KEXCEPTION_FRAME ExceptionFrame
Definition: thrdini.c:24
KSWITCH_FRAME CtxSwitchFrame
Definition: thrdini.c:22
PPROCESSOR_IDLE_FUNCTION IdleFunction
Definition: potypes.h:68
struct _SINGLE_LIST_ENTRY * Next
Definition: ntbasedef.h:629
#define NTAPI
Definition: typedefs.h:36
void * PVOID
Definition: typedefs.h:50
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define IN
Definition: typedefs.h:39
uint32_t ULONG
Definition: typedefs.h:59
KSTART_ROUTINE * PKSTART_ROUTINE
Definition: ketypes.h:487
@ WrDispatchInt
Definition: ketypes.h:434
_In_ ULONG _In_opt_ POBJECT_ATTRIBUTES _In_opt_ HANDLE _Out_opt_ PCLIENT_ID _In_ PKSTART_ROUTINE StartRoutine
Definition: psfuncs.h:91