3 #include <aros/system.h>
4 #include <exec/types.h>
16 #include <exec/lists.h>
17 #include <exec/execbase.h>
21 #include "kernel_intern.h"
23 #include "host_debug.h"
25 #define IRQ_TIMER (1<<0)
26 #define IRQ_SYSCALL (1<<1)
28 struct ExecBase
**SysBasePtr
;
29 struct KernelBase
**KernelBasePtr
;
31 static int irq_enabled
;
32 static int in_supervisor
;
35 void core_intr_disable(void) {
36 //D(printf("[kernel] disabling interrupts\n"));
40 void core_intr_enable(void) {
41 //D(printf("[kernel] enabling interrupts\n"));
45 int core_is_super(void) {
51 static ucontext_t irq_ctx
;
52 static void *irq_stack
;
54 static unsigned long timer_period
;
56 static ucontext_t idle_ctx
;
58 void core_syscall(syscall_id_t type
) {
59 sigqueue(pid
, SIGUSR1
, (const union sigval
) (int) (IRQ_SYSCALL
| ((type
& 0xffff) << 16)));
62 static void *timer_entry(void *arg
) {
67 sigprocmask(SIG_BLOCK
, &sigset
, NULL
);
70 D(printf("[kernel:timer] sleeping\n"));
72 clock_gettime(CLOCK_REALTIME
, &ts
);
73 ts
.tv_nsec
+= 1000000000 / timer_period
;
74 if (ts
.tv_nsec
> 999999999) {
75 ts
.tv_nsec
-= 1000000000;
78 clock_nanosleep(CLOCK_REALTIME
, TIMER_ABSTIME
, &ts
, NULL
);
80 D(printf("[kernel:timer] timer expiry, triggering timer interrupt\n"));
82 sigqueue(pid
, SIGUSR1
, (const union sigval
) IRQ_TIMER
);
86 static void irq_handler (int irq_bits
) {
89 if (irq_bits
& IRQ_SYSCALL
) {
90 switch ((irq_bits
& 0xffff0000) >> 16) {
92 core_Cause(*SysBasePtr
);
110 core_ExitInterrupt();
114 if (sleep_state
!= ss_RUNNING
) {
115 sleep_state
= ss_SLEEPING
;
117 setcontext(&idle_ctx
);
120 setcontext((ucontext_t
*) GetIntETask((*SysBasePtr
)->ThisTask
)->iet_Context
);
123 static void irq_trampoline (int signo
, siginfo_t
*si
, void *vctx
) {
124 if (!irq_enabled
&& !(si
->si_value
.sival_int
& IRQ_SYSCALL
)) return;
126 getcontext(&irq_ctx
);
127 irq_ctx
.uc_stack
.ss_sp
= irq_stack
;
128 irq_ctx
.uc_stack
.ss_size
= SIGSTKSZ
;
129 irq_ctx
.uc_stack
.ss_flags
= 0;
130 sigemptyset(&irq_ctx
.uc_sigmask
);
131 makecontext(&irq_ctx
, (void (*)()) irq_handler
, 1, si
->si_value
.sival_int
);
133 swapcontext((ucontext_t
*) GetIntETask((*SysBasePtr
)->ThisTask
)->iet_Context
, &irq_ctx
);
136 static void idle_handler (void) {
137 while (1) sleep(UINT_MAX
);
140 int core_init (unsigned long TimerPeriod
, struct ExecBase
**SysBasePointer
, struct KernelBase
**KernelBasePointer
) {
144 pthread_attr_t thread_attrs
;
146 D(printf("[kernel] initialising interrupts and task switching\n"));
148 SysBasePtr
= SysBasePointer
;
149 KernelBasePtr
= KernelBasePointer
;
155 timer_period
= TimerPeriod
;
157 irq_stack
= malloc(SIGSTKSZ
);
161 memset(&sa
, 0, sizeof(sa
));
162 sa
.sa_flags
= SA_SIGINFO
;
163 sa
.sa_sigaction
= irq_trampoline
;
164 sigaction(SIGUSR1
, &sa
, NULL
);
166 getcontext(&idle_ctx
);
167 idle_ctx
.uc_stack
.ss_sp
= malloc(SIGSTKSZ
);
168 idle_ctx
.uc_stack
.ss_size
= SIGSTKSZ
;
169 idle_ctx
.uc_stack
.ss_flags
= 0;
170 makecontext(&idle_ctx
, (void (*)()) idle_handler
, 0);
172 pthread_attr_init(&thread_attrs
);
173 pthread_attr_setdetachstate(&thread_attrs
, PTHREAD_CREATE_DETACHED
);
174 pthread_create(&thread
, &thread_attrs
, timer_entry
, NULL
);
176 D(printf("[kernel] timer started, frequency is %dhz\n", timer_period
));