On Tue, 28 Jun 2022, adr wrote: > It's just to play with it, note that onnote should be just passed > once. I'll post another patch if things work ok. Here it is. I'm doing sysfatal when malloc fails to be coherent with the rest of libthread, but I don't think that's a good approach. When those functions fail to make an allocation they should return an error so the program could take an action depending on the error. For example, if there is no sufficient memory at a time, the program could wait until there are enough resources to spawn a new thread. adr --- /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*); ------------------------------------------ 9fans: 9fans Permalink: https://9fans.topicbox.com/groups/9fans/Tfa6823048ad90a21-M0bb660408ef52d611ffd55ab Delivery options: https://9fans.topicbox.com/groups/9fans/subscription