itlibthread: fix pthreadperthread bugs - plan9port - [fork] Plan 9 from user space Err mx1.adamsgaard.dk 70 hgit clone git://src.adamsgaard.dk/plan9port URL:git://src.adamsgaard.dk/plan9port mx1.adamsgaard.dk 70 1Log /src/plan9port/log.gph mx1.adamsgaard.dk 70 1Files /src/plan9port/files.gph mx1.adamsgaard.dk 70 1Refs /src/plan9port/refs.gph mx1.adamsgaard.dk 70 1README /src/plan9port/file/README.md.gph mx1.adamsgaard.dk 70 1LICENSE /src/plan9port/file/LICENSE.gph mx1.adamsgaard.dk 70 i--- Err mx1.adamsgaard.dk 70 1commit b73633b1b4e9d3dbd680edf900b2b53befbf5a9a /src/plan9port/commit/b73633b1b4e9d3dbd680edf900b2b53befbf5a9a.gph mx1.adamsgaard.dk 70 1parent b3a20a96eb2b91a5b0b8a8fb506e20a2fb50ebe8 /src/plan9port/commit/b3a20a96eb2b91a5b0b8a8fb506e20a2fb50ebe8.gph mx1.adamsgaard.dk 70 hAuthor: Russ Cox URL:mailto:rsc@swtch.com mx1.adamsgaard.dk 70 iDate: Wed, 30 Dec 2020 00:15:37 -0500 Err mx1.adamsgaard.dk 70 i Err mx1.adamsgaard.dk 70 ilibthread: fix pthreadperthread bugs Err mx1.adamsgaard.dk 70 i Err mx1.adamsgaard.dk 70 iDiffstat: Err mx1.adamsgaard.dk 70 i M src/libthread/thread.c | 293 ++++++++++++++++++++----------- Err mx1.adamsgaard.dk 70 i M src/libthread/threadimpl.h | 1 + Err mx1.adamsgaard.dk 70 i Err mx1.adamsgaard.dk 70 i2 files changed, 187 insertions(+), 107 deletions(-) Err mx1.adamsgaard.dk 70 i--- Err mx1.adamsgaard.dk 70 1diff --git a/src/libthread/thread.c b/src/libthread/thread.c /src/plan9port/file/src/libthread/thread.c.gph mx1.adamsgaard.dk 70 it@@ -1,6 +1,6 @@ Err mx1.adamsgaard.dk 70 i #include "threadimpl.h" Err mx1.adamsgaard.dk 70 i Err mx1.adamsgaard.dk 70 i-int _threaddebuglevel; Err mx1.adamsgaard.dk 70 i+int _threaddebuglevel = 0; Err mx1.adamsgaard.dk 70 i Err mx1.adamsgaard.dk 70 i static uint threadnproc; Err mx1.adamsgaard.dk 70 i static uint threadnsysproc; Err mx1.adamsgaard.dk 70 it@@ -20,13 +20,16 @@ static void contextswitch(Context *from, Context *to); Err mx1.adamsgaard.dk 70 i static void procmain(Proc*); Err mx1.adamsgaard.dk 70 i static void procscheduler(Proc*); Err mx1.adamsgaard.dk 70 i static int threadinfo(void*, char*); Err mx1.adamsgaard.dk 70 i+static void pthreadscheduler(Proc *p); Err mx1.adamsgaard.dk 70 i+static void pthreadsleepschedlocked(Proc *p, _Thread *t); Err mx1.adamsgaard.dk 70 i+static void pthreadwakeupschedlocked(Proc *p, _Thread *self, _Thread *t); Err mx1.adamsgaard.dk 70 i+static _Thread* procnext(Proc*, _Thread*); Err mx1.adamsgaard.dk 70 i Err mx1.adamsgaard.dk 70 i static void Err mx1.adamsgaard.dk 70 i-_threaddebug(char *fmt, ...) Err mx1.adamsgaard.dk 70 i+_threaddebug(_Thread *t, char *fmt, ...) Err mx1.adamsgaard.dk 70 i { Err mx1.adamsgaard.dk 70 i va_list arg; Err mx1.adamsgaard.dk 70 i char buf[128]; Err mx1.adamsgaard.dk 70 i- _Thread *t; Err mx1.adamsgaard.dk 70 i char *p; Err mx1.adamsgaard.dk 70 i static int fd = -1; Err mx1.adamsgaard.dk 70 i Err mx1.adamsgaard.dk 70 it@@ -52,7 +55,8 @@ _threaddebug(char *fmt, ...) Err mx1.adamsgaard.dk 70 i va_start(arg, fmt); Err mx1.adamsgaard.dk 70 i vsnprint(buf, sizeof buf, fmt, arg); Err mx1.adamsgaard.dk 70 i va_end(arg); Err mx1.adamsgaard.dk 70 i- t = proc()->thread; Err mx1.adamsgaard.dk 70 i+ if(t == nil) Err mx1.adamsgaard.dk 70 i+ t = proc()->thread; Err mx1.adamsgaard.dk 70 i if(t) Err mx1.adamsgaard.dk 70 i fprint(fd, "%p %d.%d: %s\n", proc(), getpid(), t->id, buf); Err mx1.adamsgaard.dk 70 i else Err mx1.adamsgaard.dk 70 it@@ -181,10 +185,15 @@ _threadcreate(Proc *p, void (*fn)(void*), void *arg, uint stack) Err mx1.adamsgaard.dk 70 i stack = 0; // not using it Err mx1.adamsgaard.dk 70 i t = threadalloc(fn, arg, stack); Err mx1.adamsgaard.dk 70 i t->proc = p; Err mx1.adamsgaard.dk 70 i- if(p->nthread == 0) Err mx1.adamsgaard.dk 70 i- p->thread0 = t; Err mx1.adamsgaard.dk 70 i- else if(pthreadperthread) Err mx1.adamsgaard.dk 70 i- _threadpthreadstart(p, t); Err mx1.adamsgaard.dk 70 i+ if(pthreadperthread) { Err mx1.adamsgaard.dk 70 i+ if(p->nthread != 0) Err mx1.adamsgaard.dk 70 i+ _threadpthreadstart(p, t); Err mx1.adamsgaard.dk 70 i+ else Err mx1.adamsgaard.dk 70 i+ t->mainthread = 1; Err mx1.adamsgaard.dk 70 i+ } else { Err mx1.adamsgaard.dk 70 i+ if(p->nthread == 0) Err mx1.adamsgaard.dk 70 i+ p->thread0 = t; Err mx1.adamsgaard.dk 70 i+ } Err mx1.adamsgaard.dk 70 i p->nthread++; Err mx1.adamsgaard.dk 70 i addthreadinproc(p, t); Err mx1.adamsgaard.dk 70 i _threadready(t); Err mx1.adamsgaard.dk 70 it@@ -197,6 +206,7 @@ threadcreate(void (*fn)(void*), void *arg, uint stack) Err mx1.adamsgaard.dk 70 i _Thread *t; Err mx1.adamsgaard.dk 70 i Err mx1.adamsgaard.dk 70 i t = _threadcreate(proc(), fn, arg, stack); Err mx1.adamsgaard.dk 70 i+ _threaddebug(nil, "threadcreate %d", t->id); Err mx1.adamsgaard.dk 70 i return t->id; Err mx1.adamsgaard.dk 70 i } Err mx1.adamsgaard.dk 70 i Err mx1.adamsgaard.dk 70 it@@ -210,41 +220,11 @@ proccreate(void (*fn)(void*), void *arg, uint stack) Err mx1.adamsgaard.dk 70 i p = procalloc(); Err mx1.adamsgaard.dk 70 i t = _threadcreate(p, fn, arg, stack); Err mx1.adamsgaard.dk 70 i id = t->id; /* t might be freed after _procstart */ Err mx1.adamsgaard.dk 70 i+ _threaddebug(t, "proccreate %p", p); Err mx1.adamsgaard.dk 70 i _procstart(p, procmain); Err mx1.adamsgaard.dk 70 i return id; Err mx1.adamsgaard.dk 70 i } Err mx1.adamsgaard.dk 70 i Err mx1.adamsgaard.dk 70 i-// For pthreadperthread mode, procswitch flips Err mx1.adamsgaard.dk 70 i-// between the threads. Err mx1.adamsgaard.dk 70 i-static void Err mx1.adamsgaard.dk 70 i-procswitch(Proc *p, _Thread *from, _Thread *to) Err mx1.adamsgaard.dk 70 i-{ Err mx1.adamsgaard.dk 70 i- _threaddebug("procswitch %p %d %d", p, from?from->id:-1, to?to->id:-1); Err mx1.adamsgaard.dk 70 i- lock(&p->schedlock); Err mx1.adamsgaard.dk 70 i- from->schedrend.l = &p->schedlock; Err mx1.adamsgaard.dk 70 i- if(to) { Err mx1.adamsgaard.dk 70 i- p->schedthread = to; Err mx1.adamsgaard.dk 70 i- to->schedrend.l = &p->schedlock; Err mx1.adamsgaard.dk 70 i- _threaddebug("procswitch wakeup %p %d", p, to->id); Err mx1.adamsgaard.dk 70 i- _procwakeup(&to->schedrend); Err mx1.adamsgaard.dk 70 i- } Err mx1.adamsgaard.dk 70 i- if(p->schedthread != from) { Err mx1.adamsgaard.dk 70 i- if(from->exiting) { Err mx1.adamsgaard.dk 70 i- unlock(&p->schedlock); Err mx1.adamsgaard.dk 70 i- _threadpexit(); Err mx1.adamsgaard.dk 70 i- _threaddebug("procswitch exit wakeup!!!\n"); Err mx1.adamsgaard.dk 70 i- } Err mx1.adamsgaard.dk 70 i- while(p->schedthread != from) { Err mx1.adamsgaard.dk 70 i- _threaddebug("procswitch sleep %p %d", p, from->id); Err mx1.adamsgaard.dk 70 i- _procsleep(&from->schedrend); Err mx1.adamsgaard.dk 70 i- _threaddebug("procswitch awake %p %d", p, from->id); Err mx1.adamsgaard.dk 70 i- } Err mx1.adamsgaard.dk 70 i- if(p->schedthread != from) Err mx1.adamsgaard.dk 70 i- sysfatal("_procswitch %p %p oops", p->schedthread, from); Err mx1.adamsgaard.dk 70 i- } Err mx1.adamsgaard.dk 70 i- unlock(&p->schedlock); Err mx1.adamsgaard.dk 70 i-} Err mx1.adamsgaard.dk 70 i- Err mx1.adamsgaard.dk 70 i void Err mx1.adamsgaard.dk 70 i _threadswitch(void) Err mx1.adamsgaard.dk 70 i { Err mx1.adamsgaard.dk 70 it@@ -255,10 +235,10 @@ _threadswitch(void) Err mx1.adamsgaard.dk 70 i Err mx1.adamsgaard.dk 70 i /*print("threadswtch %p\n", p); */ Err mx1.adamsgaard.dk 70 i Err mx1.adamsgaard.dk 70 i- if(p->thread == p->thread0) Err mx1.adamsgaard.dk 70 i+ if(pthreadperthread) Err mx1.adamsgaard.dk 70 i+ pthreadscheduler(p); Err mx1.adamsgaard.dk 70 i+ else if(p->thread == p->thread0) Err mx1.adamsgaard.dk 70 i procscheduler(p); Err mx1.adamsgaard.dk 70 i- else if(pthreadperthread) Err mx1.adamsgaard.dk 70 i- procswitch(p, p->thread, p->thread0); Err mx1.adamsgaard.dk 70 i else Err mx1.adamsgaard.dk 70 i contextswitch(&p->thread->context, &p->schedcontext); Err mx1.adamsgaard.dk 70 i } Err mx1.adamsgaard.dk 70 it@@ -390,7 +370,10 @@ void Err mx1.adamsgaard.dk 70 i _threadpthreadmain(Proc *p, _Thread *t) Err mx1.adamsgaard.dk 70 i { Err mx1.adamsgaard.dk 70 i _threadsetproc(p); Err mx1.adamsgaard.dk 70 i- procswitch(p, t, nil); Err mx1.adamsgaard.dk 70 i+ lock(&p->lock); Err mx1.adamsgaard.dk 70 i+ pthreadsleepschedlocked(p, t); Err mx1.adamsgaard.dk 70 i+ unlock(&p->lock); Err mx1.adamsgaard.dk 70 i+ _threaddebug(nil, "startfn"); Err mx1.adamsgaard.dk 70 i t->startfn(t->startarg); Err mx1.adamsgaard.dk 70 i threadexits(nil); Err mx1.adamsgaard.dk 70 i } Err mx1.adamsgaard.dk 70 it@@ -400,76 +383,47 @@ procscheduler(Proc *p) Err mx1.adamsgaard.dk 70 i { Err mx1.adamsgaard.dk 70 i _Thread *t; Err mx1.adamsgaard.dk 70 i Err mx1.adamsgaard.dk 70 i- _threaddebug("scheduler enter"); Err mx1.adamsgaard.dk 70 i+ _threaddebug(nil, "scheduler enter"); Err mx1.adamsgaard.dk 70 i //print("s %p\n", p); Err mx1.adamsgaard.dk 70 i-Top: Err mx1.adamsgaard.dk 70 i- lock(&p->lock); Err mx1.adamsgaard.dk 70 i- t = p->thread; Err mx1.adamsgaard.dk 70 i- p->thread = nil; Err mx1.adamsgaard.dk 70 i- if(t->exiting){ Err mx1.adamsgaard.dk 70 i- delthreadinproc(p, t); Err mx1.adamsgaard.dk 70 i- p->nthread--; Err mx1.adamsgaard.dk 70 i-/*print("nthread %d\n", p->nthread); */ Err mx1.adamsgaard.dk 70 i- _threadstkfree(t->stk, t->stksize); Err mx1.adamsgaard.dk 70 i- /* Err mx1.adamsgaard.dk 70 i- * Cannot free p->thread0 yet: it is used for the Err mx1.adamsgaard.dk 70 i- * context switches back to the scheduler. Err mx1.adamsgaard.dk 70 i- * Instead, we will free it at the end of this function. Err mx1.adamsgaard.dk 70 i- * But all the other threads can be freed now. Err mx1.adamsgaard.dk 70 i- */ Err mx1.adamsgaard.dk 70 i- if(t != p->thread0) Err mx1.adamsgaard.dk 70 i- free(t); Err mx1.adamsgaard.dk 70 i- } Err mx1.adamsgaard.dk 70 i- Err mx1.adamsgaard.dk 70 i- for(;;){ Err mx1.adamsgaard.dk 70 i- if((t = p->pinthread) != nil){ Err mx1.adamsgaard.dk 70 i- while(!onlist(&p->runqueue, t)){ Err mx1.adamsgaard.dk 70 i- p->runrend.l = &p->lock; Err mx1.adamsgaard.dk 70 i- _threaddebug("scheduler sleep (pin)"); Err mx1.adamsgaard.dk 70 i- _procsleep(&p->runrend); Err mx1.adamsgaard.dk 70 i- _threaddebug("scheduler wake (pin)"); Err mx1.adamsgaard.dk 70 i- } Err mx1.adamsgaard.dk 70 i- }else Err mx1.adamsgaard.dk 70 i- while((t = p->runqueue.head) == nil){ Err mx1.adamsgaard.dk 70 i- if(p->nthread == 0) Err mx1.adamsgaard.dk 70 i- goto Out; Err mx1.adamsgaard.dk 70 i- if((t = p->idlequeue.head) != nil){ Err mx1.adamsgaard.dk 70 i- /* Err mx1.adamsgaard.dk 70 i- * Run all the idling threads once. Err mx1.adamsgaard.dk 70 i- */ Err mx1.adamsgaard.dk 70 i- while((t = p->idlequeue.head) != nil){ Err mx1.adamsgaard.dk 70 i- delthread(&p->idlequeue, t); Err mx1.adamsgaard.dk 70 i- addthread(&p->runqueue, t); Err mx1.adamsgaard.dk 70 i- } Err mx1.adamsgaard.dk 70 i- continue; Err mx1.adamsgaard.dk 70 i- } Err mx1.adamsgaard.dk 70 i- p->runrend.l = &p->lock; Err mx1.adamsgaard.dk 70 i- _threaddebug("scheduler sleep"); Err mx1.adamsgaard.dk 70 i- _procsleep(&p->runrend); Err mx1.adamsgaard.dk 70 i- _threaddebug("scheduler wake"); Err mx1.adamsgaard.dk 70 i+ for(;;) { Err mx1.adamsgaard.dk 70 i+ /* Finish running current thread. */ Err mx1.adamsgaard.dk 70 i+ lock(&p->lock); Err mx1.adamsgaard.dk 70 i+ t = p->thread; Err mx1.adamsgaard.dk 70 i+ p->thread = nil; Err mx1.adamsgaard.dk 70 i+ if(t->exiting){ Err mx1.adamsgaard.dk 70 i+ delthreadinproc(p, t); Err mx1.adamsgaard.dk 70 i+ p->nthread--; Err mx1.adamsgaard.dk 70 i+ /*print("nthread %d\n", p->nthread); */ Err mx1.adamsgaard.dk 70 i+ _threadstkfree(t->stk, t->stksize); Err mx1.adamsgaard.dk 70 i+ /* Err mx1.adamsgaard.dk 70 i+ * Cannot free p->thread0 yet: it is used for the Err mx1.adamsgaard.dk 70 i+ * context switches back to the scheduler. Err mx1.adamsgaard.dk 70 i+ * Instead, we will free it at the end of this function. Err mx1.adamsgaard.dk 70 i+ * But all the other threads can be freed now. Err mx1.adamsgaard.dk 70 i+ */ Err mx1.adamsgaard.dk 70 i+ if(t != p->thread0) Err mx1.adamsgaard.dk 70 i+ free(t); Err mx1.adamsgaard.dk 70 i } Err mx1.adamsgaard.dk 70 i- if(p->pinthread && p->pinthread != t) Err mx1.adamsgaard.dk 70 i- fprint(2, "p->pinthread %p t %p\n", p->pinthread, t); Err mx1.adamsgaard.dk 70 i- assert(p->pinthread == nil || p->pinthread == t); Err mx1.adamsgaard.dk 70 i- delthread(&p->runqueue, t); Err mx1.adamsgaard.dk 70 i+ Err mx1.adamsgaard.dk 70 i+ /* Pick next thread. */ Err mx1.adamsgaard.dk 70 i+ t = procnext(p, nil); Err mx1.adamsgaard.dk 70 i+ if(t == nil) Err mx1.adamsgaard.dk 70 i+ break; Err mx1.adamsgaard.dk 70 i+ _threaddebug(nil, "run %d (%s)", t->id, t->name); Err mx1.adamsgaard.dk 70 i+ //print("run %p %p %p %p\n", t, *(uintptr*)(t->context.uc.mc.sp), t->context.uc.mc.di, t->context.uc.mc.si); Err mx1.adamsgaard.dk 70 i unlock(&p->lock); Err mx1.adamsgaard.dk 70 i- p->thread = t; Err mx1.adamsgaard.dk 70 i- p->nswitch++; Err mx1.adamsgaard.dk 70 i- _threaddebug("run %d (%s)", t->id, t->name); Err mx1.adamsgaard.dk 70 i-//print("run %p %p %p %p\n", t, *(uintptr*)(t->context.uc.mc.sp), t->context.uc.mc.di, t->context.uc.mc.si); Err mx1.adamsgaard.dk 70 i+ Err mx1.adamsgaard.dk 70 i+ /* Switch to next thread. */ Err mx1.adamsgaard.dk 70 i if(t == p->thread0) Err mx1.adamsgaard.dk 70 i return; Err mx1.adamsgaard.dk 70 i- if(pthreadperthread) Err mx1.adamsgaard.dk 70 i- procswitch(p, p->thread0, t); Err mx1.adamsgaard.dk 70 i- else Err mx1.adamsgaard.dk 70 i- contextswitch(&p->schedcontext, &t->context); Err mx1.adamsgaard.dk 70 i- _threaddebug("back in scheduler"); Err mx1.adamsgaard.dk 70 i-/*print("back in scheduler\n"); */ Err mx1.adamsgaard.dk 70 i- goto Top; Err mx1.adamsgaard.dk 70 i+ contextswitch(&p->schedcontext, &t->context); Err mx1.adamsgaard.dk 70 i+ Err mx1.adamsgaard.dk 70 i+ _threaddebug(nil, "back in scheduler"); Err mx1.adamsgaard.dk 70 i+ /*print("back in scheduler\n"); */ Err mx1.adamsgaard.dk 70 i } Err mx1.adamsgaard.dk 70 i Err mx1.adamsgaard.dk 70 i-Out: Err mx1.adamsgaard.dk 70 i- _threaddebug("scheduler exit"); Err mx1.adamsgaard.dk 70 i+ /* No more threads in proc. Clean up. */ Err mx1.adamsgaard.dk 70 i+ _threaddebug(nil, "scheduler exit"); Err mx1.adamsgaard.dk 70 i if(p->mainproc){ Err mx1.adamsgaard.dk 70 i /* Err mx1.adamsgaard.dk 70 i * Stupid bug - on Linux 2.6 and maybe elsewhere, Err mx1.adamsgaard.dk 70 it@@ -502,6 +456,125 @@ Out: Err mx1.adamsgaard.dk 70 i _threadpexit(); Err mx1.adamsgaard.dk 70 i } Err mx1.adamsgaard.dk 70 i Err mx1.adamsgaard.dk 70 i+static void Err mx1.adamsgaard.dk 70 i+pthreadsleepschedlocked(Proc *p, _Thread *t) Err mx1.adamsgaard.dk 70 i+{ Err mx1.adamsgaard.dk 70 i+ _threaddebug(t, "pthreadsleepsched %p %d", p, t->id);; Err mx1.adamsgaard.dk 70 i+ t->schedrend.l = &p->lock; Err mx1.adamsgaard.dk 70 i+ while(p->schedthread != t) Err mx1.adamsgaard.dk 70 i+ _procsleep(&t->schedrend); Err mx1.adamsgaard.dk 70 i+} Err mx1.adamsgaard.dk 70 i+ Err mx1.adamsgaard.dk 70 i+static void Err mx1.adamsgaard.dk 70 i+pthreadwakeupschedlocked(Proc *p, _Thread *self, _Thread *t) Err mx1.adamsgaard.dk 70 i+{ Err mx1.adamsgaard.dk 70 i+ _threaddebug(self, "pthreadwakeupschedlocked %p %d", p, t->id);; Err mx1.adamsgaard.dk 70 i+ t->schedrend.l = &p->schedlock; Err mx1.adamsgaard.dk 70 i+ p->schedthread = t; Err mx1.adamsgaard.dk 70 i+ _procwakeup(&t->schedrend); Err mx1.adamsgaard.dk 70 i+} Err mx1.adamsgaard.dk 70 i+ Err mx1.adamsgaard.dk 70 i+static void Err mx1.adamsgaard.dk 70 i+pthreadscheduler(Proc *p) Err mx1.adamsgaard.dk 70 i+{ Err mx1.adamsgaard.dk 70 i+ _Thread *self, *t; Err mx1.adamsgaard.dk 70 i+ Err mx1.adamsgaard.dk 70 i+ _threaddebug(nil, "scheduler"); Err mx1.adamsgaard.dk 70 i+ lock(&p->lock); Err mx1.adamsgaard.dk 70 i+ self = p->thread; Err mx1.adamsgaard.dk 70 i+ p->thread = nil; Err mx1.adamsgaard.dk 70 i+ _threaddebug(self, "pausing"); Err mx1.adamsgaard.dk 70 i+ Err mx1.adamsgaard.dk 70 i+ if(self->exiting) { Err mx1.adamsgaard.dk 70 i+ _threaddebug(self, "exiting"); Err mx1.adamsgaard.dk 70 i+ delthreadinproc(p, self); Err mx1.adamsgaard.dk 70 i+ p->nthread--; Err mx1.adamsgaard.dk 70 i+ } Err mx1.adamsgaard.dk 70 i+ Err mx1.adamsgaard.dk 70 i+ t = procnext(p, self); Err mx1.adamsgaard.dk 70 i+ if(t != nil) { Err mx1.adamsgaard.dk 70 i+ pthreadwakeupschedlocked(p, self, t); Err mx1.adamsgaard.dk 70 i+ if(!self->exiting) { Err mx1.adamsgaard.dk 70 i+ pthreadsleepschedlocked(p, self); Err mx1.adamsgaard.dk 70 i+ _threaddebug(nil, "resume %d", self->id); Err mx1.adamsgaard.dk 70 i+ unlock(&p->lock); Err mx1.adamsgaard.dk 70 i+ return; Err mx1.adamsgaard.dk 70 i+ } Err mx1.adamsgaard.dk 70 i+ } Err mx1.adamsgaard.dk 70 i+ Err mx1.adamsgaard.dk 70 i+ if(t == nil) { Err mx1.adamsgaard.dk 70 i+ /* Tear down proc bookkeeping. Wait to free p. */ Err mx1.adamsgaard.dk 70 i+ delproc(p); Err mx1.adamsgaard.dk 70 i+ lock(&threadnproclock); Err mx1.adamsgaard.dk 70 i+ if(p->sysproc) Err mx1.adamsgaard.dk 70 i+ --threadnsysproc; Err mx1.adamsgaard.dk 70 i+ if(--threadnproc == threadnsysproc) Err mx1.adamsgaard.dk 70 i+ threadexitsall(p->msg); Err mx1.adamsgaard.dk 70 i+ unlock(&threadnproclock); Err mx1.adamsgaard.dk 70 i+ } Err mx1.adamsgaard.dk 70 i+ Err mx1.adamsgaard.dk 70 i+ /* Tear down pthread. */ Err mx1.adamsgaard.dk 70 i+ if(self->mainthread && p->mainproc) { Err mx1.adamsgaard.dk 70 i+ _threaddaemonize(); Err mx1.adamsgaard.dk 70 i+ _threaddebug(self, "sleeper"); Err mx1.adamsgaard.dk 70 i+ unlock(&p->lock); Err mx1.adamsgaard.dk 70 i+ /* Err mx1.adamsgaard.dk 70 i+ * Avoid bugs with main pthread exiting. Err mx1.adamsgaard.dk 70 i+ * When all procs are gone, threadexitsall above will happen. Err mx1.adamsgaard.dk 70 i+ */ Err mx1.adamsgaard.dk 70 i+ for(;;) Err mx1.adamsgaard.dk 70 i+ sleep(60*60*1000); Err mx1.adamsgaard.dk 70 i+ } Err mx1.adamsgaard.dk 70 i+ _threadsetproc(nil); Err mx1.adamsgaard.dk 70 i+ free(self); Err mx1.adamsgaard.dk 70 i+ unlock(&p->lock); Err mx1.adamsgaard.dk 70 i+ if(t == nil) Err mx1.adamsgaard.dk 70 i+ free(p); Err mx1.adamsgaard.dk 70 i+ _threadpexit(); Err mx1.adamsgaard.dk 70 i+} Err mx1.adamsgaard.dk 70 i+ Err mx1.adamsgaard.dk 70 i+static _Thread* Err mx1.adamsgaard.dk 70 i+procnext(Proc *p, _Thread *self) Err mx1.adamsgaard.dk 70 i+{ Err mx1.adamsgaard.dk 70 i+ _Thread *t; Err mx1.adamsgaard.dk 70 i+ Err mx1.adamsgaard.dk 70 i+ if((t = p->pinthread) != nil){ Err mx1.adamsgaard.dk 70 i+ while(!onlist(&p->runqueue, t)){ Err mx1.adamsgaard.dk 70 i+ p->runrend.l = &p->lock; Err mx1.adamsgaard.dk 70 i+ _threaddebug(self, "scheduler sleep (pin)"); Err mx1.adamsgaard.dk 70 i+ _procsleep(&p->runrend); Err mx1.adamsgaard.dk 70 i+ _threaddebug(self, "scheduler wake (pin)"); Err mx1.adamsgaard.dk 70 i+ } Err mx1.adamsgaard.dk 70 i+ } else Err mx1.adamsgaard.dk 70 i+ while((t = p->runqueue.head) == nil){ Err mx1.adamsgaard.dk 70 i+ if(p->nthread == 0) Err mx1.adamsgaard.dk 70 i+ return nil; Err mx1.adamsgaard.dk 70 i+ if((t = p->idlequeue.head) != nil){ Err mx1.adamsgaard.dk 70 i+ /* Err mx1.adamsgaard.dk 70 i+ * Run all the idling threads once. Err mx1.adamsgaard.dk 70 i+ */ Err mx1.adamsgaard.dk 70 i+ while((t = p->idlequeue.head) != nil){ Err mx1.adamsgaard.dk 70 i+ delthread(&p->idlequeue, t); Err mx1.adamsgaard.dk 70 i+ addthread(&p->runqueue, t); Err mx1.adamsgaard.dk 70 i+ } Err mx1.adamsgaard.dk 70 i+ continue; Err mx1.adamsgaard.dk 70 i+ } Err mx1.adamsgaard.dk 70 i+ p->runrend.l = &p->lock; Err mx1.adamsgaard.dk 70 i+ _threaddebug(self, "scheduler sleep"); Err mx1.adamsgaard.dk 70 i+ _procsleep(&p->runrend); Err mx1.adamsgaard.dk 70 i+ _threaddebug(self, "scheduler wake"); Err mx1.adamsgaard.dk 70 i+ } Err mx1.adamsgaard.dk 70 i+ Err mx1.adamsgaard.dk 70 i+ if(p->pinthread && p->pinthread != t) Err mx1.adamsgaard.dk 70 i+ fprint(2, "p->pinthread %p t %p\n", p->pinthread, t); Err mx1.adamsgaard.dk 70 i+ assert(p->pinthread == nil || p->pinthread == t); Err mx1.adamsgaard.dk 70 i+ delthread(&p->runqueue, t); Err mx1.adamsgaard.dk 70 i+ Err mx1.adamsgaard.dk 70 i+ p->thread = t; Err mx1.adamsgaard.dk 70 i+ p->nswitch++; Err mx1.adamsgaard.dk 70 i+ return t; Err mx1.adamsgaard.dk 70 i+} Err mx1.adamsgaard.dk 70 i+ Err mx1.adamsgaard.dk 70 i void Err mx1.adamsgaard.dk 70 i _threadsetsysproc(void) Err mx1.adamsgaard.dk 70 i { Err mx1.adamsgaard.dk 70 it@@ -784,14 +857,18 @@ threadrwakeup(Rendez *r, int all, ulong pc) Err mx1.adamsgaard.dk 70 i int i; Err mx1.adamsgaard.dk 70 i _Thread *t; Err mx1.adamsgaard.dk 70 i Err mx1.adamsgaard.dk 70 i+ _threaddebug(nil, "rwakeup %p %d", r, all); Err mx1.adamsgaard.dk 70 i for(i=0;; i++){ Err mx1.adamsgaard.dk 70 i if(i==1 && !all) Err mx1.adamsgaard.dk 70 i break; Err mx1.adamsgaard.dk 70 i if((t = r->waiting.head) == nil) Err mx1.adamsgaard.dk 70 i break; Err mx1.adamsgaard.dk 70 i+ _threaddebug(nil, "rwakeup %p %d -> wake %d", r, all, t->id); Err mx1.adamsgaard.dk 70 i delthread(&r->waiting, t); Err mx1.adamsgaard.dk 70 i _threadready(t); Err mx1.adamsgaard.dk 70 i+ _threaddebug(nil, "rwakeup %p %d -> loop", r, all); Err mx1.adamsgaard.dk 70 i } Err mx1.adamsgaard.dk 70 i+ _threaddebug(nil, "rwakeup %p %d -> total %d", r, all, i); Err mx1.adamsgaard.dk 70 i return i; Err mx1.adamsgaard.dk 70 i } Err mx1.adamsgaard.dk 70 i Err mx1.adamsgaard.dk 70 it@@ -827,6 +904,7 @@ int Err mx1.adamsgaard.dk 70 i main(int argc, char **argv) Err mx1.adamsgaard.dk 70 i { Err mx1.adamsgaard.dk 70 i Proc *p; Err mx1.adamsgaard.dk 70 i+ _Thread *t; Err mx1.adamsgaard.dk 70 i char *opts; Err mx1.adamsgaard.dk 70 i Err mx1.adamsgaard.dk 70 i argv0 = argv[0]; Err mx1.adamsgaard.dk 70 it@@ -875,7 +953,8 @@ main(int argc, char **argv) Err mx1.adamsgaard.dk 70 i if(mainstacksize == 0) Err mx1.adamsgaard.dk 70 i mainstacksize = 256*1024; Err mx1.adamsgaard.dk 70 i atnotify(threadinfo, 1); Err mx1.adamsgaard.dk 70 i- _threadcreate(p, threadmainstart, nil, mainstacksize); Err mx1.adamsgaard.dk 70 i+ t = _threadcreate(p, threadmainstart, nil, mainstacksize); Err mx1.adamsgaard.dk 70 i+ t->mainthread = 1; Err mx1.adamsgaard.dk 70 i procmain(p); Err mx1.adamsgaard.dk 70 i sysfatal("procscheduler returned in threadmain!"); Err mx1.adamsgaard.dk 70 i /* does not return */ Err mx1.adamsgaard.dk 70 1diff --git a/src/libthread/threadimpl.h b/src/libthread/threadimpl.h /src/plan9port/file/src/libthread/threadimpl.h.gph mx1.adamsgaard.dk 70 it@@ -97,6 +97,7 @@ struct _Thread Err mx1.adamsgaard.dk 70 i uchar *stk; Err mx1.adamsgaard.dk 70 i uint stksize; Err mx1.adamsgaard.dk 70 i int exiting; Err mx1.adamsgaard.dk 70 i+ int mainthread; Err mx1.adamsgaard.dk 70 i Proc *proc; Err mx1.adamsgaard.dk 70 i char name[256]; Err mx1.adamsgaard.dk 70 i char state[256]; Err mx1.adamsgaard.dk 70 .