2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/ke/i386/ctxswitch.S
5 * PURPOSE: Thread Context Switching
8 (i386 implementation by Alex Ionescu)
11 /* INCLUDES ******************************************************************/
16 #include <ppcmmu/mmu.h>
21 * The KiThreadStartup routine is the beginning of any thread.
24 * SystemRoutine - Pointer to the System Startup Routine. Either
25 * PspUserThreadStartup or PspSystemThreadStartup
27 * StartRoutine - For Kernel Threads only, specifies the starting execution
28 * point of the new thread.
30 * StartContext - For Kernel Threads only, specifies a pointer to variable
31 * context data to be sent to the StartRoutine above.
33 * UserThread - Indicates whether or not this is a user thread. This tells
34 * us if the thread has a context or not.
36 * TrapFrame - Pointer to the KTHREAD to which the caller wishes to
40 * Should never return for a system thread. Returns through the System Call
41 * Exit Dispatcher for a user thread.
44 * If a return from a system thread is detected, a bug check will occur.
50 KiThreadStartup(PKSYSTEM_ROUTINE SystemRoutine
,
51 PKSTART_ROUTINE StartRoutine
,
54 KTRAP_FRAME TrapFrame
)
56 KeLowerIrql(APC_LEVEL
);
63 "r" (0xf0000), /* Thread start function */
68 PspTerminateThreadByPointer(PsGetCurrentThread(), STATUS_THREAD_IS_TERMINATING
, TRUE
);
71 /* Take a decrementer trap, and prepare the given trap frame, swapping
72 * process and thread context as appropriate. */
73 VOID
KiDecrementerTrapFinish(PKTRAP_FRAME TrapFrame
);
77 KiQueueReadyThread(IN PKTHREAD Thread
,
80 PKTHREAD KiLastThread
= NULL
;
81 PKTRAP_FRAME KiLastThreadTrapFrame
= NULL
;
85 KiDecrementerTrap(PKTRAP_FRAME TrapFrame
)
88 PKPRCB Prcb
= KeGetPcr()->Prcb
;
90 KiLastThread
= KeGetCurrentThread();
92 if (KiLastThread
->State
== Running
)
93 KiQueueReadyThread(KiLastThread
, Prcb
);
95 if (!KiLastThreadTrapFrame
)
96 KiLastThreadTrapFrame
= Prcb
->IdleThread
->TrapFrame
;
98 TrapFrame
->OldIrql
= KeGetCurrentIrql();
99 *KiLastThreadTrapFrame
= *TrapFrame
;
101 if (Prcb
->NextThread
)
103 Prcb
->CurrentThread
= Prcb
->NextThread
;
104 Prcb
->NextThread
= NULL
;
107 Prcb
->CurrentThread
= Prcb
->IdleThread
;
109 Prcb
->CurrentThread
->State
= Running
;
111 KiLastThreadTrapFrame
= Prcb
->CurrentThread
->TrapFrame
;
112 KiLastThread
= Prcb
->CurrentThread
;
114 *TrapFrame
= *KiLastThreadTrapFrame
;
115 Irql
= KeGetCurrentIrql();
117 if (Irql
> TrapFrame
->OldIrql
)
119 else if (Irql
< TrapFrame
->OldIrql
)
122 /* When we return, we'll go through rfi and be in new thread land */
123 __asm__("mtdec %0" : : "r" (0x1000000)); // Reset the trap