summaryrefslogtreecommitdiff
path: root/sys/src/ape/lib/ap/amd64/notetramp.c
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@felloff.net>2014-02-01 10:31:41 +0100
committercinap_lenrek <cinap_lenrek@felloff.net>2014-02-01 10:31:41 +0100
commited9e9f98e9cc502c72b27c68612e9e187ec11e10 (patch)
tree42901d0156503dadce4bf1f0b60e9ef850c3c5e0 /sys/src/ape/lib/ap/amd64/notetramp.c
parentd4fb753c9c90e0ca745a1b3708ad3ec4ca523e71 (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.c81
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 */
+}