ReactOS 0.4.15-dev-7942-gd23573b
thrdini.c File Reference
#include <ntoskrnl.h>
#include <debug.h>
Include dependency graph for thrdini.c:

Go to the source code of this file.

Classes

struct  _KSWITCHFRAME
 
struct  _KUINIT_FRAME
 
struct  _KKINIT_FRAME
 

Macros

#define NDEBUG
 

Typedefs

typedef struct _KSWITCHFRAME KSWITCHFRAME
 
typedef struct _KSWITCHFRAMEPKSWITCHFRAME
 
typedef struct _KUINIT_FRAME KUINIT_FRAME
 
typedef struct _KUINIT_FRAMEPKUINIT_FRAME
 
typedef struct _KKINIT_FRAME KKINIT_FRAME
 
typedef struct _KKINIT_FRAMEPKKINIT_FRAME
 

Functions

VOID NTAPI KiThreadStartup (VOID)
 
VOID FASTCALL KiSwitchThreads (IN PKTHREAD OldThread, IN PKTHREAD NewThread)
 
VOID NTAPI KiInitializeContextThread (IN PKTHREAD Thread, IN PKSYSTEM_ROUTINE SystemRoutine, IN PKSTART_ROUTINE StartRoutine, IN PVOID StartContext, IN PCONTEXT ContextPointer)
 
DECLSPEC_NORETURN VOID KiIdleLoop (VOID)
 
BOOLEAN FASTCALL KiSwapContextExit (IN PKTHREAD OldThread, IN PKSWITCHFRAME SwitchFrame)
 
VOID FASTCALL KiSwapContextEntry (IN PKSWITCHFRAME SwitchFrame, IN ULONG_PTR OldThreadAndApcFlag)
 
VOID NTAPI KiDispatchInterrupt (VOID)
 

Macro Definition Documentation

◆ NDEBUG

#define NDEBUG

Definition at line 12 of file thrdini.c.

Typedef Documentation

◆ KKINIT_FRAME

◆ KSWITCHFRAME

◆ KUINIT_FRAME

◆ PKKINIT_FRAME

◆ PKSWITCHFRAME

◆ PKUINIT_FRAME

Function Documentation

◆ KiDispatchInterrupt()

VOID NTAPI KiDispatchInterrupt ( VOID  )

Definition at line 305 of file thrdini.c.

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}
#define NULL
Definition: types.h:112
#define FALSE
Definition: types.h:117
#define APC_LEVEL
Definition: env_spec_w32.h:695
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
struct _KIPCR * PKIPCR
#define KeGetPcr()
Definition: ketypes.h:81
@ Running
Definition: ketypes.h:390
BOOLEAN FASTCALL KiSwapContext(IN KIRQL WaitIrql, IN PKTHREAD CurrentThread)
VOID NTAPI KiQuantumEnd(VOID)
VOID FASTCALL KiRetireDpcList(IN PKPRCB Prcb)
Definition: dpc.c:562
volatile ULONG DpcQueueDepth
Definition: ketypes.h:858
KPRCB Prcb
Definition: ketypes.h:976
UCHAR QuantumEnd
Definition: ketypes.h:780
KDPC_DATA DpcData[2]
Definition: ketypes.h:760
struct _KTHREAD * CurrentThread
Definition: ketypes.h:650
struct _KTHREAD * NextThread
Definition: ketypes.h:651
UINT64 TimerRequest
Definition: ketypes.h:775
SINGLE_LIST_ENTRY DeferredReadyListHead
Definition: ketypes.h:712
UCHAR WaitReason
Definition: ketypes.h:1964
volatile UCHAR State
Definition: ketypes.h:1789
struct _SINGLE_LIST_ENTRY * Next
Definition: ntbasedef.h:629
@ WrDispatchInt
Definition: ketypes.h:446

Referenced by _HalpDispatchInterruptHandler(), HalpDispatchInterruptHandler(), HalpLowerIrql(), and KiInitializePcr().

◆ KiIdleLoop()

DECLSPEC_NORETURN VOID KiIdleLoop ( VOID  )

Definition at line 153 of file thrdini.c.

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}
#define TRUE
Definition: types.h:120
#define SYNCH_LEVEL
Definition: env_spec_w32.h:704
#define KeLowerIrql(oldIrql)
Definition: env_spec_w32.h:602
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
KIRQL FASTCALL KfRaiseIrql(IN KIRQL NewIrql)
Definition: pic.c:187
VOID FASTCALL HalClearSoftwareInterrupt(IN KIRQL Irql)
Definition: pic.c:282
FORCEINLINE struct _KPRCB * KeGetCurrentPrcb(VOID)
Definition: ketypes.h:1161
#define YieldProcessor
Definition: ke.h:48
PROCESSOR_POWER_STATE PowerState
Definition: ketypes.h:879
PPROCESSOR_IDLE_FUNCTION IdleFunction
Definition: potypes.h:68

◆ KiInitializeContextThread()

VOID NTAPI KiInitializeContextThread ( IN PKTHREAD  Thread,
IN PKSYSTEM_ROUTINE  SystemRoutine,
IN PKSTART_ROUTINE  StartRoutine,
IN PVOID  StartContext,
IN PCONTEXT  ContextPointer 
)

Definition at line 53 of file thrdini.c.

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}
struct _KUINIT_FRAME * PKUINIT_FRAME
struct _KKINIT_FRAME * PKKINIT_FRAME
struct _KKINIT_FRAME KKINIT_FRAME
struct _KUINIT_FRAME KUINIT_FRAME
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
__in PVOID ContextPointer
Definition: handleapi.cpp:679
#define KernelMode
Definition: asm.h:34
#define UserMode
Definition: asm.h:35
#define CONTEXT_CONTROL
Definition: nt_native.h:1369
VOID NTAPI KiThreadStartup(VOID)
Definition: thrdini.c:63
VOID NTAPI KeContextToTrapFrame(PCONTEXT Context, PKEXCEPTION_FRAME ExeptionFrame, PKTRAP_FRAME TrapFrame, ULONG ContextFlags, KPROCESSOR_MODE PreviousMode)
ULONG64 Return
Definition: ketypes.h:1052
KSWITCH_FRAME CtxSwitchFrame
Definition: thrdini.c:31
ULONG64 Return
Definition: ketypes.h:1134
KTRAP_FRAME TrapFrame
Definition: thrdini.c:25
KEXCEPTION_FRAME ExceptionFrame
Definition: thrdini.c:24
KSWITCH_FRAME CtxSwitchFrame
Definition: thrdini.c:22
void * PVOID
Definition: typedefs.h:50
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
uint32_t ULONG
Definition: typedefs.h:59
_In_ ULONG _In_opt_ POBJECT_ATTRIBUTES _In_opt_ HANDLE _Out_opt_ PCLIENT_ID _In_ PKSTART_ROUTINE StartRoutine
Definition: psfuncs.h:91

◆ KiSwapContextEntry()

VOID FASTCALL KiSwapContextEntry ( IN PKSWITCHFRAME  SwitchFrame,
IN ULONG_PTR  OldThreadAndApcFlag 
)

Definition at line 272 of file thrdini.c.

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}
VOID FASTCALL KiSwitchThreads(IN PKTHREAD OldThread, IN PKTHREAD NewThread)
#define DPRINT1
Definition: precomp.h:8
#define ASSERT(a)
Definition: mode.c:44
struct _KTHREAD * PKTHREAD
Definition: nt_native.h:28
PVOID PerfGlobalGroupMask
Definition: ketypes.h:798
ULONG KeContextSwitches
Definition: ketypes.h:732
PVOID KernelStack
Definition: ketypes.h:1675

◆ KiSwapContextExit()

BOOLEAN FASTCALL KiSwapContextExit ( IN PKTHREAD  OldThread,
IN PKSWITCHFRAME  SwitchFrame 
)

Definition at line 219 of file thrdini.c.

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}
FORCEINLINE VOID KeArmTranslationTableRegisterSet(IN ARM_TTB_REGISTER Ttb)
Definition: intrin_i.h:145
VOID FASTCALL HalRequestSoftwareInterrupt(IN KIRQL Irql)
Definition: pic.c:271
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
UCHAR DpcRoutineActive
Definition: ketypes.h:772
ULONG_PTR DirectoryTableBase
Definition: ketypes.h:2087
SHORT SpecialApcDisable
Definition: ketypes.h:1881
ULONG ContextSwitches
Definition: ketypes.h:1788
KAPC_STATE ApcState
Definition: ketypes.h:1778

◆ KiSwitchThreads()

VOID FASTCALL KiSwitchThreads ( IN PKTHREAD  OldThread,
IN PKTHREAD  NewThread 
)

Referenced by KiSwapContextEntry().

◆ KiThreadStartup()

VOID NTAPI KiThreadStartup ( VOID  )

Definition at line 63 of file thrdini.c.

64{
65 PKTRAP_FRAME TrapFrame;
66 PKSTART_FRAME StartFrame;
67 PKUINIT_FRAME InitFrame;
68
69 /* Get the start and trap frames */
70 InitFrame = KeGetCurrentThread()->KernelStack;
71 StartFrame = &InitFrame->StartFrame;
72 TrapFrame = &InitFrame->TrapFrame;
73
74 /* Lower to APC level */
76
77 /* Call the system routine */
78 StartFrame->SystemRoutine(StartFrame->StartRoutine, StartFrame->StartContext);
79
80 /* If we returned, we better be a user thread */
81 if (!StartFrame->UserThread)
82 {
83 KeBugCheck(NO_USER_MODE_CONTEXT);
84 }
85
86 /* Exit to user-mode */
87 KiServiceExit2(TrapFrame);
88}
DECLSPEC_NORETURN VOID NTAPI KeBugCheck(ULONG BugCheckCode)
Definition: bug.c:1430
VOID FASTCALL KfLowerIrql(IN KIRQL NewIrql)
Definition: pic.c:232
#define KeGetCurrentThread
Definition: hal.h:55
#define KiServiceExit2
Definition: ke.h:5
PKSYSTEM_ROUTINE SystemRoutine
Definition: thrdini.c:24
PVOID StartContext
Definition: thrdini.c:26
PKSTART_ROUTINE StartRoutine
Definition: thrdini.c:25
BOOLEAN UserThread
Definition: thrdini.c:27
KSTART_FRAME StartFrame
Definition: thrdini.c:23