diff options
author | Petter Rodhelind <petter.rodhelind@gmail.com> | 2021-02-18 20:21:24 +0100 |
---|---|---|
committer | Petter Rodhelind <petter.rodhelind@gmail.com> | 2021-02-18 20:21:24 +0100 |
commit | 181d56ee64da53279bb6ecf49c24ab54cfb7193f (patch) | |
tree | fc6c8736bb97790a257c5514998c583ffce7c41c /src/libthread/NetBSD.c | |
parent | 94c521bf102a74aec7e1a5c3a9ef5eaa968d4e14 (diff) | |
parent | 90971376a5e8620fc62579aa1b3be26245ec8c06 (diff) | |
download | plan9port-master.tar.gz plan9port-master.tar.bz2 plan9port-master.zip |
Diffstat (limited to 'src/libthread/NetBSD.c')
-rw-r--r-- | src/libthread/NetBSD.c | 437 |
1 files changed, 0 insertions, 437 deletions
diff --git a/src/libthread/NetBSD.c b/src/libthread/NetBSD.c deleted file mode 100644 index 2b14146b..00000000 --- a/src/libthread/NetBSD.c +++ /dev/null @@ -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); -} |