On Tue, 28 Jun 2022, adr wrote:
This just evade going through the arrays twice. For the current
value of NFN it doesn't make too much a difference, note that this
structures are locked. It just was hurting my eyes.

Sorry for the noise, bad patch.
--- /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,161 @@

 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<NFN; i++)
-               if(onnote[i]==from){
-                       onnote[i] = to;
-                       onnotepid[i] = topid;
+
+       /* add note for all processes */
+       if(in < -1){
+               n = -1;
+               for(i=0; i<NFN; i++){
+                       if(onnoteall[i] == f){
+                               unlock(&onnotelock);
+                               return 1;
+                       }
+                       if(onnoteall[i]==nil && n==-1)
+                               n = i;
+               }
+               if(n > -1)
+                       onnoteall[n] = f;
+               unlock(&onnotelock);
+               return n>-1;
+       }
+
+       /* remove note for all processes */
+       if(in == -1){
+               for(i=0; i<NFN; i++)
+                       if(onnoteall[i] == f){
+                               onnoteall[i] = nil;
+                               break;
+                       }
+               unlock(&onnotelock);
+               return i<NFN;
+       }
+
+       /* remove note for current process */
+       if(!in){
+               for(i=0; i<onnotesize; i++){
+                       if(onnote[i]!=nil && 
onnote[i]->pid==_threadgetproc()->pid){
+                               for(j=0; j<NFN; j++){
+                                       if(onnote[i]->fn[j] == f){
+                                               onnote[i]->fn[j] = 0;
+                                               break;
+                                       }
+                               }
+                               unlock(&onnotelock);
+                               return j<NFN;
+                       }
+               }
+               unlock(&onnotelock);
+               return 0;
+       }
+
+       /* add note for current process */
+       for(i=0; i<onnotesize; i++)
+               if(onnote[i] && onnote[i]->pid==_threadgetproc()->pid)
+                       break;
+
+       /* process has already a slot */
+       if(i < onnotesize){
+               n = -1;
+               for(j=0; j<NFN; j++){
+                       if(onnote[i]->fn[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;
+ + }
+
+       for(i=0; i<onnotesize; i++)
+               if(!onnote[i])
+                       break;
+
+       /* there is no free slot */
+       if(i == onnotesize){
+               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);
+       }
+
+       onnote[i]=mallocz(sizeof(Onnote), 1);
+       if(!onnote[i]){
+               unlock(&onnotelock);
+               sysfatal("Malloc of size %d failed: %r", sizeof(Onnote));
+       }
+       onnote[i]->pid = _threadgetproc()->pid;
+       onnote[i]->fn[0] = f;
+       unlock(&onnotelock);
+       return 1;
+}
+
+void
+threadcancelnotes(int pid)
+{
+       int i;
+
+       lock(&onnotelock);
+       for(i=0; i<onnotesize; i++)
+               if(onnote[i] && onnote[i]->pid==pid){
+                       free(onnote[i]);
+                       onnote[i] = nil;
                       break;
               }
       unlock(&onnotelock);
-       return i<NFN;
+       return;
 }

 static void
 delayednotes(Proc *p, void *v)
 {
-       int i;
+       int i, j, all;
       Note *n;
-       char s[ERRMAX];
-       int (*fn)(void*, char*);
+       int (*f)(void*, char*);

       if(!p->pending)
               return;

       p->pending = 0;
+       all = j = 0;
       for(n=notes; n<enotes; n++){
               if(n->proc == p){
-                       strcpy(s, n->s);
-                       n->proc = nil;
-                       unlock(&n->inuse);
-
-                       for(i=0; i<NFN; i++){
-                               if(onnotepid[i]!=p->pid || (fn = 
onnote[i])==nil)
-                                       continue;
-                               if((*fn)(v, s))
-                                       break;
+                       for(i=0; i<NFN; i++)
+                               if(f=onnoteall[i])
+                                       if((*f)(v, n->s)){
+                                               all = 1;
+                                               break;
+                                       }
+                       if(!all){
+                               for(i=0; i<onnotesize; i++)
+                                       if(onnote[i] && onnote[i]->pid==p->pid){
+                                               for(j=0; j<NFN; j++)
+                                                       if(f=onnote[i]->fn[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 +177,8 @@
                                       abort();
                               threadexitsall(n->s);
                       }
+                       n->proc = nil;
+                       unlock(&n->inuse);
               }
       }
 }
@@ -94,7 +194,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-Mc1bc6e87aa53de84e2f20729
Delivery options: https://9fans.topicbox.com/groups/9fans/subscription

Reply via email to