aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrsc <devnull@localhost>2005-05-01 18:38:12 +0000
committerrsc <devnull@localhost>2005-05-01 18:38:12 +0000
commitcea10000c59882b43525e4fd4fb17a55b7dba1c1 (patch)
tree63e81981a798e074e7de146e23c8e16eaf3a26dc
parente9ad899486adb4c561e682ced74ac0cb1c4539fc (diff)
downloadplan9port-cea10000c59882b43525e4fd4fb17a55b7dba1c1.tar.gz
plan9port-cea10000c59882b43525e4fd4fb17a55b7dba1c1.tar.bz2
plan9port-cea10000c59882b43525e4fd4fb17a55b7dba1c1.zip
OpenBSD/power support.
-rw-r--r--src/libthread/BSD.c384
-rw-r--r--src/libthread/FreeBSD.c364
-rw-r--r--src/libthread/OpenBSD-power-asm.S125
-rw-r--r--src/libthread/OpenBSD-power.c38
-rw-r--r--src/libthread/OpenBSD.c4
-rw-r--r--src/libthread/mkfile7
-rw-r--r--src/libthread/power-ucontext.h (renamed from src/libthread/Darwin-ucontext.h)0
-rw-r--r--src/libthread/sysofiles.sh3
-rw-r--r--src/libthread/threadimpl.h11
9 files changed, 567 insertions, 369 deletions
diff --git a/src/libthread/BSD.c b/src/libthread/BSD.c
new file mode 100644
index 00000000..2679cd21
--- /dev/null
+++ b/src/libthread/BSD.c
@@ -0,0 +1,384 @@
+#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;
+ sched_yield();
+ }
+ /* 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);
+}
+
+/*
+ * 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 = "";
+ 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
+_pthreadinit(void)
+{
+ __isthreaded = 1;
+ signal(SIGUSR2, sigusr2handler);
+}
+
+void
+_threadpexit(void)
+{
+ _exit(0);
+}
+
diff --git a/src/libthread/FreeBSD.c b/src/libthread/FreeBSD.c
index d80aaec9..e6ce09b2 100644
--- a/src/libthread/FreeBSD.c
+++ b/src/libthread/FreeBSD.c
@@ -1,368 +1,6 @@
#include "threadimpl.h"
-#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;
- sched_yield();
- }
- /* 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 FreeBSD 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);
-}
-
-/*
- * 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 = "";
- 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
- *
- * 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: 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
-_pthreadinit(void)
-{
- __isthreaded = 1;
- signal(SIGUSR2, sigusr2handler);
-}
-
-void
-_threadpexit(void)
-{
- _exit(0);
-}
-
+#include "BSD.c"
/*
* FreeBSD 4 and earlier needs the context functions.
diff --git a/src/libthread/OpenBSD-power-asm.S b/src/libthread/OpenBSD-power-asm.S
new file mode 100644
index 00000000..25ceb45c
--- /dev/null
+++ b/src/libthread/OpenBSD-power-asm.S
@@ -0,0 +1,125 @@
+#include <sys/syscall.h>
+#include <machine/asm.h>
+
+ENTRY(_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
+
+ENTRY(_getmcontext) /* xxx: instruction scheduling */
+ mflr %r0
+ mfcr %r5
+ mfctr %r6
+ mfxer %r7
+ stw %r0, 0*4(%r3)
+ stw %r5, 1*4(%r3)
+ stw %r6, 2*4(%r3)
+ stw %r7, 3*4(%r3)
+
+ stw %r1, 4*4(%r3)
+ stw %r2, 5*4(%r3)
+ li %r5, 1 /* return value for setmcontext */
+ stw %r5, 6*4(%r3)
+
+ stw %r13, (0+7)*4(%r3) /* callee-save GPRs */
+ stw %r14, (1+7)*4(%r3) /* xxx: block move */
+ stw %r15, (2+7)*4(%r3)
+ stw %r16, (3+7)*4(%r3)
+ stw %r17, (4+7)*4(%r3)
+ stw %r18, (5+7)*4(%r3)
+ stw %r19, (6+7)*4(%r3)
+ stw %r20, (7+7)*4(%r3)
+ stw %r21, (8+7)*4(%r3)
+ stw %r22, (9+7)*4(%r3)
+ stw %r23, (10+7)*4(%r3)
+ stw %r24, (11+7)*4(%r3)
+ stw %r25, (12+7)*4(%r3)
+ stw %r26, (13+7)*4(%r3)
+ stw %r27, (14+7)*4(%r3)
+ stw %r28, (15+7)*4(%r3)
+ stw %r29, (16+7)*4(%r3)
+ stw %r30, (17+7)*4(%r3)
+ stw %r31, (18+7)*4(%r3)
+
+ li %r3, 0 /* return */
+ blr
+
+ENTRY(_setmcontext)
+ lwz %r13, (0+7)*4(%r3) /* callee-save GPRs */
+ lwz %r14, (1+7)*4(%r3) /* xxx: block move */
+ lwz %r15, (2+7)*4(%r3)
+ lwz %r16, (3+7)*4(%r3)
+ lwz %r17, (4+7)*4(%r3)
+ lwz %r18, (5+7)*4(%r3)
+ lwz %r19, (6+7)*4(%r3)
+ lwz %r20, (7+7)*4(%r3)
+ lwz %r21, (8+7)*4(%r3)
+ lwz %r22, (9+7)*4(%r3)
+ lwz %r23, (10+7)*4(%r3)
+ lwz %r24, (11+7)*4(%r3)
+ lwz %r25, (12+7)*4(%r3)
+ lwz %r26, (13+7)*4(%r3)
+ lwz %r27, (14+7)*4(%r3)
+ lwz %r28, (15+7)*4(%r3)
+ lwz %r29, (16+7)*4(%r3)
+ lwz %r30, (17+7)*4(%r3)
+ lwz %r31, (18+7)*4(%r3)
+
+ lwz %r1, 4*4(%r3)
+ lwz %r2, 5*4(%r3)
+
+ lwz %r0, 0*4(%r3)
+ mtlr %r0
+ lwz %r0, 1*4(%r3)
+ mtcr %r0 /* mtcrf 0xFF, %r0 */
+ lwz %r0, 2*4(%r3)
+ mtctr %r0
+ lwz %r0, 3*4(%r3)
+ mtxer %r0
+
+ lwz %r3, 6*4(%r3)
+ blr
+
+ENTRY(rfork_thread)
+ /* sanity check */
+ cmpwi %r4, 0
+ beq 1f
+ cmpwi %r5, 0
+ beq 1f
+
+ mr %r7,%r4
+
+ /* call rfork */
+ li %r0, SYS_rfork
+ sc
+ cmpwi %r0, 0
+ bne 2f
+
+ /* check if we are parent or child */
+ cmpwi %r3, 0
+ bnelr
+
+ /* child */
+ mtlr %r5 /* fp */
+ mr %r3, %r6 /* arg */
+ mr %r1, %r7 /* new sp */
+ blrl
+
+ /* child returned, call _exit */
+ li %r0, SYS_exit
+ sc
+1:
+ li %r3, -1
+2:
+ b PIC_PLT(_C_LABEL(__cerror))
+
diff --git a/src/libthread/OpenBSD-power.c b/src/libthread/OpenBSD-power.c
new file mode 100644
index 00000000..c3c7e72b
--- /dev/null
+++ b/src/libthread/OpenBSD-power.c
@@ -0,0 +1,38 @@
+#include "threadimpl.h"
+
+void
+makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...)
+{
+ ulong *sp, *tos;
+ va_list arg;
+
+ tos = (ulong*)ucp->uc_stack.ss_sp+ucp->uc_stack.ss_size/sizeof(ulong);
+ sp = (ulong*)((ulong)(tos-16) & ~15);
+ ucp->mc.pc = (long)func;
+ ucp->mc.sp = (long)sp;
+ va_start(arg, argc);
+ ucp->mc.r3 = va_arg(arg, long);
+ va_end(arg);
+}
+
+int
+getcontext(ucontext_t *uc)
+{
+ return _getmcontext(&uc->mc);
+}
+
+int
+setcontext(ucontext_t *uc)
+{
+ _setmcontext(&uc->mc);
+ return 0;
+}
+
+int
+swapcontext(ucontext_t *oucp, ucontext_t *ucp)
+{
+ if(getcontext(oucp) == 0)
+ setcontext(ucp);
+ return 0;
+}
+
diff --git a/src/libthread/OpenBSD.c b/src/libthread/OpenBSD.c
new file mode 100644
index 00000000..9aaa28cb
--- /dev/null
+++ b/src/libthread/OpenBSD.c
@@ -0,0 +1,4 @@
+#include "threadimpl.h"
+
+#include "BSD.c"
+
diff --git a/src/libthread/mkfile b/src/libthread/mkfile
index b1bf3ccf..3750c796 100644
--- a/src/libthread/mkfile
+++ b/src/libthread/mkfile
@@ -15,6 +15,8 @@ OFILES=\
<$PLAN9/src/mksyslib
HFILES=thread.h threadimpl.h
+OpenBSD.$O FreeBSD.$O: BSD.c
+NetBSD.$O: Linux.c
tprimes: tprimes.$O
9l -o $target $target.$O $PLAN9/lib/$LIB -l9 -lpthread
@@ -24,9 +26,8 @@ tspawnloop: tspawnloop.$O
9l -o $target $target.$O $PLAN9/lib/$LIB -l9 -lpthread
%.$O: %.c
- $CC -I. $stem.c
+ $CC $CFLAGS -I. $stem.c
-NetBSD.$O: Linux.c
test:V: tprimes tspawn
primes 1 10007 >p1.txt
@@ -40,5 +41,3 @@ test:V: tprimes tspawn
CLEANFILES=p1.txt p2.txt tp1.txt tp2.txt
-
-
diff --git a/src/libthread/Darwin-ucontext.h b/src/libthread/power-ucontext.h
index a39be28a..a39be28a 100644
--- a/src/libthread/Darwin-ucontext.h
+++ b/src/libthread/power-ucontext.h
diff --git a/src/libthread/sysofiles.sh b/src/libthread/sysofiles.sh
index 37ab6eb5..4832145b 100644
--- a/src/libthread/sysofiles.sh
+++ b/src/libthread/sysofiles.sh
@@ -23,6 +23,9 @@ case "$tag" in
*-Darwin-*)
echo ${SYSNAME}-${OBJTYPE}-asm.o ${SYSNAME}-${OBJTYPE}.o pthread.o
;;
+*-OpenBSD-*)
+ echo ${SYSNAME}-${OBJTYPE}-asm.o ${SYSNAME}-${OBJTYPE}.o $SYSNAME.o
+ ;;
*)
echo pthread.o
esac
diff --git a/src/libthread/threadimpl.h b/src/libthread/threadimpl.h
index 346288de..fff874d8 100644
--- a/src/libthread/threadimpl.h
+++ b/src/libthread/threadimpl.h
@@ -5,7 +5,9 @@
#include <sys/wait.h>
#include <sched.h>
#include <signal.h>
-#include <ucontext.h>
+#if !defined(_OpenBSD__)
+# include <ucontext.h>
+#endif
#include <sys/utsname.h>
#include "libc.h"
#include "thread.h"
@@ -22,7 +24,12 @@ extern void makecontext(ucontext_t*, void(*)(), int, ...);
# define mcontext_t libthread_mcontext_t
# define ucontext libthread_ucontext
# define ucontext_t libthread_ucontext_t
-# include "Darwin-ucontext.h"
+# include "power-ucontext.h"
+#endif
+
+#if defined(__OpenBSD__)
+# include "power-ucontext.h"
+extern pid_t rfork_thread(int, void*, int(*)(void*), void*);
#endif
typedef struct Context Context;