ReactOS 0.4.15-dev-7924-g5949c20
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#ifdef CONFIG_SMP
197 /* Do the swap at SYNCH_LEVEL */
199#endif
200
201 /* Switch away from the idle thread */
202 KiSwapContext(APC_LEVEL, OldThread);
203
204#ifdef CONFIG_SMP
205 /* Go back to DISPATCH_LEVEL */
207#endif
208 }
209 else
210 {
211 /* Continue staying idle. Note the HAL returns with interrupts on */
212 Prcb->PowerState.IdleFunction(&Prcb->PowerState);
213 }
214 }
215}
216
220 IN PKSWITCHFRAME SwitchFrame)
221{
222 PKIPCR Pcr = (PKIPCR)KeGetPcr();
223 PKPROCESS OldProcess, NewProcess;
224 PKTHREAD NewThread;
225 ARM_TTB_REGISTER TtbRegister;
226
227 /* We are on the new thread stack now */
228 NewThread = Pcr->Prcb.CurrentThread;
229
230 /* Now we are the new thread. Check if it's in a new process */
231 OldProcess = OldThread->ApcState.Process;
232 NewProcess = NewThread->ApcState.Process;
233 if (OldProcess != NewProcess)
234 {
235 TtbRegister.AsUlong = NewProcess->DirectoryTableBase[0];
236 ASSERT(TtbRegister.Reserved == 0);
238 }
239
240 /* Increase thread context switches */
241 NewThread->ContextSwitches++;
242
243 /* DPCs shouldn't be active */
244 if (Pcr->Prcb.DpcRoutineActive)
245 {
246 /* Crash the machine */
247 KeBugCheckEx(ATTEMPTED_SWITCH_FROM_DPC,
248 (ULONG_PTR)OldThread,
249 (ULONG_PTR)NewThread,
250 (ULONG_PTR)OldThread->InitialStack,
251 0);
252 }
253
254 /* Kernel APCs may be pending */
255 if (NewThread->ApcState.KernelApcPending)
256 {
257 /* Are APCs enabled? */
258 if (!NewThread->SpecialApcDisable)
259 {
260 /* Request APC delivery */
261 if (SwitchFrame->ApcBypassDisable) HalRequestSoftwareInterrupt(APC_LEVEL);
262 return TRUE;
263 }
264 }
265
266 /* Return */
267 return FALSE;
268}
269
270VOID
273 IN ULONG_PTR OldThreadAndApcFlag)
274{
275 PKIPCR Pcr = (PKIPCR)KeGetPcr();
276 PKTHREAD OldThread, NewThread;
277
278 /* Save APC bypass disable */
279 SwitchFrame->ApcBypassDisable = OldThreadAndApcFlag & 3;
280
281 /* Increase context switch count and check if tracing is enabled */
282 Pcr->Prcb.KeContextSwitches++;
283#if 0
284 if (Pcr->PerfGlobalGroupMask)
285 {
286 /* We don't support this yet on x86 either */
287 DPRINT1("WMI Tracing not supported\n");
288 ASSERT(FALSE);
289 }
290#endif // 0
291
292 /* Get thread pointers */
293 OldThread = (PKTHREAD)(OldThreadAndApcFlag & ~3);
294 NewThread = Pcr->Prcb.CurrentThread;
295
296 /* Get the old thread and set its kernel stack */
297 OldThread->KernelStack = SwitchFrame;
298
299 /* Do the switch */
300 KiSwitchThreads(OldThread, NewThread->KernelStack);
301}
302
303VOID
304NTAPI
306{
307 PKIPCR Pcr = (PKIPCR)KeGetPcr();
308 PKPRCB Prcb = &Pcr->Prcb;
309 PKTHREAD NewThread, OldThread;
310
311 /* Disable interrupts */
312 _disable();
313
314 /* Check for pending timers, pending DPCs, or pending ready threads */
315 if ((Prcb->DpcData[0].DpcQueueDepth) ||
316 (Prcb->TimerRequest) ||
318 {
319 /* Retire DPCs while under the DPC stack */
320 //KiRetireDpcListInDpcStack(Prcb, Prcb->DpcStack);
321 // FIXME!!! //
322 KiRetireDpcList(Prcb);
323 }
324
325 /* Re-enable interrupts */
326 _enable();
327
328 /* Check for quantum end */
329 if (Prcb->QuantumEnd)
330 {
331 /* Handle quantum end */
332 Prcb->QuantumEnd = FALSE;
333 KiQuantumEnd();
334 }
335 else if (Prcb->NextThread)
336 {
337 /* Acquire the PRCB lock */
338 KiAcquirePrcbLock(Prcb);
339
340 /* Capture current thread data */
341 OldThread = Prcb->CurrentThread;
342 NewThread = Prcb->NextThread;
343
344 /* Set new thread data */
345 Prcb->NextThread = NULL;
346 Prcb->CurrentThread = NewThread;
347
348 /* The thread is now running */
349 NewThread->State = Running;
350 OldThread->WaitReason = WrDispatchInt;
351
352 /* Make the old thread ready */
353 KxQueueReadyThread(OldThread, Prcb);
354
355 /* Swap to the new thread */
356 KiSwapContext(APC_LEVEL, OldThread);
357 }
358}
359
360/* 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:219
DECLSPEC_NORETURN VOID KiIdleLoop(VOID)
Definition: thrdini.c:153
VOID NTAPI KiDispatchInterrupt(VOID)
Definition: thrdini.c:305
struct _KSWITCHFRAME KSWITCHFRAME
struct _KSWITCHFRAME * PKSWITCHFRAME
VOID FASTCALL KiSwapContextEntry(IN PKSWITCHFRAME SwitchFrame, IN ULONG_PTR OldThreadAndApcFlag)
Definition: thrdini.c:272
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 SYNCH_LEVEL
Definition: env_spec_w32.h:704
#define APC_LEVEL
Definition: env_spec_w32.h:695
#define KeLowerIrql(oldIrql)
Definition: env_spec_w32.h:602
#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
KIRQL FASTCALL KfRaiseIrql(IN KIRQL NewIrql)
Definition: pic.c:187
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
FORCEINLINE VOID KiAcquirePrcbLock(IN PKPRCB Prcb)
Definition: ke_x.h:220
#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:1146
struct _KIPCR * PKIPCR
#define KeGetPcr()
Definition: ketypes.h:81
VOID(NTAPI * PKSYSTEM_ROUTINE)(PKSTART_ROUTINE StartRoutine, PVOID StartContext)
Definition: ketypes.h:737
@ Running
Definition: ketypes.h:390
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
volatile ULONG DpcQueueDepth
Definition: ketypes.h:858
ULONG64 Return
Definition: ketypes.h:1037
KPRCB Prcb
Definition: ketypes.h:961
PVOID PerfGlobalGroupMask
Definition: ketypes.h:798
KSWITCH_FRAME CtxSwitchFrame
Definition: thrdini.c:31
KEXCEPTION_FRAME CtxSwitchFrame
Definition: thrdini.c:33
UCHAR QuantumEnd
Definition: ketypes.h:765
PROCESSOR_POWER_STATE PowerState
Definition: ketypes.h:864
UCHAR DpcRoutineActive
Definition: ketypes.h:757
ULONG KeContextSwitches
Definition: ketypes.h:717
KDPC_DATA DpcData[2]
Definition: ketypes.h:745
struct _KTHREAD * CurrentThread
Definition: ketypes.h:635
struct _KTHREAD * NextThread
Definition: ketypes.h:636
UINT64 TimerRequest
Definition: ketypes.h:760
SINGLE_LIST_ENTRY DeferredReadyListHead
Definition: ketypes.h:697
ULONG_PTR DirectoryTableBase
Definition: ketypes.h:2087
PVOID ExceptionList
Definition: thrdini.c:19
BOOLEAN ApcBypassDisable
Definition: thrdini.c:20
PVOID RetAddr
Definition: thrdini.c:21
ULONG64 Return
Definition: ketypes.h:1119
PVOID InitialStack
Definition: ketypes.h:1664
SHORT SpecialApcDisable
Definition: ketypes.h:1881
PVOID KernelStack
Definition: ketypes.h:1675
UCHAR WaitReason
Definition: ketypes.h:1964
ULONG ContextSwitches
Definition: ketypes.h:1788
KAPC_STATE ApcState
Definition: ketypes.h:1778
volatile UCHAR State
Definition: ketypes.h:1789
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:499
@ WrDispatchInt
Definition: ketypes.h:446
_In_ ULONG _In_opt_ POBJECT_ATTRIBUTES _In_opt_ HANDLE _Out_opt_ PCLIENT_ID _In_ PKSTART_ROUTINE StartRoutine
Definition: psfuncs.h:91