xref: /plan9-contrib/sys/src/ape/lib/ap/amd64/notetramp.c (revision 272efad760864ee41cfe633b56aea9b4f5cf3ae7)
1 #include "../plan9/lib.h"
2 #include "../plan9/sys9.h"
3 #include <signal.h>
4 #include <setjmp.h>
5 
6 /* A stack to hold pcs when signals nest */
7 #define MAXSIGSTACK 20
8 typedef struct Pcstack Pcstack;
9 static struct Pcstack {
10 	int sig;
11 	void (*hdlr)(int, char*, Ureg*);
12 	unsigned long long restorepc;
13 	Ureg *u;
14 } pcstack[MAXSIGSTACK];
15 static int nstack = 0;
16 
17 static void notecont(Ureg*, char*);
18 
19 void
_notetramp(int sig,void (* hdlr)(int,char *,Ureg *),Ureg * u)20 _notetramp(int sig, void (*hdlr)(int, char*, Ureg*), Ureg *u)
21 {
22 	Pcstack *p;
23 
24 	if(nstack >= MAXSIGSTACK)
25 		_NOTED(1);	/* nesting too deep; just do system default */
26 	p = &pcstack[nstack];
27 	p->restorepc = u->ip;
28 	p->sig = sig;
29 	p->hdlr = hdlr;
30 	p->u = u;
31 	nstack++;
32 	u->ip = (unsigned long long) notecont;
33 	_NOTED(2);	/* NSAVE: clear note but hold state */
34 }
35 
36 static void
notecont(Ureg * u,char * s)37 notecont(Ureg *u, char *s)
38 {
39 	Pcstack *p;
40 	void(*f)(int, char*, Ureg*);
41 
42 	p = &pcstack[nstack-1];
43 	f = p->hdlr;
44 	u->ip = p->restorepc;
45 	nstack--;
46 	(*f)(p->sig, s, u);
47 	_NOTED(3);	/* NRSTR */
48 }
49 
50 #define JMPBUFPC 1
51 #define JMPBUFSP 0
52 
53 extern sigset_t	_psigblocked;
54 
55 typedef struct {
56 	sigset_t set;
57 	sigset_t blocked;
58 	unsigned long long jmpbuf[2];
59 } sigjmp_buf_amd64;
60 
61 void
siglongjmp(sigjmp_buf j,int ret)62 siglongjmp(sigjmp_buf j, int ret)
63 {
64 	struct Ureg *u;
65 	sigjmp_buf_amd64 *jb;
66 
67 	jb = (sigjmp_buf_amd64*)j;
68 
69 	if(jb->set)
70 		_psigblocked = jb->blocked;
71 	if(nstack == 0 || pcstack[nstack-1].u->sp > jb->jmpbuf[JMPBUFSP])
72 		longjmp((void*)jb->jmpbuf, ret);
73 	u = pcstack[nstack-1].u;
74 	nstack--;
75 	u->ax = ret;
76 	if(ret == 0)
77 		u->ax = 1;
78 	u->ip = jb->jmpbuf[JMPBUFPC];
79 	u->sp = jb->jmpbuf[JMPBUFSP] + 8;
80 	_NOTED(3);	/* NRSTR */
81 }
82