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 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 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 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 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 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