diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2014-02-01 10:31:41 +0100 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2014-02-01 10:31:41 +0100 |
commit | ed9e9f98e9cc502c72b27c68612e9e187ec11e10 (patch) | |
tree | 42901d0156503dadce4bf1f0b60e9ef850c3c5e0 /sys/src/ape/lib/ap/amd64/notetramp.c | |
parent | d4fb753c9c90e0ca745a1b3708ad3ec4ca523e71 (diff) |
libc and ape support for amd64
Diffstat (limited to 'sys/src/ape/lib/ap/amd64/notetramp.c')
-rw-r--r-- | sys/src/ape/lib/ap/amd64/notetramp.c | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/sys/src/ape/lib/ap/amd64/notetramp.c b/sys/src/ape/lib/ap/amd64/notetramp.c new file mode 100644 index 000000000..c92205175 --- /dev/null +++ b/sys/src/ape/lib/ap/amd64/notetramp.c @@ -0,0 +1,81 @@ +#include "../plan9/lib.h" +#include "../plan9/sys9.h" +#include <signal.h> +#include <setjmp.h> + +/* A stack to hold pcs when signals nest */ +#define MAXSIGSTACK 20 +typedef struct Pcstack Pcstack; +static struct Pcstack { + int sig; + void (*hdlr)(int, char*, Ureg*); + unsigned long long restorepc; + Ureg *u; +} pcstack[MAXSIGSTACK]; +static int nstack = 0; + +static void notecont(Ureg*, char*); + +void +_notetramp(int sig, void (*hdlr)(int, char*, Ureg*), Ureg *u) +{ + Pcstack *p; + + if(nstack >= MAXSIGSTACK) + _NOTED(1); /* nesting too deep; just do system default */ + p = &pcstack[nstack]; + p->restorepc = u->pc; + p->sig = sig; + p->hdlr = hdlr; + p->u = u; + nstack++; + u->pc = (unsigned long long) notecont; + _NOTED(2); /* NSAVE: clear note but hold state */ +} + +static void +notecont(Ureg *u, char *s) +{ + Pcstack *p; + void(*f)(int, char*, Ureg*); + + p = &pcstack[nstack-1]; + f = p->hdlr; + u->pc = p->restorepc; + nstack--; + (*f)(p->sig, s, u); + _NOTED(3); /* NRSTR */ +} + +#define JMPBUFPC 1 +#define JMPBUFSP 0 + +extern sigset_t _psigblocked; + +typedef struct { + sigset_t set; + sigset_t blocked; + unsigned long long jmpbuf[2]; +} sigjmp_buf_amd64; + +void +siglongjmp(sigjmp_buf j, int ret) +{ + struct Ureg *u; + sigjmp_buf_amd64 *jb; + + jb = (sigjmp_buf_amd64*)j; + + if(jb->set) + _psigblocked = jb->blocked; + if(nstack == 0 || pcstack[nstack-1].u->sp > jb->jmpbuf[JMPBUFSP]) + longjmp((void*)jb->jmpbuf, ret); + u = pcstack[nstack-1].u; + nstack--; + u->ax = ret; + if(ret == 0) + u->ax = 1; + u->pc = jb->jmpbuf[JMPBUFPC]; + u->sp = jb->jmpbuf[JMPBUFSP] + 8; + _NOTED(3); /* NRSTR */ +} |