Sync with trunk for console graphics palettes.
[reactos.git] / ntoskrnl / ke / powerpc / ctxswitch.c
1 /*
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
6 *
7 * PROGRAMMERS: arty
8 (i386 implementation by Alex Ionescu)
9 */
10
11 /* INCLUDES ******************************************************************/
12
13 #include <ntoskrnl.h>
14 #define NDEBUG
15 #include <debug.h>
16 #include <ppcmmu/mmu.h>
17
18 /*++
19 * KiThreadStartup
20 *
21 * The KiThreadStartup routine is the beginning of any thread.
22 *
23 * Params:
24 * SystemRoutine - Pointer to the System Startup Routine. Either
25 * PspUserThreadStartup or PspSystemThreadStartup
26 *
27 * StartRoutine - For Kernel Threads only, specifies the starting execution
28 * point of the new thread.
29 *
30 * StartContext - For Kernel Threads only, specifies a pointer to variable
31 * context data to be sent to the StartRoutine above.
32 *
33 * UserThread - Indicates whether or not this is a user thread. This tells
34 * us if the thread has a context or not.
35 *
36 * TrapFrame - Pointer to the KTHREAD to which the caller wishes to
37 * switch from.
38 *
39 * Returns:
40 * Should never return for a system thread. Returns through the System Call
41 * Exit Dispatcher for a user thread.
42 *
43 * Remarks:
44 * If a return from a system thread is detected, a bug check will occur.
45 *
46 *--*/
47
48 VOID
49 NTAPI
50 KiThreadStartup(PKSYSTEM_ROUTINE SystemRoutine,
51 PKSTART_ROUTINE StartRoutine,
52 PVOID StartContext,
53 BOOLEAN UserThread,
54 KTRAP_FRAME TrapFrame)
55 {
56 KeLowerIrql(APC_LEVEL);
57 __asm__("mr 0,%0\n\t"
58 "mr 3,%1\n\t"
59 "mr 4,%2\n\t"
60 "mr 5,%3\n\t"
61 "mr 6,%4\n\t"
62 "sc" : :
63 "r" (0xf0000), /* Thread start function */
64 "r" (SystemRoutine),
65 "r" (StartRoutine),
66 "r" (StartContext),
67 "r" (UserThread));
68 PspTerminateThreadByPointer(PsGetCurrentThread(), STATUS_THREAD_IS_TERMINATING, TRUE);
69 }
70
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);
74
75 VOID
76 FASTCALL
77 KiQueueReadyThread(IN PKTHREAD Thread,
78 IN PKPRCB Prcb);
79
80 PKTHREAD KiLastThread = NULL;
81 PKTRAP_FRAME KiLastThreadTrapFrame = NULL;
82
83 VOID
84 NTAPI
85 KiDecrementerTrap(PKTRAP_FRAME TrapFrame)
86 {
87 KIRQL Irql;
88 PKPRCB Prcb = KeGetPcr()->Prcb;
89 if (!KiLastThread)
90 KiLastThread = KeGetCurrentThread();
91
92 if (KiLastThread->State == Running)
93 KiQueueReadyThread(KiLastThread, Prcb);
94
95 if (!KiLastThreadTrapFrame)
96 KiLastThreadTrapFrame = Prcb->IdleThread->TrapFrame;
97
98 TrapFrame->OldIrql = KeGetCurrentIrql();
99 *KiLastThreadTrapFrame = *TrapFrame;
100
101 if (Prcb->NextThread)
102 {
103 Prcb->CurrentThread = Prcb->NextThread;
104 Prcb->NextThread = NULL;
105 }
106 else
107 Prcb->CurrentThread = Prcb->IdleThread;
108
109 Prcb->CurrentThread->State = Running;
110
111 KiLastThreadTrapFrame = Prcb->CurrentThread->TrapFrame;
112 KiLastThread = Prcb->CurrentThread;
113
114 *TrapFrame = *KiLastThreadTrapFrame;
115 Irql = KeGetCurrentIrql();
116
117 if (Irql > TrapFrame->OldIrql)
118 KfRaiseIrql(Irql);
119 else if (Irql < TrapFrame->OldIrql)
120 KfLowerIrql(Irql);
121
122 /* When we return, we'll go through rfi and be in new thread land */
123 __asm__("mtdec %0" : : "r" (0x1000000)); // Reset the trap
124 }