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