--- /tmp/main.c +++ /sys/src/libthread/main.c @@ -28,6 +28,10 @@ _qlockinit(_threadrendezvous); _sysfatal = _threadsysfatal; __assert = _threadassert; + onnote = mallocz(PPCHUNK*sizeof(uintptr), 1); + if(!onnote) + sysfatal("Malloc of size %d failed: %r", PPCHUNK*sizeof(uintptr)); + onnotesize = PPCHUNK; notify(_threadnote); if(mainstacksize == 0) mainstacksize = 8*1024; --- /tmp/note.c +++ /sys/src/libthread/note.c @@ -5,7 +5,6 @@ int _threadnopasser; -#define NFN 33 #define ERRLEN 48 typedef struct Note Note; struct Note @@ -17,62 +16,157 @@ static Note notes[128]; static Note *enotes = notes+nelem(notes); -static int (*onnote[NFN])(void*, char*); -static int onnotepid[NFN]; +Onnote **onnote; +int onnotesize; +static int (*onnoteall[NFN])(void*, char*); static Lock onnotelock; int threadnotify(int (*f)(void*, char*), int in) { - int i, topid; - int (*from)(void*, char*), (*to)(void*, char*); + int i, j, n; - if(in){ - from = nil; - to = f; - topid = _threadgetproc()->pid; - }else{ - from = f; - to = nil; - topid = 0; - } lock(&onnotelock); - for(i=0; i -1) + onnoteall[n] = f; + unlock(&onnotelock); + return n>-1; + } + + /* remove note for all processes */ + if(in == -1){ + for(i=0; ipid==_threadgetproc()->pid){ + for(j=0; jfn[j] == f){ + onnote[i]->fn[j] = 0; + break; + } + } + unlock(&onnotelock); + return jpid==_threadgetproc()->pid){ + n = -1; + for(j=0; jfn[j] == f){ + unlock(&onnotelock); + return 1; + } + if(onnote[i]->fn[j]==nil && n==-1) + n = j; + } + if(n > -1) + onnote[i]->fn[n] = f; + unlock(&onnotelock); + return n>-1; + } + /* there is a free slot */ + if(!onnote[i] && n==-1) + n = i; + } + /* there is no free slot */ + if(n == -1){ + onnotesize += PPCHUNK; + onnote = realloc(onnote, onnotesize*sizeof(uintptr)); + if(!onnote){ + unlock(&onnotelock); + sysfatal("Malloc of size %d failed: %r", onnotesize*sizeof(uintptr)); + } + memset(onnote+i+1, 0, PPCHUNK-1); + n = i; + } + onnote[n]=mallocz(sizeof(Onnote), 1); + if(!onnote[n]){ + unlock(&onnotelock); + sysfatal("Malloc of size %d failed: %r", sizeof(Onnote)); + } + onnote[n]->pid = _threadgetproc()->pid; + onnote[n]->fn[0] = f; + unlock(&onnotelock); + return 1; +} + +void +threadcancelnotes(int pid) +{ + int i; + + lock(&onnotelock); + for(i=0; ipid==pid){ + free(onnote[i]); + onnote[i] = nil; break; } unlock(&onnotelock); - return ipending) return; p->pending = 0; + all = j = 0; for(n=notes; nproc == p){ - strcpy(s, n->s); - n->proc = nil; - unlock(&n->inuse); - - for(i=0; ipid || (fn = onnote[i])==nil) - continue; - if((*fn)(v, s)) - break; + for(i=0; is)){ + all = 1; + break; + } + if(!all){ + for(i=0; ipid==p->pid){ + for(j=0; jfn[j]) + if((*f)(v, n->s)) + break; + break; + } } - if(i==NFN){ - _threaddebug(DBGNOTE, "Unhandled note %s, proc %p", n->s, p); + if(!all && (i==onnotesize || j==NFN)){ + _threaddebug(DBGNOTE, "Unhandled note %s, proc %p\n", n->s, p); if(v != nil) noted(NDFLT); else if(strncmp(n->s, "sys:", 4)==0) @@ -79,6 +173,8 @@ abort(); threadexitsall(n->s); } + n->proc = nil; + unlock(&n->inuse); } } } @@ -94,7 +190,7 @@ noted(NDFLT); if(_threadexitsallstatus){ - _threaddebug(DBGNOTE, "Threadexitsallstatus = '%s'", _threadexitsallstatus); + _threaddebug(DBGNOTE, "Threadexitsallstatus = '%s'\n", _threadexitsallstatus); _exits(_threadexitsallstatus); } --- /tmp/sched.c +++ /sys/src/libthread/sched.c @@ -157,6 +157,7 @@ t = runthread(p); if(t == nil){ _threaddebug(DBGSCHED, "all threads gone; exiting"); + threadcancelnotes(p->pid); unlinkproc(p); _schedexit(p); /* frees proc */ } --- /tmp/thread.h +++ /sys/include/thread.h @@ -97,6 +97,7 @@ void threadkillgrp(int); /* kill threads in group */ void threadmain(int argc, char *argv[]); int threadnotify(int (*f)(void*, char*), int in); +void threadcancelnotes(int pid); int threadid(void); int threadpid(int); int threadsetgrp(int); /* set thread group, return old */ --- /tmp/threadimpl.h +++ /sys/src/libthread/threadimpl.h @@ -192,3 +192,15 @@ #define _threaddebug(flag, ...) if((_threaddebuglevel&(flag))==0){}else _threadprint(__VA_ARGS__) #define ioproc_arg(io, type) (va_arg((io)->arg, type)) + +#define PPCHUNK 100 +#define NFN 33 +typedef struct Onnote Onnote; +struct Onnote +{ + int pid; + int (*fn[NFN])(void*, char*); +}; +extern Onnote **onnote; +extern int onnotesize; +void _threadnote(void*, char*);