2013-03-06 10:29:49 +01:00
|
|
|
/**
|
|
|
|
* Native CPU irq.h implementation
|
|
|
|
*
|
|
|
|
* Copyright (C) 2013 Ludwig Ortmann
|
|
|
|
*
|
2013-06-18 17:21:38 +02:00
|
|
|
* This file subject to the terms and conditions of the GNU Lesser General
|
|
|
|
* Public License. See the file LICENSE in the top level directory for more
|
|
|
|
* details.
|
2013-03-06 10:29:49 +01:00
|
|
|
*
|
2013-03-13 21:56:56 +01:00
|
|
|
* @ingroup native_cpu
|
|
|
|
* @ingroup irq
|
2013-03-06 10:29:49 +01:00
|
|
|
* @{
|
|
|
|
* @file
|
|
|
|
* @author Ludwig Ortmann <ludwig.ortmann@fu-berlin.de>
|
|
|
|
*/
|
2013-03-06 01:08:15 +01:00
|
|
|
#include <err.h>
|
2013-05-14 18:31:47 +02:00
|
|
|
#include <string.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
|
2013-06-03 13:10:42 +02:00
|
|
|
// __USE_GNU for gregs[REG_EIP] access under Linux
|
2013-05-14 18:31:47 +02:00
|
|
|
#define __USE_GNU
|
|
|
|
#include <signal.h>
|
|
|
|
#undef __USE_GNU
|
2013-03-06 01:08:15 +01:00
|
|
|
|
2013-05-14 18:31:47 +02:00
|
|
|
#include "irq.h"
|
2013-03-06 01:08:15 +01:00
|
|
|
#include "cpu.h"
|
|
|
|
|
|
|
|
#include "debug.h"
|
|
|
|
|
|
|
|
static int native_interrupts_enabled;
|
|
|
|
|
2013-05-14 18:31:47 +02:00
|
|
|
int _native_sigpend;
|
|
|
|
int _native_in_isr;
|
|
|
|
int _native_in_syscall;
|
|
|
|
static ucontext_t native_isr_context;
|
2013-03-06 01:08:15 +01:00
|
|
|
static sigset_t native_sig_set;
|
|
|
|
static char __isr_stack[SIGSTKSZ];
|
|
|
|
extern volatile tcb_t *active_thread;
|
|
|
|
|
2013-05-14 18:31:47 +02:00
|
|
|
unsigned int _native_saved_eip;
|
|
|
|
ucontext_t *_native_cur_ctx, *_native_isr_ctx;
|
|
|
|
int _native_in_isr;
|
|
|
|
|
|
|
|
static int pipefd[2];
|
|
|
|
|
2013-03-06 01:08:15 +01:00
|
|
|
struct int_handler_t {
|
|
|
|
void (*func)(void);
|
|
|
|
};
|
|
|
|
static struct int_handler_t native_irq_handlers[255];
|
2013-05-14 18:31:47 +02:00
|
|
|
char sigalt_stk[SIGSTKSZ];
|
2013-04-15 20:08:46 +02:00
|
|
|
|
|
|
|
void print_thread_sigmask(ucontext_t *cp)
|
|
|
|
{
|
|
|
|
sigset_t *p = &cp->uc_sigmask;
|
2013-06-21 03:52:57 +02:00
|
|
|
|
|
|
|
if(sigemptyset(p) == -1) {
|
2013-04-15 20:08:46 +02:00
|
|
|
err(1, "print_thread_sigmask: sigemptyset");
|
|
|
|
}
|
|
|
|
|
2013-06-21 03:52:57 +02:00
|
|
|
for(int i = 1; i < (NSIG); i++) {
|
|
|
|
if(native_irq_handlers[i].func != NULL) {
|
2013-04-15 20:08:46 +02:00
|
|
|
printf("%s: %s\n",
|
2013-06-21 03:52:57 +02:00
|
|
|
strsignal(i),
|
|
|
|
(sigismember(&native_sig_set, i) ? "blocked" : "unblocked")
|
2013-04-15 20:08:46 +02:00
|
|
|
);
|
|
|
|
}
|
2013-06-21 03:52:57 +02:00
|
|
|
|
|
|
|
if(sigismember(p, i)) {
|
2013-04-15 20:08:46 +02:00
|
|
|
printf("%s: pending\n", strsignal(i));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void print_sigmasks(void)
|
|
|
|
{
|
|
|
|
ucontext_t *p;
|
|
|
|
//tcb_t *cb = NULL;
|
|
|
|
|
2013-06-21 03:52:57 +02:00
|
|
|
for(int i = 0; i < MAXTHREADS; i++) {
|
|
|
|
if(sched_threads[i] != NULL) {
|
2013-04-15 20:08:46 +02:00
|
|
|
printf("%s:\n", sched_threads[i]->name);
|
|
|
|
//print_thread_sigmask(sched_threads[i]->sp);
|
2013-06-21 03:52:57 +02:00
|
|
|
p = (ucontext_t *)(sched_threads[i]->stack_start);
|
2013-04-15 20:08:46 +02:00
|
|
|
print_thread_sigmask(p);
|
|
|
|
puts("");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void native_print_signals()
|
|
|
|
{
|
|
|
|
sigset_t p, q;
|
|
|
|
puts("native signals:\n");
|
2013-06-21 03:52:57 +02:00
|
|
|
|
|
|
|
if(sigemptyset(&p) == -1) {
|
2013-04-15 20:08:46 +02:00
|
|
|
err(1, "native_print_signals: sigemptyset");
|
|
|
|
}
|
2013-06-21 03:52:57 +02:00
|
|
|
|
|
|
|
if(sigpending(&p) == -1) {
|
2013-04-15 20:08:46 +02:00
|
|
|
err(1, "native_print_signals: sigpending");
|
|
|
|
}
|
2013-06-21 03:52:57 +02:00
|
|
|
|
|
|
|
if(sigprocmask(SIG_SETMASK, NULL, &q) == -1) {
|
2013-04-15 20:08:46 +02:00
|
|
|
err(1, "native_print_signals(): sigprocmask");
|
|
|
|
}
|
|
|
|
|
2013-06-21 03:52:57 +02:00
|
|
|
for(int i = 1; i < (NSIG); i++) {
|
|
|
|
if(native_irq_handlers[i].func != NULL || i == SIGUSR1) {
|
2013-05-21 10:53:59 +02:00
|
|
|
printf("%s: %s in active thread\n",
|
2013-06-21 03:52:57 +02:00
|
|
|
strsignal(i),
|
|
|
|
(sigismember(&native_sig_set, i) ? "blocked" : "unblocked")
|
2013-04-15 20:08:46 +02:00
|
|
|
);
|
|
|
|
}
|
2013-06-21 03:52:57 +02:00
|
|
|
|
|
|
|
if(sigismember(&p, i)) {
|
2013-04-15 20:08:46 +02:00
|
|
|
printf("%s: pending\n", strsignal(i));
|
|
|
|
}
|
2013-06-21 03:52:57 +02:00
|
|
|
|
|
|
|
if(sigismember(&q, i)) {
|
2013-05-21 10:53:59 +02:00
|
|
|
printf("%s: blocked in this context\n", strsignal(i));
|
2013-04-15 20:08:46 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-13 21:56:56 +01:00
|
|
|
/**
|
|
|
|
* block signals
|
|
|
|
*/
|
2013-03-06 01:08:15 +01:00
|
|
|
unsigned disableIRQ(void)
|
|
|
|
{
|
|
|
|
unsigned int prev_state;
|
|
|
|
sigset_t mask;
|
|
|
|
|
2013-05-14 18:31:47 +02:00
|
|
|
_native_in_syscall = 1;
|
2013-03-06 01:08:15 +01:00
|
|
|
DEBUG("disableIRQ()\n");
|
|
|
|
|
2013-06-21 03:52:57 +02:00
|
|
|
if(sigfillset(&mask) == -1) {
|
2013-03-06 01:08:15 +01:00
|
|
|
err(1, "disableIRQ(): sigfillset");
|
|
|
|
}
|
2013-06-21 03:52:57 +02:00
|
|
|
|
|
|
|
if(native_interrupts_enabled == 1) {
|
2013-03-21 16:55:57 +01:00
|
|
|
DEBUG("sigprocmask(..native_sig_set)\n");
|
2013-06-21 03:52:57 +02:00
|
|
|
|
|
|
|
if(sigprocmask(SIG_SETMASK, &mask, &native_sig_set) == -1) {
|
2013-03-06 01:08:15 +01:00
|
|
|
err(1, "disableIRQ(): sigprocmask");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2013-03-21 16:55:57 +01:00
|
|
|
DEBUG("sigprocmask()\n");
|
2013-06-21 03:52:57 +02:00
|
|
|
|
|
|
|
if(sigprocmask(SIG_SETMASK, &mask, NULL) == -1) {
|
2013-03-06 01:08:15 +01:00
|
|
|
err(1, "disableIRQ(): sigprocmask()");
|
|
|
|
}
|
|
|
|
}
|
2013-06-21 03:52:57 +02:00
|
|
|
|
2013-03-06 01:08:15 +01:00
|
|
|
prev_state = native_interrupts_enabled;
|
|
|
|
native_interrupts_enabled = 0;
|
2013-06-21 03:52:57 +02:00
|
|
|
|
|
|
|
if(_native_sigpend > 0) {
|
2013-05-14 18:31:47 +02:00
|
|
|
DEBUG("\n\n\t\treturn from syscall, calling native_irq_handler\n\n");
|
|
|
|
_native_in_syscall = 0;
|
|
|
|
printf("calling swapcontext()\n");
|
|
|
|
swapcontext(_native_cur_ctx, _native_isr_ctx);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
_native_in_syscall = 0;
|
|
|
|
}
|
2013-06-21 03:52:57 +02:00
|
|
|
|
2013-05-14 18:31:47 +02:00
|
|
|
DEBUG("disableIRQ(): return\n");
|
2013-03-06 01:08:15 +01:00
|
|
|
|
|
|
|
return prev_state;
|
|
|
|
}
|
|
|
|
|
2013-03-13 21:56:56 +01:00
|
|
|
/**
|
|
|
|
* unblock signals
|
|
|
|
*/
|
2013-03-06 01:08:15 +01:00
|
|
|
unsigned enableIRQ(void)
|
|
|
|
{
|
|
|
|
unsigned int prev_state;
|
|
|
|
|
2013-05-14 18:31:47 +02:00
|
|
|
_native_in_syscall = 1;
|
2013-03-06 01:08:15 +01:00
|
|
|
DEBUG("enableIRQ()\n");
|
|
|
|
|
2013-06-21 03:52:57 +02:00
|
|
|
if(sigprocmask(SIG_SETMASK, &native_sig_set, NULL) == -1) {
|
2013-03-06 01:08:15 +01:00
|
|
|
err(1, "enableIRQ(): sigprocmask()");
|
|
|
|
}
|
2013-06-21 03:52:57 +02:00
|
|
|
|
2013-03-06 01:08:15 +01:00
|
|
|
prev_state = native_interrupts_enabled;
|
|
|
|
native_interrupts_enabled = 1;
|
|
|
|
|
2013-04-15 20:08:46 +02:00
|
|
|
//print_sigmasks();
|
|
|
|
//native_print_signals();
|
2013-06-21 03:52:57 +02:00
|
|
|
if(_native_sigpend > 0) {
|
2013-05-14 18:31:47 +02:00
|
|
|
DEBUG("\n\n\t\treturn from syscall, calling native_irq_handler\n\n");
|
|
|
|
_native_in_syscall = 0;
|
|
|
|
printf("calling swapcontext()\n");
|
|
|
|
swapcontext(_native_cur_ctx, _native_isr_ctx);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
_native_in_syscall = 0;
|
|
|
|
}
|
2013-06-21 03:52:57 +02:00
|
|
|
|
2013-05-14 18:31:47 +02:00
|
|
|
DEBUG("enableIRQ(): return\n");
|
2013-04-15 20:08:46 +02:00
|
|
|
|
2013-03-06 01:08:15 +01:00
|
|
|
return prev_state;
|
|
|
|
}
|
|
|
|
|
|
|
|
void restoreIRQ(unsigned state)
|
|
|
|
{
|
|
|
|
DEBUG("restoreIRQ()\n");
|
|
|
|
|
2013-06-21 03:52:57 +02:00
|
|
|
if(state == 1) {
|
2013-03-06 01:08:15 +01:00
|
|
|
enableIRQ();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
disableIRQ();
|
|
|
|
}
|
2013-06-21 03:52:57 +02:00
|
|
|
|
2013-03-06 01:08:15 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
int inISR(void)
|
|
|
|
{
|
2013-05-14 18:31:47 +02:00
|
|
|
DEBUG("inISR(): %i\n", _native_in_isr);
|
|
|
|
return _native_in_isr;
|
2013-03-06 01:08:15 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void dINT(void)
|
|
|
|
{
|
|
|
|
disableIRQ();
|
|
|
|
}
|
|
|
|
|
|
|
|
void eINT(void)
|
|
|
|
{
|
|
|
|
enableIRQ();
|
|
|
|
}
|
|
|
|
|
2013-05-14 18:31:47 +02:00
|
|
|
int _native_popsig(void)
|
|
|
|
{
|
|
|
|
int nread, nleft, i;
|
|
|
|
int sig;
|
|
|
|
|
|
|
|
nleft = sizeof(int);
|
|
|
|
i = 0;
|
2013-06-21 03:52:57 +02:00
|
|
|
|
|
|
|
while((nleft > 0) && ((nread = read(pipefd[0], &sig + i, nleft)) != -1)) {
|
2013-05-14 18:31:47 +02:00
|
|
|
i += nread;
|
|
|
|
nleft -= nread;
|
|
|
|
}
|
2013-06-21 03:52:57 +02:00
|
|
|
|
|
|
|
if(nread == -1) {
|
2013-05-14 18:31:47 +02:00
|
|
|
err(1, "_native_popsig(): read()");
|
|
|
|
}
|
|
|
|
|
|
|
|
return sig;
|
|
|
|
}
|
|
|
|
|
2013-03-06 01:08:15 +01:00
|
|
|
/**
|
2013-05-14 18:31:47 +02:00
|
|
|
* call signal handlers,
|
2013-03-06 01:08:15 +01:00
|
|
|
* restore user context
|
|
|
|
*/
|
|
|
|
void native_irq_handler()
|
|
|
|
{
|
2013-05-14 18:31:47 +02:00
|
|
|
int sig;
|
|
|
|
|
|
|
|
DEBUG("\n\n\t\tnative_irq_handler\n\n");
|
2013-06-21 03:52:57 +02:00
|
|
|
|
|
|
|
while(_native_sigpend > 0) {
|
2013-05-14 18:31:47 +02:00
|
|
|
|
|
|
|
sig = _native_popsig();
|
|
|
|
_native_sigpend--;
|
|
|
|
|
2013-06-21 03:52:57 +02:00
|
|
|
if(native_irq_handlers[sig].func != NULL) {
|
2013-05-14 18:31:47 +02:00
|
|
|
DEBUG("calling interrupt handler for %i\n", sig);
|
|
|
|
native_irq_handlers[sig].func();
|
|
|
|
}
|
2013-06-21 03:52:57 +02:00
|
|
|
else if(sig == SIGUSR1) {
|
2013-05-14 18:31:47 +02:00
|
|
|
DEBUG("ignoring SIGUSR1\n");
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
printf("XXX: no handler for signal %i\n", sig);
|
|
|
|
errx(1, "XXX: this should not have happened!\n");
|
|
|
|
}
|
2013-03-06 01:08:15 +01:00
|
|
|
}
|
2013-06-21 03:52:57 +02:00
|
|
|
|
2013-05-14 18:31:47 +02:00
|
|
|
DEBUG("native_irq_handler(): return");
|
|
|
|
_native_in_isr = 0;
|
2013-03-06 01:08:15 +01:00
|
|
|
cpu_switch_context_exit();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2013-05-14 18:31:47 +02:00
|
|
|
* save signal, return to _native_sig_leave_tramp if possible
|
2013-03-06 01:08:15 +01:00
|
|
|
*/
|
|
|
|
void native_isr_entry(int sig, siginfo_t *info, void *context)
|
|
|
|
{
|
2013-05-14 18:31:47 +02:00
|
|
|
DEBUG("\n\n\t\tnative_isr_entry\n\n");
|
2013-06-21 03:52:57 +02:00
|
|
|
|
|
|
|
if(native_interrupts_enabled == 0) {
|
2013-05-14 18:31:47 +02:00
|
|
|
errx(1, "interrupts are off, but I caught a signal.");
|
|
|
|
}
|
2013-03-06 01:08:15 +01:00
|
|
|
|
|
|
|
/* save the signal */
|
2013-06-21 03:52:57 +02:00
|
|
|
if(write(pipefd[1], &sig, sizeof(int)) == -1) {
|
2013-05-14 18:31:47 +02:00
|
|
|
err(1, "native_isr_entry(): write()");
|
|
|
|
}
|
2013-06-21 03:52:57 +02:00
|
|
|
|
2013-05-14 18:31:47 +02:00
|
|
|
_native_sigpend++;
|
2013-03-06 01:08:15 +01:00
|
|
|
/* indicate irs status */
|
2013-06-21 03:52:57 +02:00
|
|
|
|
2013-05-14 18:31:47 +02:00
|
|
|
makecontext(&native_isr_context, native_irq_handler, 0);
|
2013-06-21 03:52:57 +02:00
|
|
|
_native_cur_ctx = (ucontext_t *)active_thread->sp;
|
2013-03-06 01:08:15 +01:00
|
|
|
|
2013-06-21 03:52:57 +02:00
|
|
|
if(_native_in_syscall == 0) {
|
2013-05-14 18:31:47 +02:00
|
|
|
_native_in_isr = 1;
|
|
|
|
DEBUG("\n\n\t\treturn to _native_sig_leave_tramp\n\n");
|
2013-05-15 17:45:43 +02:00
|
|
|
#ifdef __MACH__
|
2013-06-21 03:52:57 +02:00
|
|
|
_native_saved_eip = ((ucontext_t *)context)->uc_mcontext->__ss.__eip;
|
|
|
|
((ucontext_t *)context)->uc_mcontext->__ss.__eip = (unsigned int)&_native_sig_leave_tramp;
|
2013-06-03 13:23:57 +02:00
|
|
|
#elif BSD
|
2013-06-21 03:52:57 +02:00
|
|
|
_native_saved_eip = ((struct sigcontext *)context)->sc_eip;
|
|
|
|
((struct sigcontext *)context)->sc_eip = (unsigned int)&_native_sig_leave_tramp;
|
2013-05-15 17:45:43 +02:00
|
|
|
#else
|
2013-06-21 03:52:57 +02:00
|
|
|
_native_saved_eip = ((ucontext_t *)context)->uc_mcontext.gregs[REG_EIP];
|
|
|
|
((ucontext_t *)context)->uc_mcontext.gregs[REG_EIP] = (unsigned int)&_native_sig_leave_tramp;
|
2013-05-15 17:45:43 +02:00
|
|
|
#endif
|
2013-05-14 18:31:47 +02:00
|
|
|
// TODO: change sigmask?
|
2013-03-06 01:08:15 +01:00
|
|
|
}
|
|
|
|
else {
|
2013-05-14 18:31:47 +02:00
|
|
|
DEBUG("\n\n\t\treturn to syscall\n\n");
|
2013-03-06 01:08:15 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2013-03-13 21:56:56 +01:00
|
|
|
* register signal/interrupt handler for signal sig
|
|
|
|
*
|
2013-03-06 01:08:15 +01:00
|
|
|
* TODO: check sa_flags for appropriateness
|
2013-03-13 21:56:56 +01:00
|
|
|
* TODO: use appropriate data structure for signal
|
2013-03-06 01:08:15 +01:00
|
|
|
* handlers.
|
|
|
|
*/
|
|
|
|
int register_interrupt(int sig, void *handler)
|
|
|
|
{
|
|
|
|
struct sigaction sa;
|
|
|
|
DEBUG("XXX: register_interrupt()\n");
|
|
|
|
|
2013-06-21 03:52:57 +02:00
|
|
|
if(sigdelset(&native_sig_set, sig)) {
|
2013-04-15 20:08:46 +02:00
|
|
|
err(1, "register_interrupt: sigdelset");
|
2013-03-06 01:08:15 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
native_irq_handlers[sig].func = handler;
|
|
|
|
|
2013-06-21 03:52:57 +02:00
|
|
|
sa.sa_sigaction = (void *) native_isr_entry;
|
2013-04-15 20:08:46 +02:00
|
|
|
/* sa.sa_handler = (void*) native_isr_entry; */
|
2013-03-06 01:08:15 +01:00
|
|
|
|
2013-06-21 03:52:57 +02:00
|
|
|
if(sigemptyset(&sa.sa_mask) == -1) {
|
2013-03-06 01:08:15 +01:00
|
|
|
err(1, "register_interrupt: sigemptyset");
|
|
|
|
}
|
|
|
|
|
2013-05-14 18:31:47 +02:00
|
|
|
sa.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
|
2013-03-06 01:08:15 +01:00
|
|
|
|
2013-06-21 03:52:57 +02:00
|
|
|
if(sigaction(sig, &sa, NULL)) {
|
2013-03-06 01:08:15 +01:00
|
|
|
err(1, "register_interrupt: sigaction");
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2013-03-13 21:56:56 +01:00
|
|
|
* empty signal mask
|
|
|
|
*
|
2013-03-06 01:08:15 +01:00
|
|
|
* TODO: see register_interrupt
|
|
|
|
* TODO: ignore signal
|
|
|
|
*/
|
|
|
|
int unregister_interrupt(int sig)
|
|
|
|
{
|
|
|
|
struct sigaction sa;
|
|
|
|
DEBUG("XXX: unregister_interrupt()\n");
|
|
|
|
|
2013-06-21 03:52:57 +02:00
|
|
|
if(sigaddset(&native_sig_set, sig) == -1) {
|
2013-04-15 20:08:46 +02:00
|
|
|
err(1, "unregister_interrupt: sigaddset");
|
2013-03-06 01:08:15 +01:00
|
|
|
}
|
2013-06-21 03:52:57 +02:00
|
|
|
|
2013-03-06 01:08:15 +01:00
|
|
|
native_irq_handlers[sig].func = NULL;
|
|
|
|
|
2013-04-15 20:08:46 +02:00
|
|
|
/* sa.sa_sigaction = SIG_IGN; */
|
|
|
|
sa.sa_handler = SIG_IGN;
|
2013-06-21 03:52:57 +02:00
|
|
|
|
|
|
|
if(sigemptyset(&sa.sa_mask) == -1) {
|
2013-03-06 01:08:15 +01:00
|
|
|
err(1, "unregister_interrupt: sigemptyset");
|
|
|
|
}
|
2013-06-21 03:52:57 +02:00
|
|
|
|
2013-05-14 18:31:47 +02:00
|
|
|
sa.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
|
2013-03-06 01:08:15 +01:00
|
|
|
|
2013-06-21 03:52:57 +02:00
|
|
|
if(sigaction(sig, &sa, NULL)) {
|
2013-03-13 22:00:41 +01:00
|
|
|
err(1, "unregister_interrupt: sigaction");
|
2013-03-06 01:08:15 +01:00
|
|
|
}
|
2013-06-21 03:52:57 +02:00
|
|
|
|
2013-03-06 01:08:15 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2013-03-13 21:56:56 +01:00
|
|
|
* register internal signal handler,
|
|
|
|
* initalize local variables
|
|
|
|
*
|
2013-03-06 01:08:15 +01:00
|
|
|
* TODO: see register_interrupt
|
|
|
|
*/
|
|
|
|
void native_interrupt_init(void)
|
|
|
|
{
|
|
|
|
struct sigaction sa;
|
|
|
|
DEBUG("XXX: native_interrupt_init()\n");
|
|
|
|
|
2013-04-15 20:08:46 +02:00
|
|
|
native_interrupts_enabled = 1;
|
2013-05-14 18:31:47 +02:00
|
|
|
_native_sigpend = 0;
|
2013-04-15 20:08:46 +02:00
|
|
|
|
2013-06-21 03:52:57 +02:00
|
|
|
for(int i = 0; i < 255; i++) {
|
2013-03-06 01:08:15 +01:00
|
|
|
native_irq_handlers[i].func = NULL;
|
|
|
|
}
|
|
|
|
|
2013-06-21 03:52:57 +02:00
|
|
|
sa.sa_sigaction = (void *) native_isr_entry;
|
|
|
|
|
|
|
|
if(sigemptyset(&sa.sa_mask) == -1) {
|
2013-03-06 01:08:15 +01:00
|
|
|
err(1, "native_interrupt_init: sigemptyset");
|
|
|
|
}
|
2013-06-21 03:52:57 +02:00
|
|
|
|
2013-05-14 18:31:47 +02:00
|
|
|
sa.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
|
2013-03-06 01:08:15 +01:00
|
|
|
|
2013-04-15 20:08:46 +02:00
|
|
|
/*
|
2013-03-06 01:08:15 +01:00
|
|
|
if (sigemptyset(&native_sig_set) == -1) {
|
|
|
|
err(1, "native_interrupt_init: sigemptyset");
|
|
|
|
}
|
2013-04-15 20:08:46 +02:00
|
|
|
*/
|
2013-06-21 03:52:57 +02:00
|
|
|
if(sigprocmask(SIG_SETMASK, NULL, &native_sig_set) == -1) {
|
2013-04-15 20:08:46 +02:00
|
|
|
err(1, "native_interrupt_init(): sigprocmask");
|
|
|
|
}
|
|
|
|
|
2013-06-21 03:52:57 +02:00
|
|
|
if(sigdelset(&native_sig_set, SIGUSR1) == -1) {
|
2013-04-15 20:08:46 +02:00
|
|
|
err(1, "native_interrupt_init: sigdelset");
|
2013-03-06 01:08:15 +01:00
|
|
|
}
|
|
|
|
|
2013-06-21 03:52:57 +02:00
|
|
|
if(sigaction(SIGUSR1, &sa, NULL)) {
|
2013-03-06 01:08:15 +01:00
|
|
|
err(1, "native_interrupt_init: sigaction");
|
|
|
|
}
|
|
|
|
|
2013-06-21 03:52:57 +02:00
|
|
|
if(getcontext(&native_isr_context) == -1) {
|
2013-05-14 18:31:47 +02:00
|
|
|
err(1, "native_isr_entry(): getcontext()");
|
2013-04-15 20:08:46 +02:00
|
|
|
}
|
|
|
|
|
2013-06-21 03:52:57 +02:00
|
|
|
if(sigfillset(&(native_isr_context.uc_sigmask)) == -1) {
|
2013-05-14 18:31:47 +02:00
|
|
|
err(1, "native_isr_entry(): sigfillset()");
|
2013-04-15 20:08:46 +02:00
|
|
|
}
|
2013-06-21 03:52:57 +02:00
|
|
|
|
2013-05-14 18:31:47 +02:00
|
|
|
native_isr_context.uc_stack.ss_sp = __isr_stack;
|
|
|
|
native_isr_context.uc_stack.ss_size = SIGSTKSZ;
|
|
|
|
native_isr_context.uc_stack.ss_flags = 0;
|
|
|
|
_native_isr_ctx = &native_isr_context;
|
|
|
|
|
|
|
|
static stack_t sigstk;
|
|
|
|
sigstk.ss_sp = sigalt_stk;
|
|
|
|
sigstk.ss_size = SIGSTKSZ;
|
|
|
|
sigstk.ss_flags = 0;
|
2013-06-21 03:52:57 +02:00
|
|
|
|
|
|
|
if(sigaltstack(&sigstk, NULL) < 0) {
|
2013-05-14 18:31:47 +02:00
|
|
|
err(1, "main: sigaltstack");
|
2013-04-15 20:08:46 +02:00
|
|
|
}
|
2013-06-21 03:52:57 +02:00
|
|
|
|
2013-05-14 18:31:47 +02:00
|
|
|
makecontext(&native_isr_context, native_irq_handler, 0);
|
|
|
|
|
|
|
|
_native_in_syscall = 0;
|
2013-04-15 20:08:46 +02:00
|
|
|
|
2013-06-21 03:52:57 +02:00
|
|
|
if(pipe(pipefd) == -1) {
|
2013-05-14 18:31:47 +02:00
|
|
|
err(1, "native_interrupt_init(): pipe()");
|
2013-04-15 20:08:46 +02:00
|
|
|
}
|
|
|
|
|
2013-03-06 01:08:15 +01:00
|
|
|
puts("RIOT native interrupts/signals initialized.");
|
|
|
|
}
|
2013-03-13 21:56:56 +01:00
|
|
|
/** @} */
|