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