tlibthread: delete NetBSD special case - 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 5b37d9126474864b5299426e27b2af37fcc96dd0
 (DIR) parent 69439fae6705a125047246c889384ed3aeb4d104
 (HTM) Author: Russ Cox <rsc@swtch.com>
       Date:   Wed, 30 Dec 2020 00:06:35 -0500
       
       libthread: delete NetBSD special case
       
       I added a direct call from thread.c to pthread.c's _threadpthreadstart
       in May, and no one has complained about NetBSD being broken.
       So probably no one is using this on NetBSD at all.
       Make pthread the only option.
       
       Diffstat:
         D src/libthread/NetBSD-386-asm.s      |       7 -------
         D src/libthread/NetBSD-power-asm.s    |      16 ----------------
         D src/libthread/NetBSD.c              |     437 -------------------------------
         M src/libthread/sysofiles.sh          |       9 ++++-----
       
       4 files changed, 4 insertions(+), 465 deletions(-)
       ---
 (DIR) diff --git a/src/libthread/NetBSD-386-asm.s b/src/libthread/NetBSD-386-asm.s
       t@@ -1,7 +0,0 @@
       -.globl _tas
       -_tas:
       -        movl $0xCAFEBABE, %eax
       -        movl 4(%esp), %ecx
       -        xchgl %eax, 0(%ecx)
       -        ret
       -
 (DIR) diff --git a/src/libthread/NetBSD-power-asm.s b/src/libthread/NetBSD-power-asm.s
       t@@ -1,16 +0,0 @@
       -        .globl        _tas
       -_tas:
       -        li        %r0, 0
       -        mr        %r4, %r3
       -        lis        %r5, 0xcafe
       -        ori        %r5, %r5, 0xbabe
       -1:
       -        lwarx        %r3, %r0, %r4
       -        cmpwi        %r3, 0
       -        bne        2f
       -        stwcx.        %r5, %r0, %r4
       -        bne-        1b
       -2:
       -        sync
       -        blr
       -
 (DIR) diff --git a/src/libthread/NetBSD.c b/src/libthread/NetBSD.c
       t@@ -1,437 +0,0 @@
       -#include "threadimpl.h"
       -
       -#undef exits
       -#undef _exits
       -
       -static int
       -timefmt(Fmt *fmt)
       -{
       -        static char *mon[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
       -                "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
       -        vlong ns;
       -        Tm tm;
       -        ns = nsec();
       -        tm = *localtime(time(0));
       -        return fmtprint(fmt, "%s %2d %02d:%02d:%02d.%03d",
       -                mon[tm.mon], tm.mday, tm.hour, tm.min, tm.sec,
       -                (int)(ns%1000000000)/1000000);
       -}
       -
       -/*
       - * spin locks
       - */
       -extern int _tas(int*);
       -
       -void
       -_threadunlock(Lock *l, ulong pc)
       -{
       -        USED(pc);
       -
       -        l->held = 0;
       -}
       -
       -int
       -_threadlock(Lock *l, int block, ulong pc)
       -{
       -        int i;
       -static int first=1;
       -if(first) {first=0; fmtinstall('\001', timefmt);}
       -
       -        USED(pc);
       -
       -        /* once fast */
       -        if(!_tas(&l->held))
       -                return 1;
       -        if(!block)
       -                return 0;
       -
       -        /* a thousand times pretty fast */
       -        for(i=0; i<1000; i++){
       -                if(!_tas(&l->held))
       -                        return 1;
       -                sched_yield();
       -        }
       -        /* now increasingly slow */
       -        for(i=0; i<10; i++){
       -                if(!_tas(&l->held))
       -                        return 1;
       -                usleep(1);
       -        }
       -fprint(2, "%\001 %s: lock loop1 %p from %lux\n", argv0, l, pc);
       -        for(i=0; i<10; i++){
       -                if(!_tas(&l->held))
       -                        return 1;
       -                usleep(10);
       -        }
       -fprint(2, "%\001 %s: lock loop2 %p from %lux\n", argv0, l, pc);
       -        for(i=0; i<10; i++){
       -                if(!_tas(&l->held))
       -                        return 1;
       -                usleep(100);
       -        }
       -fprint(2, "%\001 %s: lock loop3 %p from %lux\n", argv0, l, pc);
       -        for(i=0; i<10; i++){
       -                if(!_tas(&l->held))
       -                        return 1;
       -                usleep(1000);
       -        }
       -fprint(2, "%\001 %s: lock loop4 %p from %lux\n", argv0, l, pc);
       -        for(i=0; i<10; i++){
       -                if(!_tas(&l->held))
       -                        return 1;
       -                usleep(10*1000);
       -        }
       -fprint(2, "%\001 %s: lock loop5 %p from %lux\n", argv0, l, pc);
       -        for(i=0; i<1000; i++){
       -                if(!_tas(&l->held))
       -                        return 1;
       -                usleep(100*1000);
       -        }
       -fprint(2, "%\001 %s: lock loop6 %p from %lux\n", argv0, l, pc);
       -        /* take your time */
       -        while(_tas(&l->held))
       -                usleep(1000*1000);
       -        return 1;
       -}
       -
       -/*
       - * sleep and wakeup
       - */
       -static void
       -ign(int x)
       -{
       -        USED(x);
       -}
       -
       -static void /*__attribute__((constructor))*/
       -ignusr1(int restart)
       -{
       -        struct sigaction sa;
       -
       -        memset(&sa, 0, sizeof sa);
       -        sa.sa_handler = ign;
       -        sigemptyset(&sa.sa_mask);
       -        sigaddset(&sa.sa_mask, SIGUSR1);
       -        if(restart)
       -                sa.sa_flags = SA_RESTART;
       -        sigaction(SIGUSR1, &sa, nil);
       -}
       -
       -void
       -_procsleep(_Procrendez *r)
       -{
       -        sigset_t mask;
       -
       -        /*
       -         * Go to sleep.
       -         *
       -         * Block USR1, set the handler to interrupt system calls,
       -         * unlock the vouslock so our waker can wake us,
       -         * and then suspend.
       -         */
       -again:
       -        r->asleep = 1;
       -        r->pid = getpid();
       -
       -        sigprocmask(SIG_SETMASK, nil, &mask);
       -        sigaddset(&mask, SIGUSR1);
       -        sigprocmask(SIG_SETMASK, &mask, nil);
       -        ignusr1(0);
       -        unlock(r->l);
       -        sigdelset(&mask, SIGUSR1);
       -        sigsuspend(&mask);
       -
       -        /*
       -         * We're awake.  Make USR1 not interrupt system calls.
       -         */
       -        lock(r->l);
       -        ignusr1(1);
       -        if(r->asleep && r->pid == getpid()){
       -                /* Didn't really wake up - signal from something else */
       -                goto again;
       -        }
       -}
       -
       -void
       -_procwakeupandunlock(_Procrendez *r)
       -{
       -        int pid;
       -
       -        pid = 0;
       -        if(r->asleep){
       -                r->asleep = 0;
       -                assert(r->pid >= 1);
       -                pid = r->pid;
       -        }
       -        assert(r->l);
       -        unlock(r->l);
       -        if(pid)
       -                kill(pid, SIGUSR1);
       -}
       -
       -/*
       - * process creation and exit
       - */
       -typedef struct Stackfree Stackfree;
       -struct Stackfree
       -{
       -        Stackfree        *next;
       -        int        pid;
       -        int        pid1;
       -};
       -static Lock stacklock;
       -static Stackfree *stackfree;
       -
       -static void
       -delayfreestack(uchar *stk, int pid, int pid1)
       -{
       -        Stackfree *sf;
       -
       -        sf = (Stackfree*)stk;
       -        sf->pid = pid;
       -        sf->pid1 = pid1;
       -        lock(&stacklock);
       -        sf->next = stackfree;
       -        stackfree = sf;
       -        unlock(&stacklock);
       -}
       -
       -static void
       -dofreestacks(void)
       -{
       -        Stackfree *sf, *last, *next;
       -
       -        if(stackfree==nil || !canlock(&stacklock))
       -                return;
       -
       -        for(last=nil,sf=stackfree; sf; last=sf,sf=next){
       -                next = sf->next;
       -                if(sf->pid >= 1 && kill(sf->pid, 0) < 0 && errno == ESRCH)
       -                if(sf->pid1 >= 1 && kill(sf->pid1, 0) < 0 && errno == ESRCH){
       -                        free(sf);
       -                        if(last)
       -                                last->next = next;
       -                        else
       -                                stackfree = next;
       -                        sf = last;
       -                }
       -        }
       -        unlock(&stacklock);
       -}
       -
       -static int
       -startprocfn(void *v)
       -{
       -        void **a;
       -        uchar *stk;
       -        void (*fn)(void*);
       -        Proc *p;
       -        int pid0, pid1;
       -
       -        a = (void**)v;
       -        fn = a[0];
       -        p = a[1];
       -        stk = a[2];
       -        pid0 = (int)a[4];
       -        pid1 = getpid();
       -        free(a);
       -        p->osprocid = pid1;
       -
       -        (*fn)(p);
       -
       -        delayfreestack(stk, pid0, pid1);
       -        _exit(0);
       -        return 0;
       -}
       -
       -/*
       - * indirect through here so that parent need not wait for child zombie
       - *
       - * slight race - if child exits and then another process starts before we
       - * manage to exit, we'll be running on a freed stack.
       - */
       -static int
       -trampnowait(void *v)
       -{
       -        void **a;
       -        int *kidpid;
       -
       -        a = (void*)v;
       -        kidpid = a[3];
       -        a[4] = (void*)getpid();
       -        *kidpid = clone(startprocfn, a[2]+65536-512, CLONE_VM|CLONE_FILES, a);
       -        _exit(0);
       -        return 0;
       -}
       -
       -void
       -_procstart(Proc *p, void (*fn)(Proc*))
       -{
       -        void **a;
       -        uchar *stk;
       -        int pid, kidpid, status;
       -
       -        dofreestacks();
       -        a = malloc(5*sizeof a[0]);
       -        if(a == nil)
       -                sysfatal("_procstart malloc: %r");
       -        stk = malloc(65536);
       -        if(stk == nil)
       -                sysfatal("_procstart malloc stack: %r");
       -
       -        a[0] = fn;
       -        a[1] = p;
       -        a[2] = stk;
       -        a[3] = &kidpid;
       -        kidpid = -1;
       -
       -        pid = clone(trampnowait, stk+65536-16, CLONE_VM|CLONE_FILES, a);
       -        if(pid > 0)
       -                if(wait4(pid, &status, __WALL, 0) < 0)
       -                        fprint(2, "ffork wait4: %r\n");
       -        if(pid < 0 || kidpid < 0){
       -                fprint(2, "_procstart clone: %r\n");
       -                abort();
       -        }
       -}
       -
       -static char *threadexitsmsg;
       -void
       -sigusr2handler(int s)
       -{
       -/*        fprint(2, "%d usr2 %d\n", time(0), getpid()); */
       -        if(threadexitsmsg)
       -                _exits(threadexitsmsg);
       -}
       -
       -void
       -threadexitsall(char *msg)
       -{
       -        static int pid[1024];
       -        int i, npid, mypid;
       -        Proc *p;
       -
       -        if(msg == nil)
       -                msg = "";
       -
       -        /*
       -         * Only one guy, ever, gets to run this.
       -         * If two guys do it, inevitably they end up
       -         * tripping over each other in the underlying
       -         * C library exit() implementation, which is
       -         * trying to run the atexit handlers and apparently
       -         * not thread safe.  This has been observed on
       -         * both Linux and OpenBSD.  Sigh.
       -         */
       -        {
       -                static Lock onelock;
       -                if(!canlock(&onelock))
       -                        _exits(threadexitsmsg);
       -                threadexitsmsg = msg;
       -        }
       -
       -        mypid = getpid();
       -        lock(&_threadprocslock);
       -        npid = 0;
       -        for(p=_threadprocs; p; p=p->next)
       -                if(p->osprocid != mypid && p->osprocid >= 1)
       -                        pid[npid++] = p->osprocid;
       -        for(i=0; i<npid; i++)
       -                kill(pid[i], SIGUSR2);
       -        unlock(&_threadprocslock);
       -        exits(msg);
       -}
       -
       -/*
       - * per-process data, indexed by pid
       - *
       - * could use modify_ldt and a segment register
       - * to avoid the many calls to getpid(), but i don't
       - * care -- this is compatibility code.  linux 2.6 with
       - * nptl is a good enough pthreads to avoid this whole file.
       - */
       -typedef struct Perproc Perproc;
       -struct Perproc
       -{
       -        int                pid;
       -        Proc        *proc;
       -};
       -
       -static Lock perlock;
       -static Perproc perproc[1024];
       -#define P ((Proc*)-1)
       -
       -static Perproc*
       -myperproc(void)
       -{
       -        int i, pid, h;
       -        Perproc *p;
       -
       -        pid = getpid();
       -        h = pid%nelem(perproc);
       -        for(i=0; i<nelem(perproc); i++){
       -                p = &perproc[(i+h)%nelem(perproc)];
       -                if(p->pid == pid)
       -                        return p;
       -                if(p->pid == 0){
       -                        print("found 0 at %d (h=%d)\n", (i+h)%nelem(perproc), h);
       -                        break;
       -                }
       -        }
       -        fprint(2, "myperproc %d (%s): cannot find self\n", pid, argv0);
       -        abort();
       -        return nil;
       -}
       -
       -static Perproc*
       -newperproc(void)
       -{
       -        int i, pid, h;
       -        Perproc *p;
       -
       -        lock(&perlock);
       -        pid = getpid();
       -        h = pid%nelem(perproc);
       -        for(i=0; i<nelem(perproc); i++){
       -                p = &perproc[(i+h)%nelem(perproc)];
       -                if(p->pid == pid || p->pid == -1 || p->pid == 0){
       -                        p->pid = pid;
       -                        unlock(&perlock);
       -                        return p;
       -                }
       -        }
       -        fprint(2, "newperproc %d: out of procs\n", pid);
       -        abort();
       -        return nil;
       -}
       -
       -Proc*
       -_threadproc(void)
       -{
       -        return myperproc()->proc;
       -}
       -
       -void
       -_threadsetproc(Proc *p)
       -{
       -        Perproc *pp;
       -
       -        if(p)
       -                p->osprocid = getpid();
       -        pp = newperproc();
       -        pp->proc = p;
       -        if(p == nil)
       -                pp->pid = -1;
       -}
       -
       -void
       -_pthreadinit(void)
       -{
       -        signal(SIGUSR2, sigusr2handler);
       -}
       -
       -void
       -_threadpexit(void)
       -{
       -        _exit(0);
       -}
 (DIR) diff --git a/src/libthread/sysofiles.sh b/src/libthread/sysofiles.sh
       t@@ -2,15 +2,14 @@
        
        test -f $PLAN9/config && . $PLAN9/config
        
       +echo pthread.o
       +
        case "$SYSNAME" in
       -NetBSD)
       -        echo ${SYSNAME}-${OBJTYPE}-asm.o $SYSNAME.o stkmalloc.o
       -        ;;
        OpenBSD)
       -        echo pthread.o stkmmap.o
       +        echo stkmmap.o
                ;;
        *)
       -        echo pthread.o stkmalloc.o
       +        echo stkmalloc.o
        esac
        
        # Various libc don't supply swapcontext, makecontext, so we do.