- Set a default PCM volume so that something can be heard when driver is
[AROS.git] / arch / all-unix / kernel / kernel_cpu.c
blobaa5c8a39e9d0887395ae85268cbf90f52fcd7b77
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 "../exec/etask.h"
15 #include "kernel_base.h"
16 #include "kernel_debug.h"
17 #include "kernel_intern.h"
18 #include "kernel_intr.h"
19 #include "kernel_scheduler.h"
21 #define D(x)
24 * Task exception handler.
25 * Exceptions work in a way similar to MinGW32 port. We can't manipulate stack inside
26 * UNIX signal handler, because context's SP is set to a point where it was at the moment
27 * when signal was caught. Signal handler uses some processes' stack space by itself, and
28 * if we try to use some space below SP, we will clobber signal handler's stack.
29 * In order to overcome this we disable interrupts and jump to exception handler. Since
30 * interrupts are disabled, iet_Context of our task still contains original context (saved
31 * at the moment of task switch). In our exception handler we already left the signal handler,
32 * so we can allocate some storage on stack and place our context there. After this we call
33 * exec's Exception().
34 * When we return, we place our saved context back into iet_Context and cause a SysCall (SIGUSR1)
35 * with a special TS_EXCEPT state. SysCall handler will know then that it needs just to dispatch
36 * the same task with the saved context (see cpu_DispatchContext() routine).
38 static void cpu_Exception(void)
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(GetIntETask(task)->iet_Context, 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, GetIntETask(task)->iet_Context, 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 KernelIFace.raise(SIGUSR1);
66 AROS_HOST_BARRIER
69 void cpu_Switch(regs_t *regs)
71 struct Task *task = SysBase->ThisTask;
72 struct AROSCPUContext *ctx = GetIntETask(task)->iet_Context;
74 D(bug("[KRN] cpu_Switch(), task %p (%s)\n", task, task->tc_Node.ln_Name));
75 D(PRINT_SC(regs));
77 SAVEREGS(ctx, regs);
78 ctx->errno_backup = *KernelBase->kb_PlatformData->errnoPtr;
79 task->tc_SPReg = (APTR)SP(regs);
80 core_Switch();
83 void cpu_Dispatch(regs_t *regs)
85 struct Task *task;
86 sigset_t sigs;
88 SIGEMPTYSET(&sigs);
90 while (!(task = core_Dispatch()))
92 /* Sleep almost forever ;) */
93 KernelIFace.sigsuspend(&sigs);
94 AROS_HOST_BARRIER
96 if (SysBase->SysFlags & SFF_SoftInt)
97 core_Cause(INTB_SOFTINT, 1L << INTB_SOFTINT);
100 D(bug("[KRN] cpu_Dispatch(), task %p (%s)\n", task, task->tc_Node.ln_Name));
101 cpu_DispatchContext(task, regs);
104 void cpu_DispatchContext(struct Task *task, regs_t *regs)
106 struct AROSCPUContext *ctx = GetIntETask(task)->iet_Context;
108 RESTOREREGS(ctx, regs);
109 *KernelBase->kb_PlatformData->errnoPtr = ctx->errno_backup;
111 D(PRINT_SC(regs));
113 if (task->tc_Flags & TF_EXCEPT)
115 /* Disable interrupts, otherwise we may lose saved context */
116 SysBase->IDNestCnt = 0;
118 /* Manipulate the current cpu context so Exec_Exception gets
119 excecuted after we leave the kernel resp. the signal handler. */
120 PC(regs) = (IPTR)cpu_Exception;
123 /* Adjust user mode interrupts state */
124 if (SysBase->IDNestCnt < 0) {
125 SC_ENABLE(regs);
126 } else {
127 SC_DISABLE(regs);