xref: /plan9/sys/src/libthread/note.c (revision 9a747e4fd48b9f4522c70c07e8f882a15030f964)
1*9a747e4fSDavid du Colombier #include <u.h>
2*9a747e4fSDavid du Colombier #include <libc.h>
3*9a747e4fSDavid du Colombier #include <thread.h>
4*9a747e4fSDavid du Colombier #include "threadimpl.h"
5*9a747e4fSDavid du Colombier 
6*9a747e4fSDavid du Colombier int	_threadnopasser;
7*9a747e4fSDavid du Colombier 
8*9a747e4fSDavid du Colombier #define	NFN		33
9*9a747e4fSDavid du Colombier #define	ERRLEN	48
10*9a747e4fSDavid du Colombier typedef struct Note Note;
11*9a747e4fSDavid du Colombier struct Note
12*9a747e4fSDavid du Colombier {
13*9a747e4fSDavid du Colombier 	Lock		inuse;
14*9a747e4fSDavid du Colombier 	Proc		*proc;		/* recipient */
15*9a747e4fSDavid du Colombier 	char		s[ERRMAX];	/* arg2 */
16*9a747e4fSDavid du Colombier };
17*9a747e4fSDavid du Colombier 
18*9a747e4fSDavid du Colombier static Note	notes[128];
19*9a747e4fSDavid du Colombier static Note	*enotes = notes+nelem(notes);
20*9a747e4fSDavid du Colombier static int		(*onnote[NFN])(void*, char*);
21*9a747e4fSDavid du Colombier static int		onnotepid[NFN];
22*9a747e4fSDavid du Colombier static Lock	onnotelock;
23*9a747e4fSDavid du Colombier 
24*9a747e4fSDavid du Colombier int
25*9a747e4fSDavid du Colombier threadnotify(int (*f)(void*, char*), int in)
26*9a747e4fSDavid du Colombier {
27*9a747e4fSDavid du Colombier 	int i, topid;
28*9a747e4fSDavid du Colombier 	int (*from)(void*, char*), (*to)(void*, char*);
29*9a747e4fSDavid du Colombier 
30*9a747e4fSDavid du Colombier 	if(in){
31*9a747e4fSDavid du Colombier 		from = nil;
32*9a747e4fSDavid du Colombier 		to = f;
33*9a747e4fSDavid du Colombier 		topid = _threadgetproc()->pid;
34*9a747e4fSDavid du Colombier 	}else{
35*9a747e4fSDavid du Colombier 		from = f;
36*9a747e4fSDavid du Colombier 		to = nil;
37*9a747e4fSDavid du Colombier 		topid = 0;
38*9a747e4fSDavid du Colombier 	}
39*9a747e4fSDavid du Colombier 	lock(&onnotelock);
40*9a747e4fSDavid du Colombier 	for(i=0; i<NFN; i++)
41*9a747e4fSDavid du Colombier 		if(onnote[i]==from){
42*9a747e4fSDavid du Colombier 			onnote[i] = to;
43*9a747e4fSDavid du Colombier 			onnotepid[i] = topid;
44*9a747e4fSDavid du Colombier 			break;
45*9a747e4fSDavid du Colombier 		}
46*9a747e4fSDavid du Colombier 	unlock(&onnotelock);
47*9a747e4fSDavid du Colombier 	return i<NFN;
48*9a747e4fSDavid du Colombier }
49*9a747e4fSDavid du Colombier 
50*9a747e4fSDavid du Colombier static void
51*9a747e4fSDavid du Colombier delayednotes(Proc *p, void *v)
52*9a747e4fSDavid du Colombier {
53*9a747e4fSDavid du Colombier 	int i;
54*9a747e4fSDavid du Colombier 	Note *n;
55*9a747e4fSDavid du Colombier 	int (*fn)(void*, char*);
56*9a747e4fSDavid du Colombier 
57*9a747e4fSDavid du Colombier 	if(!p->pending)
58*9a747e4fSDavid du Colombier 		return;
59*9a747e4fSDavid du Colombier 
60*9a747e4fSDavid du Colombier 	p->pending = 0;
61*9a747e4fSDavid du Colombier 	for(n=notes; n<enotes; n++){
62*9a747e4fSDavid du Colombier 		if(n->proc == p){
63*9a747e4fSDavid du Colombier 			for(i=0; i<NFN; i++){
64*9a747e4fSDavid du Colombier 				if(onnotepid[i]!=p->pid || (fn = onnote[i])==nil)
65*9a747e4fSDavid du Colombier 					continue;
66*9a747e4fSDavid du Colombier 				if((*fn)(v, n->s))
67*9a747e4fSDavid du Colombier 					break;
68*9a747e4fSDavid du Colombier 			}
69*9a747e4fSDavid du Colombier 			if(i==NFN){
70*9a747e4fSDavid du Colombier 				_threaddebug(DBGNOTE, "Unhandled note %s, proc %p\n", n->s, p);
71*9a747e4fSDavid du Colombier 				if(v != nil)
72*9a747e4fSDavid du Colombier 					noted(NDFLT);
73*9a747e4fSDavid du Colombier 				else if(strncmp(n->s, "sys:", 4)==0)
74*9a747e4fSDavid du Colombier 					abort();
75*9a747e4fSDavid du Colombier 				threadexitsall(n->s);
76*9a747e4fSDavid du Colombier 			}
77*9a747e4fSDavid du Colombier 			n->proc = nil;
78*9a747e4fSDavid du Colombier 			unlock(&n->inuse);
79*9a747e4fSDavid du Colombier 		}
80*9a747e4fSDavid du Colombier 	}
81*9a747e4fSDavid du Colombier }
82*9a747e4fSDavid du Colombier 
83*9a747e4fSDavid du Colombier void
84*9a747e4fSDavid du Colombier _threadnote(void *v, char *s)
85*9a747e4fSDavid du Colombier {
86*9a747e4fSDavid du Colombier 	Proc *p;
87*9a747e4fSDavid du Colombier 	Note *n;
88*9a747e4fSDavid du Colombier 
89*9a747e4fSDavid du Colombier 	_threaddebug(DBGNOTE, "Got note %s", s);
90*9a747e4fSDavid du Colombier 	if(strncmp(s, "sys:", 4) == 0)
91*9a747e4fSDavid du Colombier 		noted(NDFLT);
92*9a747e4fSDavid du Colombier 
93*9a747e4fSDavid du Colombier //	if(_threadexitsallstatus){
94*9a747e4fSDavid du Colombier //		_threaddebug(DBGNOTE, "Threadexitsallstatus = '%s'\n", _threadexitsallstatus);
95*9a747e4fSDavid du Colombier //		_exits(_threadexitsallstatus);
96*9a747e4fSDavid du Colombier //	}
97*9a747e4fSDavid du Colombier 
98*9a747e4fSDavid du Colombier 	if(strcmp(s, "threadint")==0)
99*9a747e4fSDavid du Colombier 		noted(NCONT);
100*9a747e4fSDavid du Colombier 
101*9a747e4fSDavid du Colombier 	p = _threadgetproc();
102*9a747e4fSDavid du Colombier 	if(p == nil)
103*9a747e4fSDavid du Colombier 		noted(NDFLT);
104*9a747e4fSDavid du Colombier 
105*9a747e4fSDavid du Colombier 	for(n=notes; n<enotes; n++)
106*9a747e4fSDavid du Colombier 		if(canlock(&n->inuse))
107*9a747e4fSDavid du Colombier 			break;
108*9a747e4fSDavid du Colombier 	if(n==enotes)
109*9a747e4fSDavid du Colombier 		sysfatal("libthread: too many delayed notes");
110*9a747e4fSDavid du Colombier 	utfecpy(n->s, n->s+ERRMAX, s);
111*9a747e4fSDavid du Colombier 	n->proc = p;
112*9a747e4fSDavid du Colombier 	p->pending = 1;
113*9a747e4fSDavid du Colombier 	if(!p->splhi)
114*9a747e4fSDavid du Colombier 		delayednotes(p, v);
115*9a747e4fSDavid du Colombier 	noted(NCONT);
116*9a747e4fSDavid du Colombier }
117*9a747e4fSDavid du Colombier 
118*9a747e4fSDavid du Colombier int
119*9a747e4fSDavid du Colombier _procsplhi(void)
120*9a747e4fSDavid du Colombier {
121*9a747e4fSDavid du Colombier 	int s;
122*9a747e4fSDavid du Colombier 	Proc *p;
123*9a747e4fSDavid du Colombier 
124*9a747e4fSDavid du Colombier 	p = _threadgetproc();
125*9a747e4fSDavid du Colombier 	s = p->splhi;
126*9a747e4fSDavid du Colombier 	p->splhi = 1;
127*9a747e4fSDavid du Colombier 	return s;
128*9a747e4fSDavid du Colombier }
129*9a747e4fSDavid du Colombier 
130*9a747e4fSDavid du Colombier void
131*9a747e4fSDavid du Colombier _procsplx(int s)
132*9a747e4fSDavid du Colombier {
133*9a747e4fSDavid du Colombier 	Proc *p;
134*9a747e4fSDavid du Colombier 
135*9a747e4fSDavid du Colombier 	p = _threadgetproc();
136*9a747e4fSDavid du Colombier 	p->splhi = s;
137*9a747e4fSDavid du Colombier 	if(s)
138*9a747e4fSDavid du Colombier 		return;
139*9a747e4fSDavid du Colombier 	if(p->pending)
140*9a747e4fSDavid du Colombier 		delayednotes(p, nil);
141*9a747e4fSDavid du Colombier }
142*9a747e4fSDavid du Colombier 
143