revert between 56095 -> 55830 in arch
[AROS.git] / arch / all-unix / kernel / kernel_cpu.c
blobe899bd9905ca0eab8f261b3ac223a6741309706e
1 /*
2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #include <exec/alerts.h>
7 #include <exec/execbase.h>
8 #include <hardware/intbits.h>
9 #include <proto/exec.h>
11 #include <unistd.h>
13 #include "kernel_base.h"
14 #include "kernel_debug.h"
15 #include "kernel_globals.h"
16 #include "kernel_intern.h"
17 #include "kernel_intr.h"
18 #include "kernel_scheduler.h"
20 #define D(x)
23 * Task exception handler.
24 * Exceptions work in a way similar to MinGW32 port. We can't manipulate stack inside
25 * UNIX signal handler, because context's SP is set to a point where it was at the moment
26 * when signal was caught. Signal handler uses some processes' stack space by itself, and
27 * if we try to use some space below SP, we will clobber signal handler's stack.
28 * In order to overcome this we disable interrupts and jump to exception handler. Since
29 * interrupts are disabled, et_RegFrame of our task still contains original context (saved
30 * at the moment of task switch). In our exception handler we already left the signal handler,
31 * so we can allocate some storage on stack and place our context there. After this we call
32 * exec's Exception().
33 * When we return, we place our saved context back into et_RegFrame and cause a SysCall (SIGUSR1)
34 * with a special TS_EXCEPT state. SysCall handler will know then that it needs just to dispatch
35 * the same task with the saved context (see cpu_DispatchContext() routine).
37 static void cpu_Exception(void)
39 struct KernelBase *KernelBase = getKernelBase();
40 /* Save return context and IDNestCnt on stack */
41 struct Task *task = SysBase->ThisTask;
42 char nestCnt = task->tc_IDNestCnt;
43 char save[KernelBase->kb_ContextSize];
44 APTR savesp;
46 /* Save original context */
47 CopyMem(task->tc_UnionETask.tc_ETask->et_RegFrame, save, KernelBase->kb_ContextSize);
48 savesp = task->tc_SPReg;
50 Exception();
52 /* Restore saved task state and resume it. Note that interrupts are
53 disabled again here */
54 task->tc_IDNestCnt = nestCnt;
55 SysBase->IDNestCnt = nestCnt;
57 /* Restore saved context */
58 CopyMem(save, task->tc_UnionETask.tc_ETask->et_RegFrame, KernelBase->kb_ContextSize);
59 task->tc_SPReg = savesp;
61 /* This tells task switcher that we are returning from the exception */
62 SysBase->ThisTask->tc_State = TS_EXCEPT;
64 /* System call */
65 KernelBase->kb_PlatformData->iface->raise(SIGUSR1);
66 AROS_HOST_BARRIER
69 void cpu_Switch(regs_t *regs)
71 struct KernelBase *KernelBase = getKernelBase();
72 struct Task *task = SysBase->ThisTask;
73 struct AROSCPUContext *ctx = task->tc_UnionETask.tc_ETask->et_RegFrame;
75 D(bug("[KRN] cpu_Switch(), task %p (%s)\n", task, task->tc_Node.ln_Name));
76 D(PRINT_SC(regs));
78 SAVEREGS(ctx, regs);
79 ctx->errno_backup = *KernelBase->kb_PlatformData->errnoPtr;
80 task->tc_SPReg = (APTR)SP(regs);
81 core_Switch();
84 void cpu_Dispatch(regs_t *regs)
86 struct KernelBase *KernelBase = getKernelBase();
87 struct PlatformData *pd = KernelBase->kb_PlatformData;
88 struct Task *task;
89 sigset_t sigs;
91 /* This macro relies on 'pd' being present */
92 SIGEMPTYSET(&sigs);
94 while (!(task = core_Dispatch()))
96 /* Sleep almost forever ;) */
97 KernelBase->kb_PlatformData->iface->sigsuspend(&sigs);
98 AROS_HOST_BARRIER
100 if (SysBase->SysFlags & SFF_SoftInt)
101 core_Cause(INTB_SOFTINT, 1L << INTB_SOFTINT);
104 D(bug("[KRN] cpu_Dispatch(), task %p (%s)\n", task, task->tc_Node.ln_Name));
105 cpu_DispatchContext(task, regs, pd);
108 void cpu_DispatchContext(struct Task *task, regs_t *regs, struct PlatformData *pd)
110 struct AROSCPUContext *ctx = task->tc_UnionETask.tc_ETask->et_RegFrame;
112 RESTOREREGS(ctx, regs);
113 *pd->errnoPtr = ctx->errno_backup;
115 D(PRINT_SC(regs));
117 if (task->tc_Flags & TF_EXCEPT)
119 /* Disable interrupts, otherwise we may lose saved context */
120 SysBase->IDNestCnt = 0;
122 /* Manipulate the current cpu context so Exec_Exception gets
123 excecuted after we leave the kernel resp. the signal handler. */
124 PC(regs) = (IPTR)cpu_Exception;
128 * Adjust user mode interrupts state.
129 * Brackets MUST present, these are complex macros.
131 if (SysBase->IDNestCnt < 0)
133 SC_ENABLE(regs);
135 else
137 SC_DISABLE(regs);