tlibthread: handle spurious _procsleep wakeups, fix $LIBTHREAD handling - plan9port - [fork] Plan 9 from user space
 (HTM) git clone git://src.adamsgaard.dk/plan9port
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit 162d0d5cd94fabab822ac66655be8957151cef99
 (DIR) parent baef953da253314657be9adea8f371bfbf4ba09e
 (HTM) Author: Russ Cox <rsc@swtch.com>
       Date:   Sun, 17 May 2020 22:31:38 -0400
       
       libthread: handle spurious _procsleep wakeups, fix $LIBTHREAD handling
       
       Diffstat:
         M src/libthread/pthread.c             |       4 +++-
         M src/libthread/thread.c              |      28 +++++++++++++++++++++++-----
       
       2 files changed, 26 insertions(+), 6 deletions(-)
       ---
 (DIR) diff --git a/src/libthread/pthread.c b/src/libthread/pthread.c
       t@@ -50,13 +50,15 @@ _threadunlock(Lock *lk, ulong pc)
                        abort();
        }
        
       +/* note: _procsleep can have spurious wakeups, like pthread_cond_wait */
        void
        _procsleep(_Procrendez *r)
        {
                /* r is protected by r->l, which we hold */
                pthread_cond_init(&r->cond, 0);
                r->asleep = 1;
       -        pthread_cond_wait(&r->cond, &r->l->mutex);
       +        if(pthread_cond_wait(&r->cond, &r->l->mutex) != 0)
       +                sysfatal("pthread_cond_wait: %r");
                pthread_cond_destroy(&r->cond);
                r->asleep = 0;
        }
 (DIR) diff --git a/src/libthread/thread.c b/src/libthread/thread.c
       t@@ -54,9 +54,9 @@ _threaddebug(char *fmt, ...)
                va_end(arg);
                t = proc()->thread;
                if(t)
       -                fprint(fd, "%d.%d: %s\n", getpid(), t->id, buf);
       +                fprint(fd, "%p %d.%d: %s\n", proc(), getpid(), t->id, buf);
                else
       -                fprint(fd, "%d._: %s\n", getpid(), buf);
       +                fprint(fd, "%p %d._: %s\n", proc(), getpid(), buf);
        }
        
        static _Thread*
       t@@ -219,20 +219,28 @@ proccreate(void (*fn)(void*), void *arg, uint stack)
        static void
        procswitch(Proc *p, _Thread *from, _Thread *to)
        {
       -// fprint(2, "procswitch %p %d %d\n", p, from?from->id:-1, to?to->id:-1);
       +        _threaddebug("procswitch %p %d %d", p, from?from->id:-1, to?to->id:-1);
                lock(&p->schedlock);
                from->schedrend.l = &p->schedlock;
                if(to) {
                        p->schedthread = to;
                        to->schedrend.l = &p->schedlock;
       +                _threaddebug("procswitch wakeup %p %d", p, to->id);
                        _procwakeup(&to->schedrend);
                }
                if(p->schedthread != from) {
                        if(from->exiting) {
                                unlock(&p->schedlock);
                                _threadpexit();
       +                        _threaddebug("procswitch exit wakeup!!!\n");
                        }
       -                _procsleep(&from->schedrend);
       +                while(p->schedthread != from) {
       +                        _threaddebug("procswitch sleep %p %d", p, from->id);
       +                        _procsleep(&from->schedrend);
       +                        _threaddebug("procswitch awake %p %d", p, from->id);
       +                }
       +                if(p->schedthread != from)
       +                        sysfatal("_procswitch %p %p oops", p->schedthread, from);
                }
                unlock(&p->schedlock);
        }
       t@@ -448,6 +456,7 @@ Top:
                                procswitch(p, p->thread0, t);
                        else
                                contextswitch(&p->schedcontext, &t->context);
       +                _threaddebug("back in scheduler");
        /*print("back in scheduler\n"); */
                        goto Top;
                }
       t@@ -589,6 +598,10 @@ threadqlock(QLock *l, int block, ulong pc)
                if(l->owner == nil){
                        l->owner = (*threadnow)();
        /*print("qlock %p @%#x by %p\n", l, pc, l->owner); */
       +                if(l->owner == nil) {
       +                        fprint(2, "%s: qlock uncontended owner=nil oops\n", argv0);
       +                        abort();
       +                }
                        unlock(&l->l);
                        return 1;
                }
       t@@ -613,6 +626,11 @@ threadqlock(QLock *l, int block, ulong pc)
                                argv0, pc, l->owner, (*threadnow)());
                        abort();
                }
       +        if(l->owner == nil) {
       +                fprint(2, "%s: qlock threadswitch owner=nil oops\n", argv0);
       +                abort();
       +        }
       +
        /*print("qlock wakeup %p @%#x by %p\n", l, pc, (*threadnow)()); */
                return 1;
        }
       t@@ -818,7 +836,7 @@ main(int argc, char **argv)
                // Easier to just run in pthread-per-thread mode.
                pthreadperthread = 1;
        #endif
       -        if(strstr(opts, "nodaemon") || getenv("NOLIBTHREADDAEMONIZE") == nil)
       +        if(strstr(opts, "nodaemon") == nil && getenv("NOLIBTHREADDAEMONIZE") == nil)
                        _threadsetupdaemonize();
        
                threadargc = argc;