diff options
-rw-r--r-- | include/u.h | 6 | ||||
-rw-r--r-- | src/libthread/BSD.c | 403 | ||||
-rw-r--r-- | src/libthread/FreeBSD-386-asm.s | 52 | ||||
-rw-r--r-- | src/libthread/FreeBSD.c | 34 | ||||
-rw-r--r-- | src/libthread/OpenBSD-386-asm.s | 53 | ||||
-rw-r--r-- | src/libthread/mkfile | 1 | ||||
-rw-r--r-- | src/libthread/threadimpl.h | 9 |
7 files changed, 54 insertions, 504 deletions
diff --git a/include/u.h b/include/u.h index d0cd6396..8a715b1e 100644 --- a/include/u.h +++ b/include/u.h @@ -86,10 +86,8 @@ typedef long p9jmp_buf[sizeof(sigjmp_buf)/sizeof(long)]; #elif defined(__FreeBSD__) # include <sys/types.h> # include <osreldate.h> -# if __FreeBSD_version >= 500000 -# define PLAN9PORT_USING_PTHREADS 1 -# include <pthread.h> -# endif +# define PLAN9PORT_USING_PTHREADS 1 +# include <pthread.h> # if !defined(_POSIX_SOURCE) # undef _NEEDUSHORT # undef _NEEDUINT diff --git a/src/libthread/BSD.c b/src/libthread/BSD.c deleted file mode 100644 index 737c0a63..00000000 --- a/src/libthread/BSD.c +++ /dev/null @@ -1,403 +0,0 @@ -#undef exits -#undef _exits - -extern int __isthreaded; - -/* - * 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; - - 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; - sleep(0); - } - /* increasingly slow */ - for(i=0; i<10; i++){ - if(!_tas(&l->held)) - return 1; - usleep(1); - } - for(i=0; i<10; i++){ - if(!_tas(&l->held)) - return 1; - usleep(10); - } - for(i=0; i<10; i++){ - if(!_tas(&l->held)) - return 1; - usleep(100); - } - for(i=0; i<10; i++){ - if(!_tas(&l->held)) - return 1; - usleep(1000); - } - for(i=0; i<10; i++){ - if(!_tas(&l->held)) - return 1; - usleep(10*1000); - } - /* now nice and slow */ - for(i=0; i<1000; i++){ - if(!_tas(&l->held)) - return 1; - usleep(100*1000); - } - /* take your time */ - while(_tas(&l->held)) - usleep(1000*1000); - return 1; -} - -/* - * For libc. - */ - -typedef struct { - volatile long access_lock; - volatile long lock_owner; - volatile char *fname; - volatile int lineno; -} spinlock_t; - -void -_spinlock(spinlock_t *lk) -{ - lock((Lock*)&lk->access_lock); -} - -void -_spinunlock(spinlock_t *lk) -{ - unlock((Lock*)&lk->access_lock); -} - - - -/* - * 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 -_procwakeup(_Procrendez *r) -{ - if(r->asleep){ - r->asleep = 0; - assert(r->pid >= 1); - kill(r->pid, SIGUSR1); - } -} - -void -_procwakeupandunlock(_Procrendez *r) -{ - _procwakeup(r); - unlock(r->l); -} - - -/* - * process creation and exit - */ -typedef struct Stackfree Stackfree; -struct Stackfree -{ - Stackfree *next; - int pid; -}; -static Lock stacklock; -static Stackfree *stackfree; - -static void -delayfreestack(uchar *stk) -{ - Stackfree *sf; - - sf = (Stackfree*)stk; - sf->pid = getpid(); - 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){ - 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; - - a = (void**)v; - fn = a[0]; - p = a[1]; - stk = a[2]; - free(a); - p->osprocid = getpid(); - - (*fn)(p); - - delayfreestack(stk); - _exit(0); - return 0; -} - -void -_procstart(Proc *p, void (*fn)(Proc*)) -{ - void **a; - uchar *stk; - int pid; - - dofreestacks(); - a = malloc(3*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; - - pid = rfork_thread(RFPROC|RFMEM|RFNOWAIT, stk+65536-64, startprocfn, a); - if(pid < 0){ - fprint(2, "_procstart rfork_thread: %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; - } - - if(msg == nil) - msg = ""; - mypid = getpid(); - lock(&_threadprocslock); - threadexitsmsg = msg; - 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 - */ -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: cannot find self\n", pid); - 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 -_threadpexit(void) -{ - _exit(0); -} diff --git a/src/libthread/FreeBSD-386-asm.s b/src/libthread/FreeBSD-386-asm.s deleted file mode 100644 index 42169853..00000000 --- a/src/libthread/FreeBSD-386-asm.s +++ /dev/null @@ -1,52 +0,0 @@ -.globl _tas -_tas: - movl $0xCAFEBABE, %eax - movl 4(%esp), %ecx - xchgl %eax, 0(%ecx) - ret - -.globl getmcontext -getmcontext: - movl 4(%esp), %eax - - movl %fs, 8(%eax) - movl %es, 12(%eax) - movl %ds, 16(%eax) - movl %ss, 76(%eax) - movl %edi, 20(%eax) - movl %esi, 24(%eax) - movl %ebp, 28(%eax) - movl %ebx, 36(%eax) - movl %edx, 40(%eax) - movl %ecx, 44(%eax) - - movl $1, 48(%eax) /* %eax */ - movl (%esp), %ecx /* %eip */ - movl %ecx, 60(%eax) - leal 4(%esp), %ecx /* %esp */ - movl %ecx, 72(%eax) - - movl 44(%eax), %ecx /* restore %ecx */ - movl $0, %eax - ret - -.globl setmcontext -setmcontext: - movl 4(%esp), %eax - - movl 8(%eax), %fs - movl 12(%eax), %es - movl 16(%eax), %ds - movl 76(%eax), %ss - movl 20(%eax), %edi - movl 24(%eax), %esi - movl 28(%eax), %ebp - movl 36(%eax), %ebx - movl 40(%eax), %edx - movl 44(%eax), %ecx - - movl 72(%eax), %esp - pushl 60(%eax) /* new %eip */ - movl 48(%eax), %eax - ret - diff --git a/src/libthread/FreeBSD.c b/src/libthread/FreeBSD.c deleted file mode 100644 index 5c282465..00000000 --- a/src/libthread/FreeBSD.c +++ /dev/null @@ -1,34 +0,0 @@ -#include "threadimpl.h" - -#include "BSD.c" - -/* - * FreeBSD 4 and earlier needs the context functions. - */ -void -makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...) -{ - int *sp; - - sp = (int*)ucp->uc_stack.ss_sp+ucp->uc_stack.ss_size/4; - sp -= argc; - memmove(sp, &argc+1, argc*sizeof(int)); - *--sp = 0; /* return address */ - ucp->uc_mcontext.mc_eip = (long)func; - ucp->uc_mcontext.mc_esp = (int)sp; -} - -int -swapcontext(ucontext_t *oucp, ucontext_t *ucp) -{ - if(getcontext(oucp) == 0) - setcontext(ucp); - return 0; -} - -void -_pthreadinit(void) -{ - __isthreaded = 1; - signal(SIGUSR2, sigusr2handler); -} diff --git a/src/libthread/OpenBSD-386-asm.s b/src/libthread/OpenBSD-386-asm.s index dad1b536..42169853 100644 --- a/src/libthread/OpenBSD-386-asm.s +++ b/src/libthread/OpenBSD-386-asm.s @@ -1 +1,52 @@ -#include "FreeBSD-386-asm.s" +.globl _tas +_tas: + movl $0xCAFEBABE, %eax + movl 4(%esp), %ecx + xchgl %eax, 0(%ecx) + ret + +.globl getmcontext +getmcontext: + movl 4(%esp), %eax + + movl %fs, 8(%eax) + movl %es, 12(%eax) + movl %ds, 16(%eax) + movl %ss, 76(%eax) + movl %edi, 20(%eax) + movl %esi, 24(%eax) + movl %ebp, 28(%eax) + movl %ebx, 36(%eax) + movl %edx, 40(%eax) + movl %ecx, 44(%eax) + + movl $1, 48(%eax) /* %eax */ + movl (%esp), %ecx /* %eip */ + movl %ecx, 60(%eax) + leal 4(%esp), %ecx /* %esp */ + movl %ecx, 72(%eax) + + movl 44(%eax), %ecx /* restore %ecx */ + movl $0, %eax + ret + +.globl setmcontext +setmcontext: + movl 4(%esp), %eax + + movl 8(%eax), %fs + movl 12(%eax), %es + movl 16(%eax), %ds + movl 76(%eax), %ss + movl 20(%eax), %edi + movl 24(%eax), %esi + movl 28(%eax), %ebp + movl 36(%eax), %ebx + movl 40(%eax), %edx + movl 44(%eax), %ecx + + movl 72(%eax), %esp + pushl 60(%eax) /* new %eip */ + movl 48(%eax), %eax + ret + diff --git a/src/libthread/mkfile b/src/libthread/mkfile index f621ac60..31c4c7e5 100644 --- a/src/libthread/mkfile +++ b/src/libthread/mkfile @@ -16,7 +16,6 @@ OFILES=\ <$PLAN9/src/mksyslib HFILES=thread.h threadimpl.h -FreeBSD.$O: BSD.c NetBSD.$O: Linux.c tprimes: test/tprimes.$O diff --git a/src/libthread/threadimpl.h b/src/libthread/threadimpl.h index 6671f23c..e26ffe6b 100644 --- a/src/libthread/threadimpl.h +++ b/src/libthread/threadimpl.h @@ -15,15 +15,6 @@ #include "libc.h" #include "thread.h" -#if defined(__FreeBSD__) && __FreeBSD__ < 5 -extern int getmcontext(mcontext_t*); -extern void setmcontext(mcontext_t*); -#define setcontext(u) setmcontext(&(u)->uc_mcontext) -#define getcontext(u) getmcontext(&(u)->uc_mcontext) -extern int swapcontext(ucontext_t*, ucontext_t*); -extern void makecontext(ucontext_t*, void(*)(), int, ...); -#endif - #if defined(__APPLE__) /* * OS X before 10.5 (Leopard) does not provide |