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