soc/runtime: fix use of setjmp

This commit is contained in:
Sebastien Bourdeauducq 2014-09-22 13:18:48 +08:00
parent 3de24619b2
commit b37ceb328f
3 changed files with 29 additions and 30 deletions

View File

@ -1,32 +1,33 @@
#include <setjmp.h>
#include "exceptions.h"
static struct exception_env *env_top;
#define MAX_EXCEPTION_CONTEXTS 64
struct exception_context {
void *jb[5];
};
static struct exception_context exception_contexts[MAX_EXCEPTION_CONTEXTS];
static int ec_top;
static int stored_id;
int exception_catch(struct exception_env *ee, int *id)
void *exception_push(void)
{
ee->prev = env_top;
env_top = ee;
if(setjmp(env_top->jb)) {
*id = stored_id;
return 1;
} else
return 0;
if(ec_top >= MAX_EXCEPTION_CONTEXTS)
exception_raise(EID_NOMEM);
return exception_contexts[ec_top++].jb;
}
void exception_pop(void)
{
env_top = env_top->prev;
ec_top--;
}
int exception_getid(void)
{
return stored_id;
}
void exception_raise(int id)
{
struct exception_env *ee;
ee = env_top;
env_top = env_top->prev;
stored_id = id; /* __builtin_longjmp needs its second argument set to 1 */
longjmp(ee->jb, 1);
__builtin_longjmp(exception_contexts[--ec_top].jb, 1);
}

View File

@ -1,15 +1,13 @@
#ifndef __EXCEPTIONS_H
#define __EXCEPTIONS_H
#include <setjmp.h>
struct exception_env {
jmp_buf jb;
struct exception_env *prev;
enum {
EID_NOMEM = 0
};
int exception_catch(struct exception_env *ee, int *id);
void *exception_push(void);
void exception_pop(void);
int exception_getid(void);
void exception_raise(int id) __attribute__((noreturn));
#endif /* __EXCEPTIONS_H */

View File

@ -68,8 +68,7 @@ typedef void (*kernel_function)(void);
static int run_kernel(const char *kernel_name, int *eid)
{
kernel_function k;
struct exception_env ee;
int exception_occured;
void *jb;
k = find_symbol(symtab, kernel_name);
if(k == NULL) {
@ -77,10 +76,11 @@ static int run_kernel(const char *kernel_name, int *eid)
return KERNEL_RUN_STARTUP_FAILED;
}
exception_occured = exception_catch(&ee, eid);
if(exception_occured)
jb = exception_push();
if(__builtin_setjmp(jb)) {
*eid = exception_getid();
return KERNEL_RUN_EXCEPTION;
else {
} else {
rtio_init();
flush_cpu_icache();
k();
@ -108,7 +108,7 @@ int main(void)
irq_setmask(0);
irq_setie(1);
uart_init();
puts("ARTIQ runtime built "__DATE__" "__TIME__"\n");
dds_init();
blink_led();