forked from M-Labs/artiq
1
0
Fork 0

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" #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; static int stored_id;
int exception_catch(struct exception_env *ee, int *id) void *exception_push(void)
{ {
ee->prev = env_top; if(ec_top >= MAX_EXCEPTION_CONTEXTS)
env_top = ee; exception_raise(EID_NOMEM);
if(setjmp(env_top->jb)) { return exception_contexts[ec_top++].jb;
*id = stored_id;
return 1;
} else
return 0;
} }
void exception_pop(void) void exception_pop(void)
{ {
env_top = env_top->prev; ec_top--;
}
int exception_getid(void)
{
return stored_id;
} }
void exception_raise(int id) void exception_raise(int id)
{ {
struct exception_env *ee; __builtin_longjmp(exception_contexts[--ec_top].jb, 1);
ee = env_top;
env_top = env_top->prev;
stored_id = id; /* __builtin_longjmp needs its second argument set to 1 */
longjmp(ee->jb, 1);
} }

View File

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

View File

@ -68,8 +68,7 @@ typedef void (*kernel_function)(void);
static int run_kernel(const char *kernel_name, int *eid) static int run_kernel(const char *kernel_name, int *eid)
{ {
kernel_function k; kernel_function k;
struct exception_env ee; void *jb;
int exception_occured;
k = find_symbol(symtab, kernel_name); k = find_symbol(symtab, kernel_name);
if(k == NULL) { if(k == NULL) {
@ -77,10 +76,11 @@ static int run_kernel(const char *kernel_name, int *eid)
return KERNEL_RUN_STARTUP_FAILED; return KERNEL_RUN_STARTUP_FAILED;
} }
exception_occured = exception_catch(&ee, eid); jb = exception_push();
if(exception_occured) if(__builtin_setjmp(jb)) {
*eid = exception_getid();
return KERNEL_RUN_EXCEPTION; return KERNEL_RUN_EXCEPTION;
else { } else {
rtio_init(); rtio_init();
flush_cpu_icache(); flush_cpu_icache();
k(); k();