aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorrsc <devnull@localhost>2004-12-25 21:56:33 +0000
committerrsc <devnull@localhost>2004-12-25 21:56:33 +0000
commit1544f90960275dc9211bde30329c3258e0e1bf38 (patch)
treef55e7a73c03aaa24daa7cc2ad02822b921c477f9 /src
parent7788fd54094693384ef5c92c475656dba8819feb (diff)
downloadplan9port-1544f90960275dc9211bde30329c3258e0e1bf38.tar.gz
plan9port-1544f90960275dc9211bde30329c3258e0e1bf38.tar.bz2
plan9port-1544f90960275dc9211bde30329c3258e0e1bf38.zip
New thread library
Diffstat (limited to 'src')
-rw-r--r--src/libthread/386.c62
-rw-r--r--src/libthread/FreeBSD-386.s18
-rw-r--r--src/libthread/Linux-clone.c185
-rw-r--r--src/libthread/NOTICE19
-rw-r--r--src/libthread/PowerMacintosh.c39
-rw-r--r--src/libthread/README19
-rw-r--r--src/libthread/asm-Darwin-PowerMacintosh.s80
-rw-r--r--src/libthread/asm-FreeBSD-386.s55
-rw-r--r--src/libthread/asm-Linux-386.s1
-rw-r--r--src/libthread/asm-Linux-power.s80
-rw-r--r--src/libthread/asm-OpenBSD-386.s49
-rw-r--r--src/libthread/asm-SunOS-sun4u.s51
-rw-r--r--src/libthread/channel.c500
-rw-r--r--src/libthread/chanprint.c20
-rw-r--r--src/libthread/create.c211
-rw-r--r--src/libthread/debug.c48
-rw-r--r--src/libthread/exec-unix.c147
-rw-r--r--src/libthread/exec.c153
-rw-r--r--src/libthread/execproc.ch183
-rw-r--r--src/libthread/exit-getpid.ch25
-rw-r--r--src/libthread/exit.c44
-rw-r--r--src/libthread/fdwait.c241
-rw-r--r--src/libthread/getpid.c7
-rw-r--r--src/libthread/id.c136
-rw-r--r--src/libthread/iocall.c55
-rw-r--r--src/libthread/ioclose.c16
-rw-r--r--src/libthread/iodial.c24
-rw-r--r--src/libthread/ioopen.c21
-rw-r--r--src/libthread/ioproc.c77
-rw-r--r--src/libthread/ioproc.h14
-rw-r--r--src/libthread/ioread.c20
-rw-r--r--src/libthread/ioreadn.c21
-rw-r--r--src/libthread/iorw.c178
-rw-r--r--src/libthread/iosleep.c16
-rw-r--r--src/libthread/iowrite.c22
-rw-r--r--src/libthread/kill.c90
-rw-r--r--src/libthread/label.h68
-rw-r--r--src/libthread/lib.c35
-rw-r--r--src/libthread/main.c98
-rw-r--r--src/libthread/memset.c8
-rw-r--r--src/libthread/memsetd.c8
-rw-r--r--src/libthread/mkfile73
-rw-r--r--src/libthread/note.c145
-rw-r--r--src/libthread/pid.c25
-rw-r--r--src/libthread/power.c40
-rw-r--r--src/libthread/procstack.ch75
-rw-r--r--src/libthread/proctab.c75
-rw-r--r--src/libthread/proctab.ch97
-rw-r--r--src/libthread/pthread.c271
-rw-r--r--src/libthread/qlock.c3
-rw-r--r--src/libthread/read9pmsg.c32
-rw-r--r--src/libthread/ref.c26
-rw-r--r--src/libthread/sched.c343
-rw-r--r--src/libthread/setproc.c36
-rw-r--r--src/libthread/sleep.c39
-rw-r--r--src/libthread/sun4u.c53
-rw-r--r--src/libthread/sysofiles.sh11
-rw-r--r--src/libthread/test/pthreadloop.c38
-rw-r--r--src/libthread/test/tprimes.c80
-rw-r--r--src/libthread/test/tspawn.c (renamed from src/libthread/tspawn.c)28
-rw-r--r--src/libthread/test/tspawnloop.c41
-rw-r--r--src/libthread/texec.c45
-rw-r--r--src/libthread/tfork.c23
-rw-r--r--src/libthread/thread.c535
-rw-r--r--src/libthread/thread.sh15
-rw-r--r--src/libthread/threadimpl.h241
-rw-r--r--src/libthread/tprimes.c68
-rw-r--r--src/libthread/trend.c31
-rw-r--r--src/libthread/tsignal.c43
-rw-r--r--src/libthread/ucontext.c49
70 files changed, 1041 insertions, 4684 deletions
diff --git a/src/libthread/386.c b/src/libthread/386.c
deleted file mode 100644
index 313c2be5..00000000
--- a/src/libthread/386.c
+++ /dev/null
@@ -1,62 +0,0 @@
-#if defined(__linux__)
-#include "ucontext.c"
-#else
-
-#include "threadimpl.h"
-/*
- * To use this you need some patches to Valgrind that
- * let it help out with detecting stack overflow.
- */
-#ifdef USEVALGRIND
-#include <valgrind/memcheck.h>
-#endif
-
-static void
-launcher386(void (*f)(void *arg), void *arg)
-{
- Proc *p;
- Thread *t;
-
- p = _threadgetproc();
- t = p->thread;
- _threadstacklimit(t->stk, t->stk+t->stksize);
-
- (*f)(arg);
- threadexits(nil);
-}
-
-void
-_threadinitstack(Thread *t, void (*f)(void*), void *arg)
-{
- ulong *tos;
-
- tos = (ulong*)&t->stk[t->stksize&~7];
- *--tos = (ulong)arg;
- *--tos = (ulong)f;
- t->sched.pc = (ulong)launcher386;
- t->sched.sp = (ulong)tos - 8; /* old PC and new PC */
-}
-
-void
-_threadinswitch(int enter)
-{
- USED(enter);
-#ifdef USEVALGRIND
- if(enter)
- VALGRIND_SET_STACK_LIMIT(0, 0, 0);
- else
- VALGRIND_SET_STACK_LIMIT(0, 0, 1);
-#endif
-}
-
-void
-_threadstacklimit(void *bottom, void *top)
-{
- USED(bottom);
- USED(top);
-
-#ifdef USEVALGRIND
- VALGRIND_SET_STACK_LIMIT(1, bottom, top);
-#endif
-}
-#endif
diff --git a/src/libthread/FreeBSD-386.s b/src/libthread/FreeBSD-386.s
deleted file mode 100644
index 624518e0..00000000
--- a/src/libthread/FreeBSD-386.s
+++ /dev/null
@@ -1,18 +0,0 @@
-
-.globl _xinc
-_xinc:
- movl 4(%esp), %eax
- lock incl 0(%eax)
- ret
-
-.globl _xdec
-_xdec:
- movl 4(%esp), %eax
- lock decl 0(%eax)
- jz iszero
- movl %eax, 1
- ret
-iszero:
- movl %eax, 0
- ret
-
diff --git a/src/libthread/Linux-clone.c b/src/libthread/Linux-clone.c
deleted file mode 100644
index 1f5e3bde..00000000
--- a/src/libthread/Linux-clone.c
+++ /dev/null
@@ -1,185 +0,0 @@
-#include <u.h>
-#include <errno.h>
-#include <sched.h>
-#include <sys/signal.h>
-#include <sys/wait.h>
-#include "threadimpl.h"
-
-#define procid() getpid()
-#define procexited(id) (kill((id), 0) < 0 && errno==ESRCH)
-
-static int multi;
-static Proc *theproc;
-
-/*
- * Run all execs forked from a special exec proc.
- */
-#include "execproc.ch"
-
-/*
- * Use _exits to exit one proc, and signals to tear everyone else down.
- */
-#include "exit-getpid.ch"
-
-/*
- * Use table for _threadmultiproc, _threadsetproc, _threadgetproc.
- */
-#include "proctab.ch"
-
-/*
- * Use per-process stack allocation code.
- */
-#include "procstack.ch"
-
-/*
- * Implement _threadstartproc using clone.
- *
- * Cannot use this on newer kernels (2.6+) because
- * on those kernels clone allows you to set up a per-thread
- * segment using %gs, and the C library and compilers
- * assume that you've done this. I don't want to learn
- * how to do this (the code below is scary enough),
- * so on those more recent kernels we use nptl (the
- * pthreads implementation), which is finally good enough.
- */
-
-/*
- * Trampoline to run f(arg).
- */
-static int
-tramp(void *v)
-{
- void (*fn)(void*), *arg;
- void **v2;
- void *p;
-
- v2 = v;
- fn = v2[0];
- arg = v2[1];
- p = v2[2];
- free(v2);
- fn(arg);
- abort(); /* not reached! */
- return 0;
-}
-
-/*
- * Trampnowait runs in the child, and starts a granchild to run f(arg).
- * When trampnowait proc exits, the connection between the
- * grandchild running f(arg) and the parent/grandparent is lost, so the
- * grandparent need not worry about cleaning up a zombie
- * when the grandchild finally exits.
- */
-static int
-trampnowait(void *v)
-{
- int pid;
- int cloneflag;
- void **v2;
- int *pidp;
- void *p;
-
- v2 = v;
- cloneflag = (int)v2[4];
- pidp = v2[3];
- p = v2[2];
- pid = clone(tramp, p+fforkstacksize-512, cloneflag, v);
- *pidp = pid;
- _exit(0);
- return 0;
-}
-
-static int
-ffork(int flags, void (*fn)(void*), void *arg)
-{
- void **v;
- char *p;
- int cloneflag, pid, thepid, status, nowait;
-
- p = mallocstack();
- v = malloc(sizeof(void*)*5);
- if(p==nil || v==nil){
- freestack(p);
- free(v);
- return -1;
- }
- cloneflag = 0;
- flags &= ~RFPROC;
- if(flags&RFMEM){
- cloneflag |= CLONE_VM;
- flags &= ~RFMEM;
- }
- if(!(flags&RFFDG))
- cloneflag |= CLONE_FILES;
- else
- flags &= ~RFFDG;
- nowait = flags&RFNOWAIT;
-// if(!(flags&RFNOWAIT))
-// cloneflag |= SIGCHLD;
-// else
- flags &= ~RFNOWAIT;
- if(flags){
- fprint(2, "unknown rfork flags %x\n", flags);
- freestack(p);
- free(v);
- return -1;
- }
- v[0] = fn;
- v[1] = arg;
- v[2] = p;
- v[3] = &thepid;
- v[4] = (void*)cloneflag;
- thepid = -1;
- pid = clone(nowait ? trampnowait : tramp, p+fforkstacksize-16, cloneflag, v);
- if(pid > 0 && nowait){
- if(wait4(pid, &status, __WALL, 0) < 0)
- fprint(2, "ffork wait4: %r\n");
- }else
- thepid = pid;
- if(thepid == -1)
- freestack(p);
- else{
- ((Stack*)p)->pid = thepid;
- }
- return thepid;
-}
-
-/*
- * Called to start a new proc.
- */
-void
-_threadstartproc(Proc *p)
-{
- int pid;
- Proc *np;
-
- np = p->newproc;
- pid = ffork(RFPROC|RFMEM|RFNOWAIT, _threadscheduler, np);
- if(pid == -1)
- sysfatal("starting new proc: %r");
- np->pid = pid;
-}
-
-/*
- * Called to associate p with the current pthread.
- */
-void
-_threadinitproc(Proc *p)
-{
- sigset_t mask;
-
- p->pid = getpid();
- sigemptyset(&mask);
- sigaddset(&mask, WAITSIG);
- sigprocmask(SIG_BLOCK, &mask, nil);
- _threadsetproc(p);
-}
-
-/*
- * Called from mainlauncher before threadmain.
- */
-void
-_threadmaininit(void)
-{
-}
-
diff --git a/src/libthread/NOTICE b/src/libthread/NOTICE
deleted file mode 100644
index 8bf69d6a..00000000
--- a/src/libthread/NOTICE
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * The authors of this software are Russ Cox, Sape Mullender, and Rob Pike.
- * Copyright (c) 2003 by Lucent Technologies.
- * Permission to use, copy, modify, and distribute this software for any
- * purpose without fee is hereby granted, provided that this entire notice
- * is included in all copies of any software which is or includes a copy
- * or modification of this software and in all copies of the supporting
- * documentation for such software.
- * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
- * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
- * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
- * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
-*/
-
-This is a Unix port of the Plan 9 thread library.
-
-Please send comments about the packaging
-to Russ Cox <rsc@post.harvard.edu>.
-
diff --git a/src/libthread/PowerMacintosh.c b/src/libthread/PowerMacintosh.c
deleted file mode 100644
index 94d4db9a..00000000
--- a/src/libthread/PowerMacintosh.c
+++ /dev/null
@@ -1,39 +0,0 @@
-#include "threadimpl.h"
-
-static void
-launcherpower(int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7,
- void (*f)(void *arg), void *arg)
-{
- (*f)(arg);
- threadexits(nil);
-}
-
-void
-_threadinitstack(Thread *t, void (*f)(void*), void *arg)
-{
- ulong *tos, *stk;
-
- tos = (ulong*)&t->stk[t->stksize&~7];
- stk = tos;
- --stk;
- --stk;
- --stk;
- --stk;
- *--stk = (ulong)arg;
- *--stk = (ulong)f;
- t->sched.pc = (ulong)launcherpower+LABELDPC;
- t->sched.sp = (ulong)tos-80;
-}
-
-void
-_threadinswitch(int enter)
-{
- USED(enter);
-}
-
-void
-_threadstacklimit(void *addr, void *addr2)
-{
- USED(addr);
-}
-
diff --git a/src/libthread/README b/src/libthread/README
deleted file mode 100644
index 8bf69d6a..00000000
--- a/src/libthread/README
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * The authors of this software are Russ Cox, Sape Mullender, and Rob Pike.
- * Copyright (c) 2003 by Lucent Technologies.
- * Permission to use, copy, modify, and distribute this software for any
- * purpose without fee is hereby granted, provided that this entire notice
- * is included in all copies of any software which is or includes a copy
- * or modification of this software and in all copies of the supporting
- * documentation for such software.
- * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
- * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
- * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
- * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
-*/
-
-This is a Unix port of the Plan 9 thread library.
-
-Please send comments about the packaging
-to Russ Cox <rsc@post.harvard.edu>.
-
diff --git a/src/libthread/asm-Darwin-PowerMacintosh.s b/src/libthread/asm-Darwin-PowerMacintosh.s
deleted file mode 100644
index c503e1d6..00000000
--- a/src/libthread/asm-Darwin-PowerMacintosh.s
+++ /dev/null
@@ -1,80 +0,0 @@
-/* get FPR and VR use flags with sc 0x7FF3 */
-/* get vsave with mfspr reg, 256 */
-
-.text
-.align 2
-
-.globl __setlabel
-
-__setlabel: /* 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)
-
- stw r13, (0+6)*4(r3) /* callee-save GPRs */
- stw r14, (1+6)*4(r3) /* xxx: block move */
- stw r15, (2+6)*4(r3)
- stw r16, (3+6)*4(r3)
- stw r17, (4+6)*4(r3)
- stw r18, (5+6)*4(r3)
- stw r19, (6+6)*4(r3)
- stw r20, (7+6)*4(r3)
- stw r21, (8+6)*4(r3)
- stw r22, (9+6)*4(r3)
- stw r23, (10+6)*4(r3)
- stw r24, (11+6)*4(r3)
- stw r25, (12+6)*4(r3)
- stw r26, (13+6)*4(r3)
- stw r27, (14+6)*4(r3)
- stw r28, (15+6)*4(r3)
- stw r29, (16+6)*4(r3)
- stw r30, (17+6)*4(r3)
- stw r31, (18+6)*4(r3)
-
- li r3, 0 /* return */
- blr
-
-.globl __gotolabel
-
-__gotolabel:
- lwz r13, (0+6)*4(r3) /* callee-save GPRs */
- lwz r14, (1+6)*4(r3) /* xxx: block move */
- lwz r15, (2+6)*4(r3)
- lwz r16, (3+6)*4(r3)
- lwz r17, (4+6)*4(r3)
- lwz r18, (5+6)*4(r3)
- lwz r19, (6+6)*4(r3)
- lwz r20, (7+6)*4(r3)
- lwz r21, (8+6)*4(r3)
- lwz r22, (9+6)*4(r3)
- lwz r23, (10+6)*4(r3)
- lwz r24, (11+6)*4(r3)
- lwz r25, (12+6)*4(r3)
- lwz r26, (13+6)*4(r3)
- lwz r27, (14+6)*4(r3)
- lwz r28, (15+6)*4(r3)
- lwz r29, (16+6)*4(r3)
- lwz r30, (17+6)*4(r3)
- lwz r31, (18+6)*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
- li r3, 1
- blr
diff --git a/src/libthread/asm-FreeBSD-386.s b/src/libthread/asm-FreeBSD-386.s
deleted file mode 100644
index c815ac58..00000000
--- a/src/libthread/asm-FreeBSD-386.s
+++ /dev/null
@@ -1,55 +0,0 @@
-.globl _setlabel
-.type _setlabel,@function
-
-_setlabel:
- movl 4(%esp), %eax
- movl 0(%esp), %edx
- movl %edx, 0(%eax)
- movl %ebx, 4(%eax)
- movl %esp, 8(%eax)
- movl %ebp, 12(%eax)
- movl %esi, 16(%eax)
- movl %edi, 20(%eax)
- xorl %eax, %eax
- ret
-
-.globl _gotolabel
-.type _gotolabel,@function
-
-_gotolabel:
- pushl $1
- call _threadinswitch
- popl %eax
- movl 4(%esp), %edx
- movl 0(%edx), %ecx
- movl 4(%edx), %ebx
- movl 8(%edx), %esp
- movl 12(%edx), %ebp
- movl 16(%edx), %esi
- movl 20(%edx), %edi
- movl %ecx, 0(%esp)
- pushl $0
- call _threadinswitch
- popl %eax
- xorl %eax, %eax
- incl %eax
- ret
-
-
-# .globl _xinc
-# _xinc:
-# movl 4(%esp), %eax
-# lock incl 0(%eax)
-# ret
-#
-# .globl _xdec
-# _xdec:
-# movl 4(%esp), %eax
-# lock decl 0(%eax)
-# jz iszero
-# movl $1, %eax
-# ret
-# iszero:
-# movl $0, %eax
-# ret
-#
diff --git a/src/libthread/asm-Linux-386.s b/src/libthread/asm-Linux-386.s
deleted file mode 100644
index 75d965bf..00000000
--- a/src/libthread/asm-Linux-386.s
+++ /dev/null
@@ -1 +0,0 @@
-.include "asm-FreeBSD-386.s"
diff --git a/src/libthread/asm-Linux-power.s b/src/libthread/asm-Linux-power.s
deleted file mode 100644
index 00bfec3e..00000000
--- a/src/libthread/asm-Linux-power.s
+++ /dev/null
@@ -1,80 +0,0 @@
-/* get FPR and VR use flags with sc 0x7FF3 */
-/* get vsave with mfspr reg, 256 */
-
-.text
-.align 2
-
-.globl _setlabel
-
-_setlabel: /* xxx: instruction scheduling */
- mflr 0
- mfcr 5
- mfctr 6
- mfxer 7
- stw 0, 0*4(3)
- stw 5, 1*4(3)
- stw 6, 2*4(3)
- stw 7, 3*4(3)
-
- stw 1, 4*4(3)
- stw 2, 5*4(3)
-
- stw 13, (0+6)*4(3) /* callee-save GPRs */
- stw 14, (1+6)*4(3) /* xxx: block move */
- stw 15, (2+6)*4(3)
- stw 16, (3+6)*4(3)
- stw 17, (4+6)*4(3)
- stw 18, (5+6)*4(3)
- stw 19, (6+6)*4(3)
- stw 20, (7+6)*4(3)
- stw 21, (8+6)*4(3)
- stw 22, (9+6)*4(3)
- stw 23, (10+6)*4(3)
- stw 24, (11+6)*4(3)
- stw 25, (12+6)*4(3)
- stw 26, (13+6)*4(3)
- stw 27, (14+6)*4(3)
- stw 28, (15+6)*4(3)
- stw 29, (16+6)*4(3)
- stw 30, (17+6)*4(3)
- stw 31, (18+6)*4(3)
-
- li 3, 0 /* return */
- blr
-
-.globl _gotolabel
-
-_gotolabel:
- lwz 13, (0+6)*4(3) /* callee-save GPRs */
- lwz 14, (1+6)*4(3) /* xxx: block move */
- lwz 15, (2+6)*4(3)
- lwz 16, (3+6)*4(3)
- lwz 17, (4+6)*4(3)
- lwz 18, (5+6)*4(3)
- lwz 19, (6+6)*4(3)
- lwz 20, (7+6)*4(3)
- lwz 21, (8+6)*4(3)
- lwz 22, (9+6)*4(3)
- lwz 23, (10+6)*4(3)
- lwz 24, (11+6)*4(3)
- lwz 25, (12+6)*4(3)
- lwz 26, (13+6)*4(3)
- lwz 27, (14+6)*4(3)
- lwz 28, (15+6)*4(3)
- lwz 29, (16+6)*4(3)
- lwz 30, (17+6)*4(3)
- lwz 31, (18+6)*4(3)
-
- lwz 1, 4*4(3)
- lwz 2, 5*4(3)
-
- lwz 0, 0*4(3)
- mtlr 0
- lwz 0, 1*4(3)
- mtcr 0 /* mtcrf 0xFF, r0 */
- lwz 0, 2*4(3)
- mtctr 0
- lwz 0, 3*4(3)
- mtxer 0
- li 3, 1
- blr
diff --git a/src/libthread/asm-OpenBSD-386.s b/src/libthread/asm-OpenBSD-386.s
deleted file mode 100644
index 35e2ab6f..00000000
--- a/src/libthread/asm-OpenBSD-386.s
+++ /dev/null
@@ -1,49 +0,0 @@
-.globl _setlabel
-.type _setlabel,@function
-
-_setlabel:
- movl 4(%esp), %eax
- movl 0(%esp), %edx
- movl %edx, 0(%eax)
- movl %ebx, 4(%eax)
- movl %esp, 8(%eax)
- movl %ebp, 12(%eax)
- movl %esi, 16(%eax)
- movl %edi, 20(%eax)
- xorl %eax, %eax
- ret
-
-.globl _gotolabel
-.type _gotolabel,@function
-
-_gotolabel:
- movl 4(%esp), %edx
- movl 0(%edx), %ecx
- movl 4(%edx), %ebx
- movl 8(%edx), %esp
- movl 12(%edx), %ebp
- movl 16(%edx), %esi
- movl 20(%edx), %edi
- xorl %eax, %eax
- incl %eax
- movl %ecx, 0(%esp)
- ret
-
-
-# .globl _xinc
-# _xinc:
-# movl 4(%esp), %eax
-# lock incl 0(%eax)
-# ret
-#
-# .globl _xdec
-# _xdec:
-# movl 4(%esp), %eax
-# lock decl 0(%eax)
-# jz iszero
-# movl $1, %eax
-# ret
-# iszero:
-# movl $0, %eax
-# ret
-#
diff --git a/src/libthread/asm-SunOS-sun4u.s b/src/libthread/asm-SunOS-sun4u.s
deleted file mode 100644
index 3e95f02b..00000000
--- a/src/libthread/asm-SunOS-sun4u.s
+++ /dev/null
@@ -1,51 +0,0 @@
-.globl _setlabel
-.type _setlabel,#function
-
-_setlabel:
- ta 3
- st %i0, [%o0]
- st %i1, [%o0+4]
- st %i2, [%o0+8]
- st %i3, [%o0+12]
- st %i4, [%o0+16]
- st %i5, [%o0+20]
- st %i6, [%o0+24]
- st %i7, [%o0+28]
- st %l0, [%o0+32]
- st %l1, [%o0+36]
- st %l2, [%o0+40]
- st %l3, [%o0+44]
- st %l4, [%o0+48]
- st %l5, [%o0+52]
- st %l6, [%o0+56]
- st %l7, [%o0+60]
- st %sp, [%o0+64]
- st %o7, [%o0+68]
- jmpl %o7+8, %g0
- or %g0, %g0, %o0
-
-.globl _gotolabel
-.type _gotolabel,#function
-
-_gotolabel:
- ta 3
- ld [%o0], %i0
- ld [%o0+4], %i1
- ld [%o0+8], %i2
- ld [%o0+12], %i3
- ld [%o0+16], %i4
- ld [%o0+20], %i5
- ld [%o0+24], %i6
- ld [%o0+28], %i7
- ld [%o0+32], %l0
- ld [%o0+36], %l1
- ld [%o0+40], %l2
- ld [%o0+44], %l3
- ld [%o0+48], %l4
- ld [%o0+52], %l5
- ld [%o0+56], %l6
- ld [%o0+60], %l7
- ld [%o0+64], %sp
- ld [%o0+68], %o7
- jmpl %o7+8, %g0
- or %g0, 1, %o0
diff --git a/src/libthread/channel.c b/src/libthread/channel.c
deleted file mode 100644
index b488dc97..00000000
--- a/src/libthread/channel.c
+++ /dev/null
@@ -1,500 +0,0 @@
-#include "threadimpl.h"
-
-static Lock chanlock; /* central channel access lock */
-
-static void enqueue(Alt*, Thread*);
-static void dequeue(Alt*);
-static int altexec(Alt*);
-
-int _threadhighnentry;
-int _threadnalt;
-
-static void
-setuserpc(ulong pc)
-{
- Thread *t;
-
- t = _threadgetproc()->thread;
- if(t)
- t->userpc = pc;
-}
-
-static int
-canexec(Alt *a)
-{
- int i, otherop;
- Channel *c;
-
- c = a->c;
- /* are there senders or receivers blocked? */
- otherop = (CHANSND+CHANRCV) - a->op;
- for(i=0; i<c->nentry; i++)
- if(c->qentry[i] && c->qentry[i]->op==otherop && c->qentry[i]->thread->altc==nil){
- _threaddebug(DBGCHAN, "can rendez alt %p chan %p", a, c);
- return 1;
- }
-
- /* is there room in the channel? */
- if((a->op==CHANSND && c->n < c->s)
- || (a->op==CHANRCV && c->n > 0)){
- _threaddebug(DBGCHAN, "can buffer alt %p chan %p", a, c);
- return 1;
- }
-
- return 0;
-}
-
-static void
-_chanfree(Channel *c)
-{
- int i, inuse;
-
- inuse = 0;
- for(i = 0; i < c->nentry; i++)
- if(c->qentry[i])
- inuse = 1;
- if(inuse)
- c->freed = 1;
- else{
- if(c->qentry)
- free(c->qentry);
- free(c);
- }
-}
-
-void
-chanfree(Channel *c)
-{
- lock(&chanlock);
- _chanfree(c);
- unlock(&chanlock);
-}
-
-int
-chaninit(Channel *c, int elemsize, int elemcnt)
-{
- if(elemcnt < 0 || elemsize <= 0 || c == nil)
- return -1;
- memset(c, 0, sizeof *c);
- c->e = elemsize;
- c->s = elemcnt;
- _threaddebug(DBGCHAN, "chaninit %p", c);
- return 1;
-}
-
-Channel*
-chancreate(int elemsize, int elemcnt)
-{
- Channel *c;
-
- if(elemcnt < 0 || elemsize <= 0)
- return nil;
- c = _threadmalloc(sizeof(Channel)+elemsize*elemcnt, 1);
- c->e = elemsize;
- c->s = elemcnt;
- _threaddebug(DBGCHAN, "chancreate %p", c);
- return c;
-}
-
-static int
-_alt(Alt *alts)
-{
- Alt *a, *xa;
- Channel *c;
- int n;
- Thread *t;
-
- /*
- * The point of going splhi here is that note handlers
- * might reasonably want to use channel operations,
- * but that will hang if the note comes while we hold the
- * chanlock. Instead, we delay the note until we've dropped
- * the lock.
- */
-
- /*
- * T might be nil here -- the scheduler sends on threadwaitchan
- * directly (in non-blocking mode, of course!).
- */
- t = _threadgetproc()->thread;
- if((t && t->moribund) || _threadexitsallstatus)
- yield(); /* won't return */
- lock(&chanlock);
-
- /* test whether any channels can proceed */
- n = 0;
- a = nil;
-
- for(xa=alts; xa->op!=CHANEND && xa->op!=CHANNOBLK; xa++){
- xa->entryno = -1;
- if(xa->op == CHANNOP)
- continue;
-
- c = xa->c;
- if(c==nil){
- unlock(&chanlock);
- return -1;
- }
- if(canexec(xa))
- if(nrand(++n) == 0)
- a = xa;
- }
-
- if(a==nil){
- /* nothing can proceed */
- if(xa->op == CHANNOBLK){
- unlock(&chanlock);
- _threadnalt++;
- return xa - alts;
- }
-
- /* enqueue on all channels. */
- t->altc = nil;
- for(xa=alts; xa->op!=CHANEND; xa++){
- if(xa->op==CHANNOP)
- continue;
- enqueue(xa, t);
- }
-
- /*
- * wait for successful rendezvous.
- * we can't just give up if the rendezvous
- * is interrupted -- someone else might come
- * along and try to rendezvous with us, so
- * we need to be here.
- *
- * actually, now we're assuming no interrupts.
- */
- /*Again:*/
- t->alt = alts;
- t->chan = Chanalt;
- t->altrend.l = &chanlock;
- _threadsleep(&t->altrend);
-
- /* dequeue from channels, find selected one */
- a = nil;
- c = t->altc;
- for(xa=alts; xa->op!=CHANEND; xa++){
- if(xa->op==CHANNOP)
- continue;
- if(xa->c == c)
- a = xa;
- dequeue(xa);
- }
- unlock(&chanlock);
- if(a == nil){ /* we were interrupted */
- assert(c==(Channel*)~0);
- return -1;
- }
- }else{
- altexec(a); /* unlocks chanlock, does splx */
- }
- if(t)
- t->chan = Channone;
- return a - alts;
-}
-
-int
-alt(Alt *alts)
-{
- setuserpc(getcallerpc(&alts));
- return _alt(alts);
-}
-
-static int
-runop(int op, Channel *c, void *v, int nb)
-{
- int r;
- Alt a[2];
-
- /*
- * we could do this without calling alt,
- * but the only reason would be performance,
- * and i'm not convinced it matters.
- */
- a[0].op = op;
- a[0].c = c;
- a[0].v = v;
- a[1].op = CHANEND;
- if(nb)
- a[1].op = CHANNOBLK;
- switch(r=_alt(a)){
- case -1: /* interrupted */
- return -1;
- case 1: /* nonblocking, didn't accomplish anything */
- assert(nb);
- return 0;
- case 0:
- return 1;
- default:
- fprint(2, "ERROR: channel alt returned %d\n", r);
- abort();
- return -1;
- }
-}
-
-int
-recv(Channel *c, void *v)
-{
- setuserpc(getcallerpc(&c));
- return runop(CHANRCV, c, v, 0);
-}
-
-int
-nbrecv(Channel *c, void *v)
-{
- setuserpc(getcallerpc(&c));
- return runop(CHANRCV, c, v, 1);
-}
-
-int
-send(Channel *c, void *v)
-{
- setuserpc(getcallerpc(&c));
- return runop(CHANSND, c, v, 0);
-}
-
-int
-nbsend(Channel *c, void *v)
-{
- setuserpc(getcallerpc(&c));
- return runop(CHANSND, c, v, 1);
-}
-
-static void
-channelsize(Channel *c, int sz)
-{
- if(c->e != sz){
- fprint(2, "expected channel with elements of size %d, got size %d\n",
- sz, c->e);
- abort();
- }
-}
-
-int
-sendul(Channel *c, ulong v)
-{
- setuserpc(getcallerpc(&c));
- channelsize(c, sizeof(ulong));
- return send(c, &v);
-}
-
-ulong
-recvul(Channel *c)
-{
- ulong v;
-
- setuserpc(getcallerpc(&c));
- channelsize(c, sizeof(ulong));
- if(runop(CHANRCV, c, &v, 0) < 0)
- return ~0;
- return v;
-}
-
-int
-sendp(Channel *c, void *v)
-{
- setuserpc(getcallerpc(&c));
- channelsize(c, sizeof(void*));
- return runop(CHANSND, c, &v, 0);
-}
-
-void*
-recvp(Channel *c)
-{
- void *v;
-
- setuserpc(getcallerpc(&c));
- channelsize(c, sizeof(void*));
- if(runop(CHANRCV, c, &v, 0) < 0)
- return nil;
- return v;
-}
-
-int
-nbsendul(Channel *c, ulong v)
-{
- setuserpc(getcallerpc(&c));
- channelsize(c, sizeof(ulong));
- return runop(CHANSND, c, &v, 1);
-}
-
-ulong
-nbrecvul(Channel *c)
-{
- ulong v;
-
- setuserpc(getcallerpc(&c));
- channelsize(c, sizeof(ulong));
- if(runop(CHANRCV, c, &v, 1) == 0)
- return 0;
- return v;
-}
-
-int
-nbsendp(Channel *c, void *v)
-{
- setuserpc(getcallerpc(&c));
- channelsize(c, sizeof(void*));
- return runop(CHANSND, c, &v, 1);
-}
-
-void*
-nbrecvp(Channel *c)
-{
- void *v;
-
- setuserpc(getcallerpc(&c));
- channelsize(c, sizeof(void*));
- if(runop(CHANRCV, c, &v, 1) == 0)
- return nil;
- return v;
-}
-
-static int
-emptyentry(Channel *c)
-{
- int i, extra;
-
- assert((c->nentry==0 && c->qentry==nil) || (c->nentry && c->qentry));
-
- for(i=0; i<c->nentry; i++)
- if(c->qentry[i]==nil)
- return i;
-
- extra = 16;
- c->nentry += extra;
-if(c->nentry > _threadhighnentry) _threadhighnentry = c->nentry;
- c->qentry = realloc((void*)c->qentry, c->nentry*sizeof(c->qentry[0]));
- if(c->qentry == nil)
- sysfatal("realloc channel entries: %r");
- _threadmemset(&c->qentry[i], 0, extra*sizeof(c->qentry[0]));
- return i;
-}
-
-static void
-enqueue(Alt *a, Thread *t)
-{
- int i;
-
- _threaddebug(DBGCHAN, "Queueing alt %p on channel %p", a, a->c);
- a->thread = t;
- i = emptyentry(a->c);
- a->c->qentry[i] = a;
-}
-
-static void
-dequeue(Alt *a)
-{
- int i;
- Channel *c;
-
- c = a->c;
- for(i=0; i<c->nentry; i++)
- if(c->qentry[i]==a){
- _threaddebug(DBGCHAN, "Dequeuing alt %p from channel %p", a, a->c);
- c->qentry[i] = nil;
- if(c->freed)
- _chanfree(c);
- return;
- }
-}
-
-static void*
-altexecbuffered(Alt *a, int willreplace)
-{
- uchar *v;
- Channel *c;
-
- c = a->c;
- /* use buffered channel queue */
- if(a->op==CHANRCV && c->n > 0){
- _threaddebug(DBGCHAN, "buffer recv alt %p chan %p", a, c);
- v = c->v + c->e*(c->f%c->s);
- if(!willreplace)
- c->n--;
- c->f++;
- return v;
- }
- if(a->op==CHANSND && c->n < c->s){
- _threaddebug(DBGCHAN, "buffer send alt %p chan %p", a, c);
- v = c->v + c->e*((c->f+c->n)%c->s);
- if(!willreplace)
- c->n++;
- return v;
- }
- abort();
- return nil;
-}
-
-static void
-altcopy(void *dst, void *src, int sz)
-{
- if(dst){
- if(src)
- memmove(dst, src, sz);
- else
- _threadmemset(dst, 0, sz);
- }
-}
-
-static int
-altexec(Alt *a)
-{
- volatile Alt *b;
- int i, n, otherop;
- Channel *c;
- void *me, *waiter, *buf;
-
- c = a->c;
-
- /* rendezvous with others */
- otherop = (CHANSND+CHANRCV) - a->op;
- n = 0;
- b = nil;
- me = a->v;
- for(i=0; i<c->nentry; i++)
- if(c->qentry[i] && c->qentry[i]->op==otherop && c->qentry[i]->thread->altc==nil)
- if(nrand(++n) == 0)
- b = c->qentry[i];
- if(b != nil){
- _threaddebug(DBGCHAN, "rendez %s alt %p chan %p alt %p", a->op==CHANRCV?"recv":"send", a, c, b);
- waiter = b->v;
- if(c->s && c->n){
- /*
- * if buffer is full and there are waiters
- * and we're meeting a waiter,
- * we must be receiving.
- *
- * we use the value in the channel buffer,
- * copy the waiter's value into the channel buffer
- * on behalf of the waiter, and then wake the waiter.
- */
- if(a->op!=CHANRCV)
- abort();
- buf = altexecbuffered(a, 1);
- altcopy(me, buf, c->e);
- altcopy(buf, waiter, c->e);
- }else{
- if(a->op==CHANRCV)
- altcopy(me, waiter, c->e);
- else
- altcopy(waiter, me, c->e);
- }
- b->thread->altc = c;
- _threadwakeup(&b->thread->altrend);
- _threaddebug(DBGCHAN, "chanlock is %lud", *(ulong*)(void*)&chanlock);
- _threaddebug(DBGCHAN, "unlocking the chanlock");
- unlock(&chanlock);
- return 1;
- }
-
- buf = altexecbuffered(a, 0);
- if(a->op==CHANRCV)
- altcopy(me, buf, c->e);
- else
- altcopy(buf, me, c->e);
-
- unlock(&chanlock);
- return 1;
-}
diff --git a/src/libthread/chanprint.c b/src/libthread/chanprint.c
deleted file mode 100644
index 781c6f6f..00000000
--- a/src/libthread/chanprint.c
+++ /dev/null
@@ -1,20 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <thread.h>
-
-int
-chanprint(Channel *c, char *fmt, ...)
-{
- va_list arg;
- char *p;
- int n;
-
- va_start(arg, fmt);
- p = vsmprint(fmt, arg);
- va_end(arg);
- if(p == nil)
- sysfatal("vsmprint failed: %r");
- n = sendp(c, p);
- yield(); /* let recipient handle message immediately */
- return n;
-}
diff --git a/src/libthread/create.c b/src/libthread/create.c
deleted file mode 100644
index 4e6bc6de..00000000
--- a/src/libthread/create.c
+++ /dev/null
@@ -1,211 +0,0 @@
-#include "threadimpl.h"
-
-Pqueue _threadpq; /* list of all procs */
-int _threadnprocs; /* count of procs */
-
-static int newthreadid(void);
-static int newprocid(void);
-
-/*
- * Create and initialize a new Thread structure attached to a given proc.
- */
-int
-_newthread(Proc *p, void (*f)(void *arg), void *arg, uint stacksize,
- char *name, int grp)
-{
- int id;
- Thread *t;
-
- t = _threadmalloc(sizeof(Thread), 1);
- t->proc = p;
- t->nextproc = p;
- t->homeproc = p;
-
- t->grp = grp;
- t->id = id = newthreadid();
- if(name)
- t->name = strdup(name);
- _threaddebug(DBGSCHED, "create thread %d.%d name %s", p->id, id, name);
-
- /*
- * Allocate and clear stack.
- */
- if(stacksize < 1024)
- sysfatal("bad stacksize %d", stacksize);
- t->stk = _threadmalloc(stacksize, 0);
- t->stksize = stacksize;
- _threaddebugmemset(t->stk, 0xFE, stacksize);
-
- /*
- * Set up t->context to call f(arg).
- */
- _threadinitstack(t, f, arg);
-
- /*
- * Add thread to proc.
- */
- lock(&p->lock);
- _procaddthread(p, t);
-
- /*
- * Mark thread as ready to run.
- */
- t->state = Ready;
- _threadready(t);
- unlock(&p->lock);
-
- return id;
-}
-
-/*
- * Free a Thread structure.
- */
-void
-_threadfree(Thread *t)
-{
- free(t->stk);
- free(t->name);
- free(t);
-}
-
-/*
- * Create and initialize a new Proc structure with a single Thread
- * running inside it. Add the Proc to the global process list.
- */
-Proc*
-_newproc(void)
-{
- Proc *p;
-
- /*
- * Allocate.
- */
- p = _threadmalloc(sizeof *p, 1);
- p->id = newprocid();
-
- /*
- * Add to list. Record if we're now multiprocess.
- */
- lock(&_threadpq.lock);
- if(_threadpq.head == nil)
- _threadpq.head = p;
- else
- *_threadpq.tail = p;
- _threadpq.tail = &p->next;
- if(_threadnprocs == 1)
- _threadmultiproc();
- _threadnprocs++;
- unlock(&_threadpq.lock);
-
- return p;
-}
-
-/*
- * Allocate a new thread running f(arg) on a stack of size stacksize.
- * Return the thread id. The thread group inherits from the current thread.
- */
-int
-threadcreate(void (*f)(void*), void *arg, uint stacksize)
-{
- return _newthread(_threadgetproc(), f, arg, stacksize, nil, threadgetgrp());
-}
-
-/*
- * Allocate a new idle thread. Only allowed in a single-proc program.
- */
-int
-threadcreateidle(void (*f)(void *arg), void *arg, uint stacksize)
-{
- int id;
-
- assert(_threadpq.head->next == nil); /* only 1 */
-
- id = threadcreate(f, arg, stacksize);
- _threaddebug(DBGSCHED, "idle is %d", id);
- _threadsetidle(id);
- return id;
-}
-
-/*
- * Threadcreate, but do it inside a fresh proc.
- */
-int
-proccreate(void (*f)(void*), void *arg, uint stacksize)
-{
- int id;
- Proc *p, *np;
-
- p = _threadgetproc();
- np = _newproc();
- p->newproc = np;
- p->schedfn = _kthreadstartproc;
- id = _newthread(np, f, arg, stacksize, nil, p->thread->grp);
- _sched(); /* call into scheduler to create proc XXX */
- return id;
-}
-
-/*
- * Allocate a new thread id.
- */
-static int
-newthreadid(void)
-{
- static Lock l;
- static int id;
- int i;
-
- lock(&l);
- i = ++id;
- unlock(&l);
- return i;
-}
-
-/*
- * Allocate a new proc id.
- */
-static int
-newprocid(void)
-{
- static Lock l;
- static int id;
- int i;
-
- lock(&l);
- i = ++id;
- unlock(&l);
- return i;
-}
-
-/*
- * Add thread to proc's list.
- */
-void
-_procaddthread(Proc *p, Thread *t)
-{
- p->nthreads++;
- if(p->threads.head == nil)
- p->threads.head = t;
- else{
- t->prevt = p->threads.tail;
- t->prevt->nextt = t;
- }
- p->threads.tail = t;
- t->next = (Thread*)~0;
-}
-
-/*
- * Remove thread from proc's list.
- */
-void
-_procdelthread(Proc *p, Thread *t)
-{
- if(t->prevt)
- t->prevt->nextt = t->nextt;
- else
- p->threads.head = t->nextt;
- if(t->nextt)
- t->nextt->prevt = t->prevt;
- else
- p->threads.tail = t->prevt;
- p->nthreads--;
-}
diff --git a/src/libthread/debug.c b/src/libthread/debug.c
deleted file mode 100644
index 14b47c00..00000000
--- a/src/libthread/debug.c
+++ /dev/null
@@ -1,48 +0,0 @@
-#include "threadimpl.h"
-
-int _threaddebuglevel;
-
-void
-__threaddebug(ulong flag, char *fmt, ...)
-{
- char buf[128];
- va_list arg;
- Fmt f;
- Proc *p;
-
- if((_threaddebuglevel&flag) == 0)
- return;
-
- fmtfdinit(&f, 2, buf, sizeof buf);
-
- p = _threadgetproc();
- if(p==nil)
- fmtprint(&f, "noproc ");
- else if(p->thread)
- fmtprint(&f, "%d.%d ", p->id, p->thread->id);
- else
- fmtprint(&f, "%d._ ", p->id);
-
- va_start(arg, fmt);
- fmtvprint(&f, fmt, arg);
- va_end(arg);
- fmtprint(&f, "\n");
- fmtfdflush(&f);
-}
-
-void
-_threadassert(char *s)
-{
- char buf[256];
- int n;
- Proc *p;
-
- p = _threadgetproc();
- if(p && p->thread)
- n = sprint(buf, "%d.%d ", p->pid, p->thread->id);
- else
- n = 0;
- snprint(buf+n, sizeof(buf)-n, "%s: assertion failed\n", s);
- write(2, buf, strlen(buf));
- abort();
-}
diff --git a/src/libthread/exec-unix.c b/src/libthread/exec-unix.c
deleted file mode 100644
index e5848eaa..00000000
--- a/src/libthread/exec-unix.c
+++ /dev/null
@@ -1,147 +0,0 @@
-#include <u.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include "threadimpl.h"
-
-static void efork(int[3], int[2], char*, char**);
-int
-_threadexec(Channel *pidc, int fd[3], char *prog, char *args[], int freeargs)
-{
- int pfd[2];
- int n, pid;
- char exitstr[ERRMAX];
-
- _threaddebug(DBGEXEC, "threadexec %s", prog);
-
- /*
- * We want threadexec to behave like exec; if exec succeeds,
- * never return, and if it fails, return with errstr set.
- * Unfortunately, the exec happens in another proc since
- * we have to wait for the exec'ed process to finish.
- * To provide the semantics, we open a pipe with the
- * write end close-on-exec and hand it to the proc that
- * is doing the exec. If the exec succeeds, the pipe will
- * close so that our read below fails. If the exec fails,
- * then the proc doing the exec sends the errstr down the
- * pipe to us.
- */
- if(pipe(pfd) < 0)
- goto Bad;
- if(fcntl(pfd[0], F_SETFD, 1) < 0)
- goto Bad;
- if(fcntl(pfd[1], F_SETFD, 1) < 0)
- goto Bad;
-
- switch(pid = fork()){
- case -1:
- close(pfd[0]);
- close(pfd[1]);
- goto Bad;
- case 0:
- efork(fd, pfd, prog, args);
- _threaddebug(DBGSCHED, "exit after efork");
- _exit(0);
- default:
- if(freeargs)
- free(args);
- break;
- }
-
- close(pfd[1]);
- if((n = read(pfd[0], exitstr, ERRMAX-1)) > 0){ /* exec failed */
- exitstr[n] = '\0';
- errstr(exitstr, ERRMAX);
- close(pfd[0]);
- goto Bad;
- }
- close(pfd[0]);
- close(fd[0]);
- if(fd[1] != fd[0])
- close(fd[1]);
- if(fd[2] != fd[1] && fd[2] != fd[0])
- close(fd[2]);
- if(pidc)
- sendul(pidc, pid);
-
- _threaddebug(DBGEXEC, "threadexec schedexecwait");
- return pid;
-
-Bad:
- _threaddebug(DBGEXEC, "threadexec bad %r");
- if(pidc)
- sendul(pidc, ~0);
- return -1;
-}
-
-void
-threadexec(Channel *pidc, int fd[3], char *prog, char *args[])
-{
- if(_kthreadexec(pidc, fd, prog, args, 0) >= 0)
- threadexits(nil);
-}
-
-int
-threadspawn(int fd[3], char *prog, char *args[])
-{
- return _kthreadexec(nil, fd, prog, args, 0);
-}
-
-/*
- * The &f+1 trick doesn't work on SunOS, so we might
- * as well bite the bullet and do this correctly.
- */
-void
-threadexecl(Channel *pidc, int fd[3], char *f, ...)
-{
- char **args, *s;
- int n;
- va_list arg;
-
- va_start(arg, f);
- for(n=0; va_arg(arg, char*) != 0; n++)
- ;
- n++;
- va_end(arg);
-
- args = malloc(n*sizeof(args[0]));
- if(args == nil){
- if(pidc)
- sendul(pidc, ~0);
- return;
- }
-
- va_start(arg, f);
- for(n=0; (s=va_arg(arg, char*)) != 0; n++)
- args[n] = s;
- args[n] = 0;
- va_end(arg);
-
- if(_kthreadexec(pidc, fd, f, args, 1) >= 0)
- threadexits(nil);
-}
-
-static void
-efork(int stdfd[3], int fd[2], char *prog, char **args)
-{
- char buf[ERRMAX];
- int i;
-
- _threaddebug(DBGEXEC, "_schedexec %s -- calling execv", prog);
- dup(stdfd[0], 0);
- dup(stdfd[1], 1);
- dup(stdfd[2], 2);
- for(i=3; i<40; i++)
- if(i != fd[1])
- close(i);
- rfork(RFNOTEG);
- execvp(prog, args);
- _threaddebug(DBGEXEC, "_schedexec failed: %r");
- rerrstr(buf, sizeof buf);
- if(buf[0]=='\0')
- strcpy(buf, "exec failed");
- write(fd[1], buf, strlen(buf));
- close(fd[1]);
- _threaddebug(DBGSCHED, "_exits in exec-unix");
- _exits(buf);
-}
-
diff --git a/src/libthread/exec.c b/src/libthread/exec.c
new file mode 100644
index 00000000..2cbb4437
--- /dev/null
+++ b/src/libthread/exec.c
@@ -0,0 +1,153 @@
+#include "u.h"
+#include <errno.h>
+#include "libc.h"
+#include "thread.h"
+#include "threadimpl.h"
+
+static Lock thewaitlock;
+static Channel *thewaitchan;
+static Channel *dowaitchan;
+
+/* BUG - start waitproc on first exec, not when threadwaitchan is called */
+static void
+waitproc(void *v)
+{
+ Channel *c;
+ Waitmsg *w;
+
+ _threadsetsysproc();
+ for(;;){
+ while((w = wait()) == nil){
+ if(errno == ECHILD)
+ recvul(dowaitchan);
+ }
+ if((c = thewaitchan) != nil)
+ sendp(c, w);
+ else
+ free(w);
+ }
+}
+
+Channel*
+threadwaitchan(void)
+{
+ if(thewaitchan)
+ return thewaitchan;
+ lock(&thewaitlock);
+ if(thewaitchan){
+ unlock(&thewaitlock);
+ return thewaitchan;
+ }
+ thewaitchan = chancreate(sizeof(Waitmsg*), 4);
+ chansetname(thewaitchan, "threadwaitchan");
+ dowaitchan = chancreate(sizeof(ulong), 1);
+ chansetname(dowaitchan, "dowaitchan");
+ proccreate(waitproc, nil, STACK);
+ unlock(&thewaitlock);
+ return thewaitchan;
+}
+
+int
+threadspawn(int fd[3], char *cmd, char *argv[])
+{
+ int i, n, p[2], pid;
+ char exitstr[100];
+
+ if(pipe(p) < 0)
+ return -1;
+ if(fcntl(p[0], F_SETFD, 1) < 0 || fcntl(p[1], F_SETFD, 1) < 0){
+ close(p[0]);
+ close(p[1]);
+ return -1;
+ }
+ switch(pid = fork()){
+ case -1:
+ close(p[0]);
+ close(p[1]);
+ return -1;
+ case 0:
+ dup2(fd[0], 0);
+ dup2(fd[1], 1);
+ dup2(fd[2], 2);
+ for(i=3; i<100; i++)
+ if(i != p[1])
+ close(i);
+ execvp(cmd, argv);
+ fprint(p[1], "%d", errno);
+ close(p[1]);
+ _exit(0);
+ }
+
+ close(p[1]);
+ n = read(p[0], exitstr, sizeof exitstr-1);
+ close(p[0]);
+ if(n > 0){ /* exec failed */
+ exitstr[n] = 0;
+ errno = atoi(exitstr);
+ return -1;
+ }
+
+ close(fd[0]);
+ if(fd[1] != fd[0])
+ close(fd[1]);
+ if(fd[2] != fd[1] && fd[2] != fd[0])
+ close(fd[2]);
+ channbsendul(dowaitchan, 1);
+ return pid;
+}
+
+int
+_threadexec(Channel *cpid, int fd[3], char *cmd, char *argv[])
+{
+ int pid;
+
+ pid = threadspawn(fd, cmd, argv);
+ if(cpid){
+ if(pid < 0)
+ chansendul(cpid, ~0);
+ else
+ chansendul(cpid, pid);
+ }
+ return pid;
+}
+
+void
+threadexec(Channel *cpid, int fd[3], char *cmd, char *argv[])
+{
+ if(_threadexec(cpid, fd, cmd, argv) >= 0)
+ threadexits("threadexec");
+}
+
+void
+threadexecl(Channel *cpid, int fd[3], char *cmd, ...)
+{
+ char **argv, *s;
+ int n, pid;
+ va_list arg;
+
+ va_start(arg, cmd);
+ for(n=0; va_arg(arg, char*) != nil; n++)
+ ;
+ n++;
+ va_end(arg);
+
+ argv = malloc(n*sizeof(argv[0]));
+ if(argv == nil){
+ if(cpid)
+ chansendul(cpid, ~0);
+ return;
+ }
+
+ va_start(arg, cmd);
+ for(n=0; (s=va_arg(arg, char*)) != nil; n++)
+ argv[n] = s;
+ argv[n] = 0;
+ va_end(arg);
+
+ pid = _threadexec(cpid, fd, cmd, argv);
+ free(argv);
+
+ if(pid >= 0)
+ threadexits("threadexecl");
+}
+
diff --git a/src/libthread/execproc.ch b/src/libthread/execproc.ch
deleted file mode 100644
index 4382be40..00000000
--- a/src/libthread/execproc.ch
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * Set up a dedicated proc to handle calls to exec.
- * The proc also waits for child messages.
- * This way, each proc scheduler need not worry
- * about calling wait in its main loop.
- *
- * To be included from other files (e.g., Linux-clone.c).
- */
-
-typedef struct Xarg Xarg;
-struct Xarg
-{
- Channel *pidc;
- int fd[3];
- char *prog;
- char **args;
- int freeargs;
- Channel *ret;
- int errn;
- char errstr[ERRMAX];
-};
-
-static Proc *_threadexecproc;
-static Channel *_threadexecchan;
-static Lock threadexeclock;
-
-/*
- * Called to poll for any kids of this pthread.
- * We have a separate proc responsible for exec,
- * so this is a no-op.
- */
-void
-_threadwaitkids(Proc *p)
-{
-}
-
-#define WAITSIG SIGCHLD
-
-/*
- * Separate process to wait for child messages.
- * Also runs signal handlers and runs all execs.
- */
-static void
-nop(int sig)
-{
- USED(sig);
-}
-
-static void
-_threadwaitproc(void *v)
-{
- Channel *c;
- Waitmsg *w;
- sigset_t mask;
- int ret, nkids;
- Xarg *xa;
-
- nkids = 0;
-
- sigemptyset(&mask);
- siginterrupt(WAITSIG, 1);
- signal(WAITSIG, nop);
- sigaddset(&mask, WAITSIG);
- sigprocmask(SIG_BLOCK, &mask, nil);
- USED(v);
- for(;;){
- while((nkids > 0 ? nbrecv : recv)(_threadexecchan, &xa) == 1){
- ret = _threadexec(xa->pidc, xa->fd, xa->prog, xa->args, xa->freeargs);
- if(ret > 0)
- nkids++;
- else{
- rerrstr(xa->errstr, sizeof xa->errstr);
- xa->errn = errno;
- }
- sendul(xa->ret, ret);
- }
- if(nkids > 0){
- sigprocmask(SIG_UNBLOCK, &mask, nil);
- w = wait();
- sigprocmask(SIG_BLOCK, &mask, nil);
- if(w == nil && errno == ECHILD){
- fprint(2, "wait returned ECHILD but nkids=%d; reset\n", nkids);
- nkids = 0;
- }
- if(w){
- nkids--;
- if((c = _threadwaitchan) != nil)
- sendp(c, w);
- else
- free(w);
- }
- }
- }
-}
-
-static void _kickexecproc(void);
-
-int
-_callthreadexec(Channel *pidc, int fd[3], char *prog, char *args[], int freeargs)
-{
- int ret;
- Xarg xa;
-
- if(_threadexecchan == nil){
- lock(&threadexeclock);
- if(_threadexecchan == nil)
- _threadfirstexec();
- unlock(&threadexeclock);
- }
-
- xa.pidc = pidc;
- xa.fd[0] = fd[0];
- xa.fd[1] = fd[1];
- xa.fd[2] = fd[2];
- xa.prog = prog;
- xa.args = args;
- xa.freeargs = freeargs;
- xa.ret = chancreate(sizeof(ulong), 1);
- sendp(_threadexecchan, &xa);
- _kickexecproc();
- ret = recvul(xa.ret);
- if(ret < 0){
- werrstr("%s", xa.errstr);
- errno = xa.errn;
- }
- chanfree(xa.ret);
- return ret;
-}
-
-/*
- * Called before the first exec.
- */
-void
-_threadfirstexec(void)
-{
- int id;
- Proc *p;
-
- _threadexecchan = chancreate(sizeof(Xarg*), 1);
- id = proccreate(_threadwaitproc, nil, 32*1024);
-
- /*
- * Sleazy: decrement threadnprocs so that
- * the existence of the _threadwaitproc proc
- * doesn't keep us from exiting.
- */
- lock(&_threadpq.lock);
- --_threadnprocs;
- for(p=_threadpq.head; p; p=p->next)
- if(p->threads.head && p->threads.head->id == id)
- break;
- if(p == nil)
- sysfatal("cannot find exec proc");
- unlock(&_threadpq.lock);
- _threadexecproc = p;
-}
-
-/*
- * Called after the thread t has been rescheduled.
- * Kick the exec proc in case it is in the middle of a wait.
- */
-static void
-_kickexecproc(void)
-{
- kill(_threadexecproc->pid, WAITSIG);
-}
-
-/*
- * Called before exec.
- */
-void
-_threadbeforeexec(void)
-{
-}
-
-/*
- * Called after exec.
- */
-void
-_threadafterexec(void)
-{
-}
-
diff --git a/src/libthread/exit-getpid.ch b/src/libthread/exit-getpid.ch
deleted file mode 100644
index e2580ac7..00000000
--- a/src/libthread/exit-getpid.ch
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Implement threadexitsall by sending a signal to every proc.
- *
- * To be included from another C file (e.g., Linux-clone.c).
- */
-
-void
-_threadexitallproc(char *exitstr)
-{
- Proc *p;
- int mypid;
-
- mypid = getpid();
- lock(&_threadpq.lock);
- for(p=_threadpq.head; p; p=p->next)
- if(p->pid > 1 && p->pid != mypid)
- kill(p->pid, SIGUSR2);
- exits(exitstr);
-}
-
-void
-_threadexitproc(char *exitstr)
-{
- _exits(exitstr);
-}
diff --git a/src/libthread/exit.c b/src/libthread/exit.c
deleted file mode 100644
index 69f3f738..00000000
--- a/src/libthread/exit.c
+++ /dev/null
@@ -1,44 +0,0 @@
-#include <u.h>
-#include <signal.h>
-#include "threadimpl.h"
-
-char *_threadexitsallstatus;
-Channel *_threadwaitchan;
-
-void
-threadexits(char *exitstr)
-{
- Proc *p;
- Thread *t;
-
- p = _threadgetproc();
- t = p->thread;
- if(t == p->idle)
- p->idle = nil;
- t->moribund = 1;
- _threaddebug(DBGSCHED, "threadexits %s", exitstr);
- if(exitstr==nil)
- exitstr="";
- utfecpy(p->exitstr, p->exitstr+ERRMAX, exitstr);
- _sched();
-}
-
-void
-threadexitsall(char *exitstr)
-{
- _threaddebug(DBGSCHED, "threadexitsall %s", exitstr);
- if(exitstr == nil)
- exitstr = "";
- _threadexitsallstatus = exitstr;
- _threaddebug(DBGSCHED, "_threadexitsallstatus set to %p", _threadexitsallstatus);
- /* leave */
- _kthreadexitallproc(exitstr);
-}
-
-Channel*
-threadwaitchan(void)
-{
- if(_threadwaitchan==nil)
- _threadwaitchan = chancreate(sizeof(Waitmsg*), 16);
- return _threadwaitchan;
-}
diff --git a/src/libthread/fdwait.c b/src/libthread/fdwait.c
deleted file mode 100644
index d3983419..00000000
--- a/src/libthread/fdwait.c
+++ /dev/null
@@ -1,241 +0,0 @@
-#define NOPLAN9DEFINES
-#include <u.h>
-#include <libc.h>
-#include <thread.h>
-#include "threadimpl.h"
-#include <errno.h>
-#include <unistd.h>
-#include <fcntl.h>
-
-void
-fdwait()
-{
- fd_set rfd, wfd, efd;
-
- FD_ZERO(&rfd);
- FD_ZERO(&wfd);
- FD_ZERO(&efd);
- if(mode=='w')
- FD_SET(&wfd, fd);
- else
- FD_SET(&rfd, fd);
- FD_SET(&efd, fd);
- select(fd+1, &rfd, &wfd, &efd, nil);
-}
-
-void
-threadfdwaitsetup(void)
-{
-}
-
-void
-_threadfdwait(int fd, int rw, ulong pc)
-{
- int i;
-
- struct {
- Channel c;
- ulong x;
- Alt *qentry[2];
- } s;
-
- threadfdwaitsetup();
- chaninit(&s.c, sizeof(ulong), 1);
- s.c.qentry = (volatile Alt**)s.qentry;
- s.c.nentry = 2;
- memset(s.qentry, 0, sizeof s.qentry);
- for(i=0; i<npoll; i++)
- if(pfd[i].fd == -1)
- break;
- if(i==npoll){
- if(npoll >= nelem(polls)){
- fprint(2, "Too many polled fds.\n");
- abort();
- }
- npoll++;
- }
-
- pfd[i].fd = fd;
- pfd[i].events = rw=='r' ? POLLIN : POLLOUT;
- polls[i].c = &s.c;
- if(0) fprint(2, "%s [%3d] fdwait %d %c list *0x%lux\n",
- argv0, threadid(), fd, rw, pc);
- if(pollpid)
- postnote(PNPROC, pollpid, "interrupt");
- recvul(&s.c);
-}
-
-void
-threadfdwait(int fd, int rw)
-{
- _threadfdwait(fd, rw, getcallerpc(&fd));
-}
-
-void
-threadsleep(int ms)
-{
- struct {
- Channel c;
- ulong x;
- Alt *qentry[2];
- } s;
-
- threadfdwaitsetup();
- chaninit(&s.c, sizeof(ulong), 1);
- s.c.qentry = (volatile Alt**)s.qentry;
- s.c.nentry = 2;
- memset(s.qentry, 0, sizeof s.qentry);
-
- sleepchan[nsleep] = &s.c;
- sleeptime[nsleep++] = p9nsec()/1000000+ms;
- recvul(&s.c);
-}
-
-void
-threadfdnoblock(int fd)
-{
- fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0)|O_NONBLOCK);
-}
-
-long
-threadread(int fd, void *a, long n)
-{
- int nn;
-
- threadfdnoblock(fd);
-again:
- /*
- * Always call wait (i.e. don't optimistically try the read)
- * so that the scheduler gets a chance to run other threads.
- */
- _threadfdwait(fd, 'r', getcallerpc(&fd));
- errno = 0;
- nn = read(fd, a, n);
- if(nn <= 0){
- if(errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)
- goto again;
- }
- return nn;
-}
-
-int
-threadrecvfd(int fd)
-{
- int nn;
-
- threadfdnoblock(fd);
-again:
- /*
- * Always call wait (i.e. don't optimistically try the recvfd)
- * so that the scheduler gets a chance to run other threads.
- */
- _threadfdwait(fd, 'r', getcallerpc(&fd));
- nn = recvfd(fd);
- if(nn < 0){
- if(errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)
- goto again;
- }
- return nn;
-}
-
-int
-threadsendfd(int fd, int sfd)
-{
- int nn;
-
- threadfdnoblock(fd);
-again:
- /*
- * Always call wait (i.e. don't optimistically try the sendfd)
- * so that the scheduler gets a chance to run other threads.
- */
- _threadfdwait(fd, 'w', getcallerpc(&fd));
- nn = sendfd(fd, sfd);
- if(nn < 0){
- if(errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)
- goto again;
- }
- return nn;
-}
-
-long
-threadreadn(int fd, void *a, long n)
-{
- int tot, nn;
-
- for(tot = 0; tot<n; tot+=nn){
- nn = threadread(fd, (char*)a+tot, n-tot);
- if(nn <= 0){
- if(tot == 0)
- return nn;
- return tot;
- }
- }
- return tot;
-}
-
-long
-_threadwrite(int fd, const void *a, long n)
-{
- int nn;
-
- threadfdnoblock(fd);
-again:
- /*
- * Always call wait (i.e. don't optimistically try the write)
- * so that the scheduler gets a chance to run other threads.
- */
- _threadfdwait(fd, 'w', getcallerpc(&fd));
- nn = write(fd, a, n);
- if(nn < 0){
- if(errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)
- goto again;
- }
- return nn;
-}
-
-long
-threadwrite(int fd, const void *a, long n)
-{
- int tot, nn;
-
- for(tot = 0; tot<n; tot+=nn){
- nn = _threadwrite(fd, (char*)a+tot, n-tot);
- if(nn <= 0){
- if(tot == 0)
- return nn;
- return tot;
- }
- }
- return tot;
-}
-
-int
-threadannounce(char *addr, char *dir)
-{
- return p9announce(addr, dir);
-}
-
-int
-threadlisten(char *dir, char *newdir)
-{
- int fd, ret;
- extern int _p9netfd(char*);
-
- fd = _p9netfd(dir);
- if(fd < 0){
- werrstr("bad 'directory' in listen: %s", dir);
- return -1;
- }
- threadfdnoblock(fd);
- while((ret = p9listen(dir, newdir)) < 0 && errno==EAGAIN)
- _threadfdwait(fd, 'r', getcallerpc(&dir));
- return ret;
-}
-
-int
-threadaccept(int cfd, char *dir)
-{
- return p9accept(cfd, dir);
-}
-
diff --git a/src/libthread/getpid.c b/src/libthread/getpid.c
deleted file mode 100644
index c4d23dad..00000000
--- a/src/libthread/getpid.c
+++ /dev/null
@@ -1,7 +0,0 @@
-#include "threadimpl.h"
-extern int getfforkid(void);
-int
-_threadgetpid(void)
-{
- return getfforkid();
-}
diff --git a/src/libthread/id.c b/src/libthread/id.c
deleted file mode 100644
index c2aa03d0..00000000
--- a/src/libthread/id.c
+++ /dev/null
@@ -1,136 +0,0 @@
-#include "threadimpl.h"
-
-int
-threadid(void)
-{
- return _threadgetproc()->thread->id;
-}
-
-int
-threadpid(int id)
-{
- int pid;
- Proc *p;
- Thread *t;
-
- if (id < 0)
- return -1;
- if (id == 0)
- return _threadgetproc()->pid;
- lock(&_threadpq.lock);
- for (p = _threadpq.head; p->next; p = p->next){
- lock(&p->lock);
- for (t = p->threads.head; t; t = t->nextt)
- if (t->id == id){
- pid = p->pid;
- unlock(&p->lock);
- unlock(&_threadpq.lock);
- return pid;
- }
- unlock(&p->lock);
- }
- unlock(&_threadpq.lock);
- return -1;
-}
-
-int
-threadsetgrp(int ng)
-{
- int og;
- Thread *t;
-
- t = _threadgetproc()->thread;
- og = t->grp;
- t->grp = ng;
- return og;
-}
-
-int
-threadgetgrp(void)
-{
- return _threadgetproc()->thread->grp;
-}
-
-void
-threadsetname(char *fmt, ...)
-{
- Proc *p;
- Thread *t;
- va_list arg;
-
- p = _threadgetproc();
- t = p->thread;
- if(t->name)
- free(t->name);
- va_start(arg, fmt);
- t->name = vsmprint(fmt, arg);
- va_end(arg);
-
- _threaddebug(DBGSCHED, "set name %s", t->name);
-/* Plan 9 only
- if(p->nthreads == 1){
- snprint(buf, sizeof buf, "#p/%d/args", getpid());
- if((fd = open(buf, OWRITE)) >= 0){
- snprint(buf, sizeof buf, "%s [%s]", argv0, name);
- n = strlen(buf)+1;
- s = strchr(buf, ' ');
- if(s)
- *s = '\0';
- write(fd, buf, n);
- close(fd);
- }
- }
-*/
-}
-
-char*
-threadgetname(void)
-{
- return _threadgetproc()->thread->name;
-}
-
-void**
-threaddata(void)
-{
- return &_threadgetproc()->thread->udata[0];
-}
-
-void**
-procdata(void)
-{
- return &_threadgetproc()->udata;
-}
-
-static Lock privlock;
-static int privmask = 1;
-
-int
-tprivalloc(void)
-{
- int i;
-
- lock(&privlock);
- for(i=0; i<NPRIV; i++)
- if(!(privmask&(1<<i))){
- privmask |= 1<<i;
- unlock(&privlock);
- return i;
- }
- unlock(&privlock);
- return -1;
-}
-
-void
-tprivfree(int i)
-{
- if(i < 0 || i >= NPRIV)
- abort();
- lock(&privlock);
- privmask &= ~(1<<i);
-}
-
-void**
-tprivaddr(int i)
-{
- return &_threadgetproc()->thread->udata[i];
-}
diff --git a/src/libthread/iocall.c b/src/libthread/iocall.c
deleted file mode 100644
index e359c4d5..00000000
--- a/src/libthread/iocall.c
+++ /dev/null
@@ -1,55 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <thread.h>
-#include "ioproc.h"
-
-long
-iocall(Ioproc *io, long (*op)(va_list*), ...)
-{
- char e[ERRMAX];
- int ret, inted;
- Ioproc *msg;
-
- if(send(io->c, &io) == -1){
- werrstr("interrupted");
- return -1;
- }
- assert(!io->inuse);
- io->inuse = 1;
- io->op = op;
- va_start(io->arg, op);
- msg = io;
- inted = 0;
- while(send(io->creply, &msg) == -1){
- msg = nil;
- inted = 1;
- }
- if(inted){
- werrstr("interrupted");
- return -1;
- }
-
- /*
- * If we get interrupted, we have stick around so that
- * the IO proc has someone to talk to. Send it an interrupt
- * and try again.
- */
- inted = 0;
- while(recv(io->creply, nil) == -1){
- inted = 1;
- iointerrupt(io);
- }
- USED(inted);
- va_end(io->arg);
- ret = io->ret;
- if(ret < 0)
- strecpy(e, e+sizeof e, io->err);
- io->inuse = 0;
-
- /* release resources */
- while(send(io->creply, &io) == -1)
- ;
- if(ret < 0)
- errstr(e, sizeof e);
- return ret;
-}
diff --git a/src/libthread/ioclose.c b/src/libthread/ioclose.c
deleted file mode 100644
index fbaabb7c..00000000
--- a/src/libthread/ioclose.c
+++ /dev/null
@@ -1,16 +0,0 @@
-#include "threadimpl.h"
-
-static long
-_ioclose(va_list *arg)
-{
- int fd;
-
- fd = va_arg(*arg, int);
- return close(fd);
-}
-
-int
-ioclose(Ioproc *io, int fd)
-{
- return iocall(io, _ioclose, fd);
-}
diff --git a/src/libthread/iodial.c b/src/libthread/iodial.c
deleted file mode 100644
index 2e45cfe6..00000000
--- a/src/libthread/iodial.c
+++ /dev/null
@@ -1,24 +0,0 @@
-#include "threadimpl.h"
-
-static long
-_iodial(va_list *arg)
-{
- char *addr, *local, *dir;
- int *cdfp, fd;
-
- addr = va_arg(*arg, char*);
- local = va_arg(*arg, char*);
- dir = va_arg(*arg, char*);
- cdfp = va_arg(*arg, int*);
-
-fprint(2, "before dial\n");
- fd = dial(addr, local, dir, cdfp);
-fprint(2, "after dial\n");
- return fd;
-}
-
-int
-iodial(Ioproc *io, char *addr, char *local, char *dir, int *cdfp)
-{
- return iocall(io, _iodial, addr, local, dir, cdfp);
-}
diff --git a/src/libthread/ioopen.c b/src/libthread/ioopen.c
deleted file mode 100644
index 219e581e..00000000
--- a/src/libthread/ioopen.c
+++ /dev/null
@@ -1,21 +0,0 @@
-#include <u.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include "threadimpl.h"
-
-static long
-_ioopen(va_list *arg)
-{
- char *path;
- int mode;
-
- path = va_arg(*arg, char*);
- mode = va_arg(*arg, int);
- return open(path, mode);
-}
-
-int
-ioopen(Ioproc *io, char *path, int mode)
-{
- return iocall(io, _ioopen, path, mode);
-}
diff --git a/src/libthread/ioproc.c b/src/libthread/ioproc.c
deleted file mode 100644
index 4e4c32a8..00000000
--- a/src/libthread/ioproc.c
+++ /dev/null
@@ -1,77 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <thread.h>
-#include "ioproc.h"
-
-enum
-{
- STACK = 8192,
-};
-
-void
-iointerrupt(Ioproc *io)
-{
- if(!io->inuse)
- return;
- threadint(io->tid);
-}
-
-static void
-xioproc(void *a)
-{
- Ioproc *io, *x;
- io = a;
- /*
- * first recvp acquires the ioproc.
- * second tells us that the data is ready.
- */
- for(;;){
- while(recv(io->c, &x) == -1)
- ;
- if(x == 0) /* our cue to leave */
- break;
- assert(x == io);
-
- /* caller is now committed -- even if interrupted he'll return */
- while(recv(io->creply, &x) == -1)
- ;
- if(x == 0) /* caller backed out */
- continue;
- assert(x == io);
-
- io->ret = io->op(&io->arg);
- if(io->ret < 0)
- rerrstr(io->err, sizeof io->err);
- while(send(io->creply, &io) == -1)
- ;
- while(recv(io->creply, &x) == -1)
- ;
- }
-}
-
-Ioproc*
-ioproc(void)
-{
- Ioproc *io;
-
- io = mallocz(sizeof(*io), 1);
- if(io == nil)
- sysfatal("ioproc malloc: %r");
- io->c = chancreate(sizeof(void*), 0);
- io->creply = chancreate(sizeof(void*), 0);
- io->tid = proccreate(xioproc, io, STACK);
- return io;
-}
-
-void
-closeioproc(Ioproc *io)
-{
- if(io == nil)
- return;
- iointerrupt(io);
- while(send(io->c, 0) == -1)
- ;
- chanfree(io->c);
- chanfree(io->creply);
- free(io);
-}
diff --git a/src/libthread/ioproc.h b/src/libthread/ioproc.h
deleted file mode 100644
index f3a488d3..00000000
--- a/src/libthread/ioproc.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#define ioproc_arg(io, type) (va_arg((io)->arg, type))
-
-struct Ioproc
-{
- int tid;
- Channel *c, *creply;
- int inuse;
- long (*op)(va_list*);
- va_list arg;
- long ret;
- char err[ERRMAX];
- Ioproc *next;
-};
-
diff --git a/src/libthread/ioread.c b/src/libthread/ioread.c
deleted file mode 100644
index 62b1be03..00000000
--- a/src/libthread/ioread.c
+++ /dev/null
@@ -1,20 +0,0 @@
-#include "threadimpl.h"
-
-static long
-_ioread(va_list *arg)
-{
- int fd;
- void *a;
- long n;
-
- fd = va_arg(*arg, int);
- a = va_arg(*arg, void*);
- n = va_arg(*arg, long);
- return read(fd, a, n);
-}
-
-long
-ioread(Ioproc *io, int fd, void *a, long n)
-{
- return iocall(io, _ioread, fd, a, n);
-}
diff --git a/src/libthread/ioreadn.c b/src/libthread/ioreadn.c
deleted file mode 100644
index b843f603..00000000
--- a/src/libthread/ioreadn.c
+++ /dev/null
@@ -1,21 +0,0 @@
-#include "threadimpl.h"
-
-static long
-_ioreadn(va_list *arg)
-{
- int fd;
- void *a;
- long n;
-
- fd = va_arg(*arg, int);
- a = va_arg(*arg, void*);
- n = va_arg(*arg, long);
- n = readn(fd, a, n);
- return n;
-}
-
-long
-ioreadn(Ioproc *io, int fd, void *a, long n)
-{
- return iocall(io, _ioreadn, fd, a, n);
-}
diff --git a/src/libthread/iorw.c b/src/libthread/iorw.c
new file mode 100644
index 00000000..2ad80878
--- /dev/null
+++ b/src/libthread/iorw.c
@@ -0,0 +1,178 @@
+#include <u.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <libc.h>
+#include <fcall.h>
+#include <thread.h>
+#include "ioproc.h"
+
+static long
+_ioclose(va_list *arg)
+{
+ int fd;
+
+ fd = va_arg(*arg, int);
+ return close(fd);
+}
+int
+ioclose(Ioproc *io, int fd)
+{
+ return iocall(io, _ioclose, fd);
+}
+
+static long
+_iodial(va_list *arg)
+{
+ char *addr, *local, *dir;
+ int *cdfp, fd;
+
+ addr = va_arg(*arg, char*);
+ local = va_arg(*arg, char*);
+ dir = va_arg(*arg, char*);
+ cdfp = va_arg(*arg, int*);
+
+ fd = dial(addr, local, dir, cdfp);
+ return fd;
+}
+int
+iodial(Ioproc *io, char *addr, char *local, char *dir, int *cdfp)
+{
+ return iocall(io, _iodial, addr, local, dir, cdfp);
+}
+
+static long
+_ioopen(va_list *arg)
+{
+ char *path;
+ int mode;
+
+ path = va_arg(*arg, char*);
+ mode = va_arg(*arg, int);
+ return open(path, mode);
+}
+int
+ioopen(Ioproc *io, char *path, int mode)
+{
+ return iocall(io, _ioopen, path, mode);
+}
+
+static long
+_ioread(va_list *arg)
+{
+ int fd;
+ void *a;
+ long n;
+
+ fd = va_arg(*arg, int);
+ a = va_arg(*arg, void*);
+ n = va_arg(*arg, long);
+ return read(fd, a, n);
+}
+long
+ioread(Ioproc *io, int fd, void *a, long n)
+{
+ return iocall(io, _ioread, fd, a, n);
+}
+
+static long
+_ioreadn(va_list *arg)
+{
+ int fd;
+ void *a;
+ long n;
+
+ fd = va_arg(*arg, int);
+ a = va_arg(*arg, void*);
+ n = va_arg(*arg, long);
+ n = readn(fd, a, n);
+ return n;
+}
+long
+ioreadn(Ioproc *io, int fd, void *a, long n)
+{
+ return iocall(io, _ioreadn, fd, a, n);
+}
+
+static long
+_iosleep(va_list *arg)
+{
+ long n;
+
+ n = va_arg(*arg, long);
+ return sleep(n);
+}
+int
+iosleep(Ioproc *io, long n)
+{
+ return iocall(io, _iosleep, n);
+}
+
+static long
+_iowrite(va_list *arg)
+{
+ int fd;
+ void *a;
+ long n, nn;
+
+ fd = va_arg(*arg, int);
+ a = va_arg(*arg, void*);
+ n = va_arg(*arg, long);
+ nn = write(fd, a, n);
+ return nn;
+}
+long
+iowrite(Ioproc *io, int fd, void *a, long n)
+{
+ return iocall(io, _iowrite, fd, a, n);
+}
+
+static long
+_iosendfd(va_list *arg)
+{
+ int n, fd, fd2;
+
+ fd = va_arg(*arg, int);
+ fd2 = va_arg(*arg, int);
+ n = sendfd(fd, fd2);
+ return n;
+}
+int
+iosendfd(Ioproc *io, int fd, int fd2)
+{
+ return iocall(io, _iosendfd, fd, fd2);
+}
+
+static long
+_iorecvfd(va_list *arg)
+{
+ int n, fd;
+
+ fd = va_arg(*arg, int);
+ n = recvfd(fd);
+ return n;
+}
+int
+iorecvfd(Ioproc *io, int fd)
+{
+ return iocall(io, _iorecvfd, fd);
+}
+
+static long
+_ioread9pmsg(va_list *arg)
+{
+ int fd;
+ void *a;
+ int n;
+ int r;
+
+ fd = va_arg(*arg, int);
+ a = va_arg(*arg, void*);
+ n = va_arg(*arg, int);
+ r = read9pmsg(fd, a, n);
+ return n;
+}
+int
+ioread9pmsg(Ioproc *io, int fd, void *a, int n)
+{
+ return iocall(io, _ioread9pmsg, fd, a, n);
+}
diff --git a/src/libthread/iosleep.c b/src/libthread/iosleep.c
deleted file mode 100644
index 55756454..00000000
--- a/src/libthread/iosleep.c
+++ /dev/null
@@ -1,16 +0,0 @@
-#include "threadimpl.h"
-
-static long
-_iosleep(va_list *arg)
-{
- long n;
-
- n = va_arg(*arg, long);
- return sleep(n);
-}
-
-int
-iosleep(Ioproc *io, long n)
-{
- return iocall(io, _iosleep, n);
-}
diff --git a/src/libthread/iowrite.c b/src/libthread/iowrite.c
deleted file mode 100644
index 593224c2..00000000
--- a/src/libthread/iowrite.c
+++ /dev/null
@@ -1,22 +0,0 @@
-#include "threadimpl.h"
-
-static long
-_iowrite(va_list *arg)
-{
- int fd;
- void *a;
- long n, nn;
-
- fd = va_arg(*arg, int);
- a = va_arg(*arg, void*);
- n = va_arg(*arg, long);
- nn = write(fd, a, n);
-fprint(2, "_iowrite %d %d %r\n", n, nn);
- return nn;
-}
-
-long
-iowrite(Ioproc *io, int fd, void *a, long n)
-{
- return iocall(io, _iowrite, fd, a, n);
-}
diff --git a/src/libthread/kill.c b/src/libthread/kill.c
deleted file mode 100644
index 648bd66e..00000000
--- a/src/libthread/kill.c
+++ /dev/null
@@ -1,90 +0,0 @@
-#include <u.h>
-#include <signal.h>
-#include "threadimpl.h"
-
-static void tinterrupt(Proc*, Thread*);
-
-static void
-threadxxxgrp(int grp, int dokill)
-{
- Proc *p;
- Thread *t;
-
- lock(&_threadpq.lock);
- for(p=_threadpq.head; p; p=p->next){
- lock(&p->lock);
- for(t=p->threads.head; t; t=t->nextt)
- if(t->grp == grp){
- if(dokill)
- t->moribund = 1;
- tinterrupt(p, t);
- }
- unlock(&p->lock);
- }
- unlock(&_threadpq.lock);
- _threadbreakrendez();
-}
-
-static void
-threadxxx(int id, int dokill)
-{
- Proc *p;
- Thread *t;
-
- lock(&_threadpq.lock);
- for(p=_threadpq.head; p; p=p->next){
- lock(&p->lock);
- for(t=p->threads.head; t; t=t->nextt)
- if(t->id == id){
- if(dokill)
- t->moribund = 1;
- tinterrupt(p, t);
- unlock(&p->lock);
- unlock(&_threadpq.lock);
- _threadbreakrendez();
- return;
- }
- unlock(&p->lock);
- }
- unlock(&_threadpq.lock);
- _threaddebug(DBGNOTE, "Can't find thread to kill");
- return;
-}
-
-void
-threadkillgrp(int grp)
-{
- threadxxxgrp(grp, 1);
-}
-
-void
-threadkill(int id)
-{
- threadxxx(id, 1);
-}
-
-void
-threadintgrp(int grp)
-{
- threadxxxgrp(grp, 0);
-}
-
-void
-threadint(int id)
-{
- threadxxx(id, 0);
-}
-
-static void
-tinterrupt(Proc *p, Thread *t)
-{
- switch(t->state){
- case Running:
- kill(p->pid, SIGINT);
- // postnote(PNPROC, p->pid, "threadint");
- break;
- case Rendezvous:
- _threadflagrendez(t);
- break;
- }
-}
diff --git a/src/libthread/label.h b/src/libthread/label.h
deleted file mode 100644
index 5081f48f..00000000
--- a/src/libthread/label.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * setjmp and longjmp, but our own because some (stupid) c libraries
- * assume longjmp is only used to move up the stack, and error out
- * if you do otherwise.
- */
-
-typedef struct Label Label;
-#define LABELDPC 0
-
-#if defined(__linux__)
-#include <ucontext.h>
-struct Label
-{
- ucontext_t uc;
-};
-#elif defined (__i386__) && (defined(__FreeBSD__) || defined(__linux__) || defined(__OpenBSD__))
-struct Label
-{
- ulong pc;
- ulong bx;
- ulong sp;
- ulong bp;
- ulong si;
- ulong di;
-};
-#elif defined(__APPLE__)
-struct Label
-{
- ulong pc; /* lr */
- ulong cr; /* mfcr */
- ulong ctr; /* mfcr */
- ulong xer; /* mfcr */
- ulong sp; /* callee saved: r1 */
- ulong toc; /* callee saved: r2 */
- ulong gpr[19]; /* callee saved: r13-r31 */
-// XXX: currently do not save vector registers or floating-point state
-// ulong pad;
-// uvlong fpr[18]; /* callee saved: f14-f31 */
-// ulong vr[4*12]; /* callee saved: v20-v31, 256-bits each */
-};
-#elif defined(__sun__)
-struct Label
-{
- ulong input[8]; /* %i registers */
- ulong local[8]; /* %l registers */
- ulong sp; /* %o6 */
- ulong link; /* %o7 */
-};
-#elif defined(__powerpc__)
-struct Label
-{
- ulong pc; /* lr */
- ulong cr; /* mfcr */
- ulong ctr; /* mfcr */
- ulong xer; /* mfcr */
- ulong sp; /* callee saved: r1 */
- ulong toc; /* callee saved: r2 */
- ulong gpr[19]; /* callee saved: r13-r31 */
-// XXX: currently do not save vector registers or floating-point state
-// ulong pad;
-// uvlong fpr[18]; /* callee saved: f14-f31 */
-// ulong vr[4*12]; /* callee saved: v20-v31, 256-bits each */
-};
-#else
-#error "Unknown or unsupported architecture"
-#endif
-
-
diff --git a/src/libthread/lib.c b/src/libthread/lib.c
deleted file mode 100644
index 86e7506e..00000000
--- a/src/libthread/lib.c
+++ /dev/null
@@ -1,35 +0,0 @@
-#include "threadimpl.h"
-
-static long totalmalloc;
-
-void*
-_threadmalloc(long size, int z)
-{
- void *m;
-
- m = malloc(size);
- if (m == nil)
- sysfatal("Malloc of size %ld failed: %r\n", size);
- setmalloctag(m, getcallerpc(&size));
- totalmalloc += size;
- if (size > 1000000) {
- fprint(2, "Malloc of size %ld, total %ld\n", size, totalmalloc);
- abort();
- }
- if (z)
- _threadmemset(m, 0, size);
- return m;
-}
-
-void
-_threadsysfatal(char *fmt, va_list arg)
-{
- char buf[1024]; /* size doesn't matter; we're about to exit */
-
- vseprint(buf, buf+sizeof(buf), fmt, arg);
- if(argv0)
- fprint(2, "%s: %s\n", argv0, buf);
- else
- fprint(2, "%s\n", buf);
- threadexitsall(buf);
-}
diff --git a/src/libthread/main.c b/src/libthread/main.c
deleted file mode 100644
index bc4efd27..00000000
--- a/src/libthread/main.c
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Thread library.
- */
-
-#include "threadimpl.h"
-
-typedef struct Mainarg Mainarg;
-struct Mainarg
-{
- int argc;
- char **argv;
-};
-
-int mainstacksize;
-
-extern void (*_sysfatal)(char*, va_list);
-extern Jmp *(*_notejmpbuf)(void);
-
-static void
-mainlauncher(void *arg)
-{
- Mainarg *a;
-
- a = arg;
- _kmaininit();
- threadmain(a->argc, a->argv);
- threadexits("threadmain");
-}
-
-int
-main(int argc, char **argv)
-{
- Mainarg a;
- Proc *p;
-
- /*
- * In pthreads, threadmain is actually run in a subprocess,
- * so that the main process can exit (if threaddaemonize is called).
- * The main process relays notes to the subprocess.
- * _Threadbackgroundsetup will return only in the subprocess.
- */
- _threadbackgroundinit();
-
- /*
- * Instruct QLock et al. to use our scheduling functions
- * so that they can operate at the thread level.
- */
- _qlockinit(_threadsleep, _threadwakeup);
-
- /*
- * Install our own _threadsysfatal which takes down
- * the whole confederation of procs.
- */
- _sysfatal = _threadsysfatal;
-
- /*
- * Install our own jump handler.
- */
- _notejmpbuf = _threadgetjmp;
-
- /*
- * Install our own signal handler.
- */
- notify(_threadnote);
-
- /*
- * Construct the initial proc running mainlauncher(&a).
- */
- if(mainstacksize == 0)
- mainstacksize = 32*1024;
- a.argc = argc;
- a.argv = argv;
- p = _newproc();
- _newthread(p, mainlauncher, &a, mainstacksize, "threadmain", 0);
- _threadscheduler(p);
- abort(); /* not reached */
- return 0;
-}
-
-/*
- * No-op function here so that sched.o drags in main.o.
- */
-void
-_threadlinkmain(void)
-{
-}
-
-Jmp*
-_threadgetjmp(void)
-{
- static Jmp j;
- Proc *p;
-
- p = _threadgetproc();
- if(p == nil)
- return &j;
- return &p->sigjmp;
-}
diff --git a/src/libthread/memset.c b/src/libthread/memset.c
deleted file mode 100644
index dd74fb6c..00000000
--- a/src/libthread/memset.c
+++ /dev/null
@@ -1,8 +0,0 @@
-#include "threadimpl.h"
-#include <string.h>
-
-void
-_threadmemset(void *v, int c, int n)
-{
- memset(v, c, n);
-}
diff --git a/src/libthread/memsetd.c b/src/libthread/memsetd.c
deleted file mode 100644
index ef3f9605..00000000
--- a/src/libthread/memsetd.c
+++ /dev/null
@@ -1,8 +0,0 @@
-#include "threadimpl.h"
-#include <string.h>
-
-void
-_threaddebugmemset(void *v, int c, int n)
-{
- memset(v, c, n);
-}
diff --git a/src/libthread/mkfile b/src/libthread/mkfile
deleted file mode 100644
index 6492bb93..00000000
--- a/src/libthread/mkfile
+++ /dev/null
@@ -1,73 +0,0 @@
-<$PLAN9/src/mkhdr
-
-LIB=libthread.a
-SYSOFILES=`sh ./sysofiles.sh`
-OFILES=\
- $SYSOFILES\
- channel.$O\
- chanprint.$O\
- create.$O\
- debug.$O\
- exec-unix.$O\
- exit.$O\
- fdwait.$O\
- getpid.$O\
- id.$O\
- iocall.$O\
- ioclose.$O\
- iodial.$O\
- ioopen.$O\
- ioproc.$O\
- ioread.$O\
- ioreadn.$O\
- iosleep.$O\
- iowrite.$O\
- lib.$O\
- main.$O\
- memset.$O\
- memsetd.$O\
- read9pmsg.$O\
- ref.$O\
- sched.$O\
- setproc.$O\
- sleep.$O\
-
-HFILES=\
- $PLAN9/include/thread.h\
- label.h\
- threadimpl.h\
-
-<$PLAN9/src/mksyslib
-
-tfork: tfork.$O $PLAN9/lib/$LIB
- $LD -o tfork tfork.$O $LDFLAGS -lthread -l9
-
-tprimes: tprimes.$O $PLAN9/lib/$LIB
- $LD -o tprimes tprimes.$O $LDFLAGS -lthread -l9
-
-texec: texec.$O $PLAN9/lib/$LIB
- $LD -o texec texec.$O $LDFLAGS -lthread -l9
-
-tspawn: tspawn.$O $PLAN9/lib/$LIB
- $LD -o tspawn tspawn.$O $LDFLAGS -lthread -l9
-
-trend: trend.$O $PLAN9/lib/$LIB
- $LD -o trend trend.$O $LDFLAGS -lthread -l9
-
-tsignal: tsignal.$O $PLAN9/lib/$LIB
- $LD -o tsignal tsignal.$O $LDFLAGS -lthread -l9
-
-CLEANFILES=$CLEANFILES tprimes texec
-
-asm-Linux-ppc.$O: asm-Linux-386.s
-asm-Linux-386.$O: asm-FreeBSD-386.s
-asm-NetBSD-386.$O: asm-FreeBSD-386.s
-asm-OpenBSD-386.$O: asm-FreeBSD-386.s
-
-# sorry
-VG=`test -d /home/rsc/pub/valgrind-debian && echo -DUSEVALGRIND`
-# VG=
-
-CFLAGS=$CFLAGS $VG
-
-Linux-clone.$O: execproc.ch exit-getpid.ch proctab.ch procstack.ch
diff --git a/src/libthread/note.c b/src/libthread/note.c
deleted file mode 100644
index ed40c08f..00000000
--- a/src/libthread/note.c
+++ /dev/null
@@ -1,145 +0,0 @@
-#include "threadimpl.h"
-
-
-int _threadnopasser;
-
-#define NFN 33
-#define ERRLEN 48
-typedef struct Note Note;
-struct Note
-{
- Lock inuse;
- Proc *proc; /* recipient */
- char s[ERRMAX]; /* arg2 */
-};
-
-static Note notes[128];
-static Note *enotes = notes+nelem(notes);
-static int (*onnote[NFN])(void*, char*);
-static int onnotepid[NFN];
-static Lock onnotelock;
-
-int
-threadnotify(int (*f)(void*, char*), int in)
-{
- int i, topid;
- int (*from)(void*, char*), (*to)(void*, char*);
-
- if(in){
- from = 0;
- to = f;
- topid = _threadgetproc()->pid;
- }else{
- from = f;
- to = 0;
- topid = 0;
- }
- lock(&onnotelock);
- for(i=0; i<NFN; i++)
- if(onnote[i]==from){
- onnote[i] = to;
- onnotepid[i] = topid;
- break;
- }
- unlock(&onnotelock);
- return i<NFN;
-}
-
-static void
-delayednotes(Proc *p, void *v)
-{
- int i;
- Note *n;
- int (*fn)(void*, char*);
-
- if(!p->pending)
- return;
-
- p->pending = 0;
- for(n=notes; n<enotes; n++){
- if(n->proc == p){
- for(i=0; i<NFN; i++){
- if(onnotepid[i]!=p->pid || (fn = onnote[i])==0)
- continue;
- if((*fn)(v, n->s))
- break;
- }
- if(i==NFN){
- _threaddebug(DBGNOTE, "Unhandled note %s, proc %p\n", n->s, p);
- if(strcmp(n->s, "sys: child") == 0)
- noted(NCONT);
- fprint(2, "unhandled note %s, pid %d\n", n->s, p->pid);
- if(v != nil)
- noted(NDFLT);
- else if(strncmp(n->s, "sys:", 4)==0)
- abort();
- threadexitsall(n->s);
- }
- n->proc = nil;
- unlock(&n->inuse);
- }
- }
-}
-
-void
-_threadnote(void *v, char *s)
-{
- Proc *p;
- Note *n;
-
- _threaddebug(DBGNOTE, "Got note %s", s);
- if(strncmp(s, "sys:", 4) == 0)
- noted(NDFLT);
-
-// if(_threadexitsallstatus){
-// _threaddebug(DBGNOTE, "Threadexitsallstatus = '%s'\n", _threadexitsallstatus);
-// _exits(_threadexitsallstatus);
-// }
-
- if(strcmp(s, "threadint")==0 || strcmp(s, "interrupt")==0)
- noted(NCONT);
-
- p = _threadgetproc();
- if(p == nil)
- noted(NDFLT);
-
- for(n=notes; n<enotes; n++)
- if(canlock(&n->inuse))
- break;
- if(n==enotes)
- sysfatal("libthread: too many delayed notes");
- utfecpy(n->s, n->s+ERRMAX, s);
- n->proc = p;
- p->pending = 1;
- if(!p->splhi)
- delayednotes(p, v);
- noted(NCONT);
-}
-
-int
-_procsplhi(void)
-{
- int s;
- Proc *p;
-
- p = _threadgetproc();
- s = p->splhi;
- p->splhi = 1;
- return s;
-}
-
-void
-_procsplx(int s)
-{
- Proc *p;
-
- p = _threadgetproc();
- p->splhi = s;
- if(s)
- return;
-/*
- if(p->pending)
- delayednotes(p, nil);
-*/
-}
-
diff --git a/src/libthread/pid.c b/src/libthread/pid.c
deleted file mode 100644
index bbc7dbbf..00000000
--- a/src/libthread/pid.c
+++ /dev/null
@@ -1,25 +0,0 @@
- mypid = getpid();
-
- /*
- * signal others.
- * copying all the pids first avoids other thread's
- * teardown procedures getting in the way.
- */
- lock(&_threadpq.lock);
- npid = 0;
- for(p=_threadpq.head; p; p=p->next)
- npid++;
- pid = _threadmalloc(npid*sizeof(pid[0]), 0);
- npid = 0;
- for(p = _threadpq.head; p; p=p->next)
- pid[npid++] = p->pid;
- unlock(&_threadpq.lock);
- for(i=0; i<npid; i++){
- _threaddebug(DBGSCHED, "threadexitsall kill %d", pid[i]);
- if(pid[i]==0 || pid[i]==-1)
- fprint(2, "bad pid in threadexitsall: %d\n", pid[i]);
- else if(pid[i] != mypid){
- kill(pid[i], SIGTERM);
- }
- }
-
diff --git a/src/libthread/power.c b/src/libthread/power.c
deleted file mode 100644
index b0a14e6f..00000000
--- a/src/libthread/power.c
+++ /dev/null
@@ -1,40 +0,0 @@
-#include "threadimpl.h"
-
-static void
-launcherpower(int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7,
- void (*f)(void *arg), void *arg)
-{
- (*f)(arg);
- threadexits(nil);
-}
-
-void
-_threadinitstack(Thread *t, void (*f)(void*), void *arg)
-{
- ulong *tos, *stk;
-
- tos = (ulong*)&t->stk[t->stksize&~7];
- stk = tos;
- --stk;
- --stk;
- --stk;
- --stk;
- *--stk = (ulong)arg;
- *--stk = (ulong)f;
- t->sched.pc = (ulong)launcherpower+LABELDPC;
- t->sched.sp = ((ulong)stk)-8;
- *((ulong *)t->sched.sp) = 0;
-}
-
-void
-_threadinswitch(int enter)
-{
- USED(enter);
-}
-
-void
-_threadstacklimit(void *addr, void *addr2)
-{
- USED(addr);
-}
-
diff --git a/src/libthread/procstack.ch b/src/libthread/procstack.ch
deleted file mode 100644
index ccf81866..00000000
--- a/src/libthread/procstack.ch
+++ /dev/null
@@ -1,75 +0,0 @@
-static int fforkstacksize = 16384;
-
-typedef struct Stack Stack;
-struct Stack
-{
- Stack *next;
- Stack *fnext;
- int pid;
-};
-
-static Lock stacklock;
-static Stack *freestacks;
-static Stack *allstacks;
-static int stackmallocs;
-static void gc(void);
-
-static void*
-mallocstack(void)
-{
- Stack *p;
-
- lock(&stacklock);
-top:
- p = freestacks;
- if(p)
- freestacks = p->fnext;
- else{
- if(stackmallocs++%1 == 0)
- gc();
- if(freestacks)
- goto top;
- p = malloc(fforkstacksize);
- p->next = allstacks;
- allstacks = p;
- }
- if(p)
- p->pid = 1;
- unlock(&stacklock);
- return p;
-}
-
-static void
-gc(void)
-{
- Stack *p;
-
- for(p=allstacks; p; p=p->next){
- if(p->pid > 1 && procexited(p->pid)){
- if(0) fprint(2, "reclaim stack from %d\n", p->pid);
- p->pid = 0;
- }
- if(p->pid == 0){
- p->fnext = freestacks;
- freestacks = p;
- }
- }
-}
-
-static void
-freestack(void *v)
-{
- Stack *p;
-
- p = v;
- if(p == nil)
- return;
- lock(&stacklock);
- p->fnext = freestacks;
- p->pid = 0;
- freestacks = p;
- unlock(&stacklock);
- return;
-}
-
-
diff --git a/src/libthread/proctab.c b/src/libthread/proctab.c
deleted file mode 100644
index b8dd2097..00000000
--- a/src/libthread/proctab.c
+++ /dev/null
@@ -1,75 +0,0 @@
-#include "threadimpl.h"
-
-/* this will need work */
-enum
-{
- PTABHASH = 257,
-};
-
-static int multi;
-static Proc *theproc;
-
-void
-_threadmultiproc(void)
-{
- if(multi == 0){
- multi = 1;
- _threadsetproc(theproc);
- }
-}
-
-static Lock ptablock;
-Proc *ptab[PTABHASH];
-
-void
-_threadsetproc(Proc *p)
-{
- int h;
-
- if(!multi){
- theproc = p;
- return;
- }
- lock(&ptablock);
- h = ((unsigned)p->pid)%PTABHASH;
- p->link = ptab[h];
- unlock(&ptablock);
- ptab[h] = p;
-}
-
-static Proc*
-__threadgetproc(int rm)
-{
- Proc **l, *p;
- int h, pid;
-
- if(!multi)
- return theproc;
-
- pid = getpid();
-
- lock(&ptablock);
- h = ((unsigned)pid)%PTABHASH;
- for(l=&ptab[h]; p=*l; l=&p->link){
- if(p->pid == pid){
- if(rm)
- *l = p->link;
- unlock(&ptablock);
- return p;
- }
- }
- unlock(&ptablock);
- return nil;
-}
-
-Proc*
-_threadgetproc(void)
-{
- return __threadgetproc(0);
-}
-
-Proc*
-_threaddelproc(void)
-{
- return __threadgetproc(1);
-}
diff --git a/src/libthread/proctab.ch b/src/libthread/proctab.ch
deleted file mode 100644
index d51543f9..00000000
--- a/src/libthread/proctab.ch
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Proc structure hash table indexed by proctabid() (usually getpid()).
- * No lock is necessary for lookups (important when called from signal
- * handlers).
- *
- * To be included from other files (e.g., Linux-clone.c).
- */
-
-#define T ((void*)-1)
-
-enum
-{
- PTABHASH = 1031,
-};
-
-static Lock ptablock;
-static Proc *proctab[PTABHASH];
-static Proc *theproc;
-static int multi;
-
-void
-_threadmultiproc(void)
-{
- if(multi == 0){
- multi = 1;
- _threadsetproc(theproc);
- }
-}
-
-void
-_threadsetproc(Proc *p)
-{
- int i, h;
- Proc **t;
-
- if(!multi){
- theproc = p;
- return;
- }
- lock(&ptablock);
- p->procid = procid();
- h = p->procid%PTABHASH;
- for(i=0; i<PTABHASH; i++){
- t = &proctab[(h+i)%PTABHASH];
- if(*t==nil || *t==T){
- *t = p;
- break;
- }
- }
- unlock(&ptablock);
- if(i == PTABHASH)
- sysfatal("too many procs - proctab is full");
-}
-
-static Proc**
-_threadfindproc(int id)
-{
- int i, h;
- Proc **t;
-
- if(!multi)
- return &theproc;
-
- h = id%PTABHASH;
- for(i=0; i<PTABHASH; i++){
- t = &proctab[(h+i)%PTABHASH];
- if(*t != nil && *t != T && (*t)->procid == id){
- unlock(&ptablock);
- return t;
- }
- }
- return nil;
-}
-
-Proc*
-_threadgetproc(void)
-{
- Proc **t;
-
- t = _threadfindproc(procid());
- if(t == nil)
- return nil;
- return *t;
-}
-
-Proc*
-_threaddelproc(void)
-{
- Proc **t, *p;
-
- t = _threadfindproc(procid());
- if(t == nil)
- return nil;
- p = *t;
- *t = T;
- return p;
-}
diff --git a/src/libthread/pthread.c b/src/libthread/pthread.c
deleted file mode 100644
index 83d8b023..00000000
--- a/src/libthread/pthread.c
+++ /dev/null
@@ -1,271 +0,0 @@
-#include <u.h>
-#include <errno.h>
-#include "threadimpl.h"
-
-/*
- * Basic kernel thread management.
- */
-static pthread_key_t key;
-
-void
-_kthreadinit(void)
-{
- pthread_key_create(&key, 0);
-}
-
-void
-_kthreadsetproc(Proc *p)
-{
- sigset_t all;
-
- p->pthreadid = pthread_self();
- sigfillset(&all);
- pthread_sigmask(SIG_SETMASK, &all, nil);
- pthread_setspecific(key, p);
-}
-
-Proc*
-_kthreadgetproc(void)
-{
- return pthread_getspecific(key);
-}
-
-void
-_kthreadstartproc(Proc *p)
-{
- Proc *np;
- pthread_t tid;
- sigset_t all;
-
- np = p->newproc;
- sigfillset(&all);
- pthread_sigmask(SIG_SETMASK, &all, nil);
- if(pthread_create(&tid, nil, (void*(*)(void*))_threadscheduler,
- np) < 0)
- sysfatal("pthread_create: %r");
- np->pthreadid = tid;
-}
-
-void
-_kthreadexitproc(char *exitstr)
-{
- _threaddebug(DBGSCHED, "_pthreadexit");
- pthread_exit(nil);
-}
-
-void
-_kthreadexitallproc(char *exitstr)
-{
- _threaddebug(DBGSCHED, "_threadexitallproc");
- exits(exitstr);
-}
-
-/*
- * Exec. Pthreads does the hard work of making it possible
- * for any thread to do the waiting, so this is pretty easy.
- * We create a separate proc whose job is to wait for children
- * and deliver wait messages.
- */
-static Channel *_threadexecwaitchan;
-
-static void
-_threadwaitproc(void *v)
-{
- Channel *c;
- Waitmsg *w;
-
- _threadinternalproc();
-
- USED(v);
-
- for(;;){
- w = wait();
- if(w == nil){
- if(errno == ECHILD) /* wait for more */
- recvul(_threadexecwaitchan);
- continue;
- }
- if((c = _threadwaitchan) != nil)
- sendp(c, w);
- else
- free(w);
- }
- fprint(2, "_threadwaitproc exits\n"); /* not reached */
-}
-
-
-/*
- * Call _threadexec in the right conditions.
- */
-int
-_kthreadexec(Channel *c, int fd[3], char *prog, char *args[], int freeargs)
-{
- static Lock lk;
- int rv;
-
- if(!_threadexecwaitchan){
- lock(&lk);
- if(!_threadexecwaitchan){
- _threadexecwaitchan = chancreate(sizeof(ulong), 1);
- proccreate(_threadwaitproc, nil, 32*1024);
- }
- unlock(&lk);
- }
- rv = _threadexec(c, fd, prog, args, freeargs);
- nbsendul(_threadexecwaitchan, 1);
- return rv;
-}
-
-/*
- * Some threaded applications want to run in the background.
- * Calling fork() and exiting in the parent will result in a child
- * with a single pthread (if we are using pthreads), and will screw
- * up our internal process info if we are using clone/rfork.
- * Instead, apps should call threadbackground(), which takes
- * care of this.
- *
- * _threadbackgroundinit is called from main.
- */
-
-static int mainpid, passerpid;
-
-static void
-passer(void *x, char *msg)
-{
- Waitmsg *w;
-
- USED(x);
- if(strcmp(msg, "sys: usr2") == 0)
- _exit(0); /* daemonize */
- else if(strcmp(msg, "sys: child") == 0){
- /* child exited => so should we */
- w = wait();
- if(w == nil)
- _exit(1);
- _exit(atoi(w->msg));
- }else
- postnote(PNGROUP, mainpid, msg);
-}
-
-void
-_threadbackgroundinit(void)
-{
- int pid;
- sigset_t mask;
-
- sigfillset(&mask);
- pthread_sigmask(SIG_BLOCK, &mask, 0);
-
-return;
-
- passerpid = getpid();
- switch(pid = fork()){
- case -1:
- sysfatal("fork: %r");
-
- case 0:
- rfork(RFNOTEG);
- return;
-
- default:
- break;
- }
-
- mainpid = pid;
- notify(passer);
- notifyon("sys: child");
- notifyon("sys: usr2"); /* should already be on */
- for(;;)
- pause();
- _exit(0);
-}
-
-void
-threadbackground(void)
-{
- if(passerpid <= 1)
- return;
- postnote(PNPROC, passerpid, "sys: usr2");
-}
-
-/*
- * Notes.
- */
-Channel *_threadnotechan;
-static ulong sigs;
-static Lock _threadnotelk;
-static void _threadnoteproc(void*);
-extern int _p9strsig(char*);
-extern char *_p9sigstr(int);
-
-Channel*
-threadnotechan(void)
-{
- if(_threadnotechan == nil){
- lock(&_threadnotelk);
- if(_threadnotechan == nil){
- _threadnotechan = chancreate(sizeof(char*), 1);
- proccreate(_threadnoteproc, nil, 32*1024);
- }
- unlock(&_threadnotelk);
- }
- return _threadnotechan;
-}
-
-void
-_threadnote(void *x, char *msg)
-{
- USED(x);
-
- if(_threadexitsallstatus)
- _kthreadexitproc(_threadexitsallstatus);
-
- if(strcmp(msg, "sys: usr2") == 0)
- noted(NCONT);
-
- if(_threadnotechan == nil)
- noted(NDFLT);
-
- sigs |= 1<<_p9strsig(msg);
- noted(NCONT);
-}
-
-void
-_threadnoteproc(void *x)
-{
- int i;
- sigset_t none;
- Channel *c;
-
- _threadinternalproc();
- sigemptyset(&none);
- pthread_sigmask(SIG_SETMASK, &none, 0);
-
- c = _threadnotechan;
- for(;;){
- if(sigs == 0)
- pause();
- for(i=0; i<32; i++){
- if((sigs&(1<<i)) == 0)
- continue;
- sigs &= ~(1<<i);
- if(i == 0)
- continue;
- sendp(c, _p9sigstr(i));
- }
- }
-}
-
-void
-_threadschednote(void)
-{
-}
-
-void
-_kmaininit(void)
-{
- sigset_t all;
-
- sigfillset(&all);
- pthread_sigmask(SIG_SETMASK, &all, 0);
-}
diff --git a/src/libthread/qlock.c b/src/libthread/qlock.c
new file mode 100644
index 00000000..30a0c9e1
--- /dev/null
+++ b/src/libthread/qlock.c
@@ -0,0 +1,3 @@
+#include "u.h"
+#include "libc.h"
+
diff --git a/src/libthread/read9pmsg.c b/src/libthread/read9pmsg.c
deleted file mode 100644
index 652fc82f..00000000
--- a/src/libthread/read9pmsg.c
+++ /dev/null
@@ -1,32 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <fcall.h>
-#include <thread.h>
-
-int
-threadread9pmsg(int fd, void *abuf, uint n)
-{
- int m, len;
- uchar *buf;
-
- buf = abuf;
-
- /* read count */
- m = threadreadn(fd, buf, BIT32SZ);
- if(m != BIT32SZ){
- if(m < 0)
- return -1;
- return 0;
- }
-
- len = GBIT32(buf);
- if(len <= BIT32SZ || len > n){
- werrstr("bad length in 9P2000 message header");
- return -1;
- }
- len -= BIT32SZ;
- m = threadreadn(fd, buf+BIT32SZ, len);
- if(m < len)
- return 0;
- return BIT32SZ+m;
-}
diff --git a/src/libthread/ref.c b/src/libthread/ref.c
deleted file mode 100644
index a3b2cbae..00000000
--- a/src/libthread/ref.c
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Atomic reference counts - used by applications.
- *
- * We use locks to avoid the assembly of the Plan 9 versions.
- */
-
-#include "threadimpl.h"
-
-void
-incref(Ref *r)
-{
- lock(&r->lk);
- r->ref++;
- unlock(&r->lk);
-}
-
-long
-decref(Ref *r)
-{
- long n;
-
- lock(&r->lk);
- n = --r->ref;
- unlock(&r->lk);
- return n;
-}
diff --git a/src/libthread/sched.c b/src/libthread/sched.c
deleted file mode 100644
index ac982da8..00000000
--- a/src/libthread/sched.c
+++ /dev/null
@@ -1,343 +0,0 @@
-/*
- * Thread scheduler.
- */
-#include "threadimpl.h"
-
-static Thread *runthread(Proc*);
-static void schedexit(Proc*);
-
-/*
- * Main scheduling loop.
- */
-void
-_threadscheduler(void *arg)
-{
- Proc *p;
- Thread *t;
-
- p = arg;
-
- _threadlinkmain();
- _threadsetproc(p);
-
- for(;;){
- /*
- * Clean up zombie children.
- */
-
- /*
- * Find next thread to run.
- */
- _threaddebug(DBGSCHED, "runthread");
- t = runthread(p);
- if(t == nil)
- schedexit(p);
-
- /*
- * If it's ready, run it (might instead be marked to die).
- */
- lock(&p->lock);
- if(t->state == Ready){
- _threaddebug(DBGSCHED, "running %d.%d", p->id, t->id);
- t->state = Running;
- t->nextstate = Ready;
- p->thread = t;
- unlock(&p->lock);
- _swaplabel(&p->context, &t->context);
- lock(&p->lock);
- p->thread = nil;
- }
-
- /*
- * If thread needs to die, kill it.
- * t->proc == p may not be true if we're
- * trying to jump into the exec proc (see exec-unix.c).
- */
- if(t->moribund){
- _threaddebug(DBGSCHED, "moribund %d.%d", p->id, t->id);
- if(t->moribund != 1)
- print("moribund broke %p %d\n", &t->moribund, t->moribund);
- assert(t->moribund == 1);
- t->state = Dead;
- _procdelthread(p, t);
- unlock(&p->lock);
- _threadfree(t);
- t = nil;
- continue;
- }
-
- /*
- * If the thread has asked to move to another proc,
- * let it go (only to be used in *very* special situations).
- if(t->nextproc != p)
- _procdelthread(p, t);
- */
-
- unlock(&p->lock);
-
- /*
- * If the thread has asked to move to another proc,
- * add it to the new proc.
- */
- if(t->nextproc != p){
- // lock(&t->nextproc->lock);
- // _procaddthread(t->nextproc, t);
- // unlock(&t->nextproc->lock);
- t->proc = t->nextproc;
- }
-
- /*
- * If there is a request to run a function on the
- * scheduling stack, do so.
- */
- if(p->schedfn){
- _threaddebug(DBGSCHED, "schedfn");
- p->schedfn(p);
- p->schedfn = nil;
- _threaddebug(DBGSCHED, "schedfn ended");
- }
-
- /*
- * Move the thread along.
- */
- t->state = t->nextstate;
- _threaddebug(DBGSCHED, "moveon %d.%d", t->proc->id, t->id);
- if(t->state == Ready)
- _threadready(t);
- }
-}
-
-/*
- * Called by thread to give up control of processor to scheduler.
- */
-int
-_sched(void)
-{
- Proc *p;
- Thread *t;
-
- p = _threadgetproc();
- t = p->thread;
- assert(t != nil);
- _swaplabel(&t->context, &p->context);
- return p->nsched++;
-}
-
-/*
- * Called by thread to yield the processor to other threads.
- * Returns number of other threads run between call and return.
- */
-int
-yield(void)
-{
- Proc *p;
- int nsched;
-
- p = _threadgetproc();
- nsched = p->nsched;
- return _sched() - nsched;
-}
-
-/*
- * Choose the next thread to run.
- */
-static Thread*
-runthread(Proc *p)
-{
- Thread *t;
- Tqueue *q;
-
- /*
- * No threads left?
- */
- if(p->nthreads==0 || (p->nthreads==1 && p->idle))
- return nil;
-
- _threadschednote();
- lock(&p->readylock);
- q = &p->ready;
- if(q->head == nil){
- /*
- * Is this a single-process program with an idle thread?
- */
- if(p->idle){
- /*
- * The idle thread had better be ready!
- */
- if(p->idle->state != Ready)
- sysfatal("all threads are asleep");
-
- /*
- * Run the idle thread.
- */
- unlock(&p->readylock);
- _threaddebug(DBGSCHED, "running idle thread", p->nthreads);
- return p->idle;
- }
-
- /*
- * Wait until one of our threads is readied (by another proc!).
- */
- q->asleep = 1;
- p->rend.l = &p->readylock;
- while(q->asleep){
- _procsleep(&p->rend);
- _threadschednote();
- }
-
- /*
- * Maybe we were awakened to exit?
- */
- if(_threadexitsallstatus){
- _threaddebug(DBGSCHED, "time to exit");
- _exits(_threadexitsallstatus);
- }
- assert(q->head != nil);
- }
-
- t = q->head;
- q->head = t->next;
- unlock(&p->readylock);
-
- return t;
-}
-
-/*
- * Add a newly-ready thread to its proc's run queue.
- */
-void
-_threadready(Thread *t)
-{
- Tqueue *q;
-
- /*
- * The idle thread does not go on the run queue.
- */
- if(t == t->proc->idle){
- _threaddebug(DBGSCHED, "idle thread is ready");
- return;
- }
-
- assert(t->state == Ready);
- _threaddebug(DBGSCHED, "readying %d.%d", t->proc->id, t->id);
-
- /*
- * Add thread to run queue.
- */
- q = &t->proc->ready;
- lock(&t->proc->readylock);
-
- t->next = nil;
- if(q->head == nil)
- q->head = t;
- else
- q->tail->next = t;
- q->tail = t;
-
- /*
- * Wake proc scheduler if it is sleeping.
- */
- if(q->asleep){
- assert(q->asleep == 1);
- q->asleep = 0;
- _procwakeup(&t->proc->rend);
- }
- unlock(&t->proc->readylock);
-}
-
-/*
- * Mark the given thread as the idle thread.
- * Since the idle thread was just created, it is sitting
- * somewhere on the ready queue.
- */
-void
-_threadsetidle(int id)
-{
- Tqueue *q;
- Thread *t, **l, *last;
- Proc *p;
-
- p = _threadgetproc();
-
- lock(&p->readylock);
-
- /*
- * Find thread on ready queue.
- */
- q = &p->ready;
- for(l=&q->head, last=nil; (t=*l) != nil; l=&t->next, last=t)
- if(t->id == id)
- break;
- assert(t != nil);
-
- /*
- * Remove it from ready queue.
- */
- *l = t->next;
- if(t == q->head)
- q->head = t->next;
- if(t->next == nil)
- q->tail = last;
-
- /*
- * Set as idle thread.
- */
- p->idle = t;
- _threaddebug(DBGSCHED, "p->idle is %d\n", t->id);
- unlock(&p->readylock);
-}
-
-/*
- * Mark proc as internal so that if all but internal procs exit, we exit.
- */
-void
-_threadinternalproc(void)
-{
- Proc *p;
-
- p = _threadgetproc();
- if(p->internal)
- return;
- lock(&_threadpq.lock);
- if(p->internal == 0){
- p->internal = 1;
- --_threadnprocs;
- }
- unlock(&_threadpq.lock);
-}
-
-static void
-schedexit(Proc *p)
-{
- char ex[ERRMAX];
- int n;
- Proc **l;
-
- _threaddebug(DBGSCHED, "exiting proc %d", p->id);
- lock(&_threadpq.lock);
- for(l=&_threadpq.head; *l; l=&(*l)->next){
- if(*l == p){
- *l = p->next;
- if(*l == nil)
- _threadpq.tail = l;
- break;
- }
- }
- if(p->internal)
- n = _threadnprocs;
- else
- n = --_threadnprocs;
- unlock(&_threadpq.lock);
-
- strncpy(ex, p->exitstr, sizeof ex);
- ex[sizeof ex-1] = '\0';
- free(p);
- if(n == 0){
- _threaddebug(DBGSCHED, "procexit; no more procs");
- _kthreadexitallproc(ex);
- }else{
- _threaddebug(DBGSCHED, "procexit");
- _kthreadexitproc(ex);
- }
-}
-
diff --git a/src/libthread/setproc.c b/src/libthread/setproc.c
deleted file mode 100644
index 5f1e2a8d..00000000
--- a/src/libthread/setproc.c
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Avoid using threading calls for single-proc programs.
- */
-
-#include "threadimpl.h"
-
-static int multi;
-static Proc *theproc;
-
-void
-_threadsetproc(Proc *p)
-{
- if(!multi)
- theproc = p;
- else
- _kthreadsetproc(p);
-}
-
-Proc*
-_threadgetproc(void)
-{
- if(!multi)
- return theproc;
- return _kthreadgetproc();
-}
-
-void
-_threadmultiproc(void)
-{
- if(multi)
- return;
-
- multi = 1;
- _kthreadinit();
- _threadsetproc(theproc);
-}
diff --git a/src/libthread/sleep.c b/src/libthread/sleep.c
deleted file mode 100644
index 4b0d82a1..00000000
--- a/src/libthread/sleep.c
+++ /dev/null
@@ -1,39 +0,0 @@
-#include "threadimpl.h"
-
-int _threadhighnrendez;
-int _threadnrendez;
-
-void
-_threadsleep(_Procrend *r)
-{
- Thread *t;
-
- t = _threadgetproc()->thread;
- r->arg = t;
- t->nextstate = Rendezvous;
- t->asleep = 1;
- unlock(r->l);
- _sched();
- t->asleep = 0;
- lock(r->l);
-}
-
-void
-_threadwakeup(_Procrend *r)
-{
- Thread *t;
-
- t = r->arg;
- while(t->state == Running)
- sleep(0);
- lock(&t->proc->lock);
- if(t->state == Dead){
- unlock(&t->proc->lock);
- return;
- }
- assert(t->state == Rendezvous && t->asleep);
- t->state = Ready;
- _threadready(t);
- unlock(&t->proc->lock);
-}
-
diff --git a/src/libthread/sun4u.c b/src/libthread/sun4u.c
deleted file mode 100644
index 0d2d8d24..00000000
--- a/src/libthread/sun4u.c
+++ /dev/null
@@ -1,53 +0,0 @@
-#include "threadimpl.h"
-
-static void
-launchersparc(uint o0, uint o1, uint o2, uint o3,
- uint o4, uint o5, uint o6, uint o7,
- void (*f)(void *arg), void *arg)
-{
- if(0) print("ls %x %x %x %x %x %x %x %x %x %x at %x\n",
- o0, o1, o2, o3, o4, o5, o6, o7, f, arg, &o0);
- (*f)(arg);
- threadexits(nil);
-}
-
-void
-_threadinitstack(Thread *t, void (*f)(void*), void *arg)
-{
- ulong *tos, *stk;
-
- /*
- * This is a bit more complicated than it should be,
- * because we need to set things up so that gotolabel
- * (which executes a return) gets us into launchersparc.
- * So all the registers are going to be renamed before
- * we get there. The input registers here become the
- * output registers there, which is useless.
- * The input registers there are inaccessible, so we
- * have to give launchersparc enough arguments that
- * everything ends up in the stack.
- */
- tos = (ulong*)&t->stk[t->stksize&~7];
- stk = tos;
- --stk;
- *--stk = (ulong)arg;
- *--stk = (ulong)f;
- stk -= 25; /* would love to understand this */
- t->sched.link = (ulong)launchersparc - 8;
- t->sched.input[6] = 0;
- t->sched.sp = (ulong)stk;
- if(0) print("tis %x %x at %x\n", f, arg, t->sched.sp);
-}
-
-void
-_threadinswitch(int enter)
-{
- USED(enter);
-}
-
-void
-_threadstacklimit(void *addr, void *addr2)
-{
- USED(addr);
-}
-
diff --git a/src/libthread/sysofiles.sh b/src/libthread/sysofiles.sh
deleted file mode 100644
index 11b21814..00000000
--- a/src/libthread/sysofiles.sh
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/bin/sh
-
-case "`uname`-`uname -r`" in
-Linux-2.[01234]*)
- echo Linux-clone.o ucontext.o
- exit 0
- ;;
-esac
-
-echo pthread.o ucontext.o
-exit 0
diff --git a/src/libthread/test/pthreadloop.c b/src/libthread/test/pthreadloop.c
new file mode 100644
index 00000000..73b600e7
--- /dev/null
+++ b/src/libthread/test/pthreadloop.c
@@ -0,0 +1,38 @@
+#include <pthread.h>
+#include <utf.h>
+#include <fmt.h>
+
+pthread_key_t key;
+
+void
+pexit(void *v)
+{
+ int s;
+
+ pthread_setspecific(key, (void*)1);
+ switch(fork()){
+ case -1:
+ fprint(2, "fork: %r\n");
+ case 0:
+ _exit(0);
+ default:
+ wait(&s);
+ }
+ pthread_exit(0);
+}
+
+int
+main(int argc, char *argv[])
+{
+ int i;
+ pthread_t pid;
+
+ pthread_key_create(&key, 0);
+ for(i=0;; i++){
+ print("%d\n", i);
+ if(pthread_create(&pid, 0, pexit, 0) < 0){
+ fprint(2, "pthread_create: %r\n");
+ abort();
+ }
+ }
+}
diff --git a/src/libthread/test/tprimes.c b/src/libthread/test/tprimes.c
new file mode 100644
index 00000000..91af5a73
--- /dev/null
+++ b/src/libthread/test/tprimes.c
@@ -0,0 +1,80 @@
+#include "u.h"
+#include "libc.h"
+#include "thread.h"
+
+enum
+{
+ STACK = 8192
+};
+
+int max = 10000;
+int (*mk)(void (*fn)(void*), void *arg, uint stack);
+
+void
+countthread(void *v)
+{
+ uint i;
+ Channel *c;
+
+ c = v;
+ for(i=2;; i++){
+ sendul(c, i);
+ }
+}
+
+void
+filterthread(void *v)
+{
+ uint i, p;
+ Channel *c, *nextc;
+
+ c = v;
+ p = recvul(c);
+ print("%d\n", p);
+ if(p > max)
+ threadexitsall(0);
+ nextc = chancreate(sizeof(ulong), 0);
+ mk(filterthread, nextc, STACK);
+ for(;;){
+ i = recvul(c);
+ if(i%p)
+ sendul(nextc, i);
+ }
+}
+
+void
+usage(void)
+{
+ fprint(2, "usage: tprimes [-p] [max]\n");
+ threadexitsall("usage");
+}
+
+void
+threadmain(int argc, char **argv)
+{
+ Channel *c;
+ int nbuf;
+
+ nbuf = 0;
+ mk = threadcreate;
+ ARGBEGIN{
+ default:
+ usage();
+ case 'b':
+ nbuf = atoi(EARGF(usage()));
+ break;
+ case 'p':
+ mk = proccreate;
+ max = 1000;
+ break;
+ }ARGEND
+
+ if(argc == 1)
+ max = atoi(argv[0]);
+ else if(argc)
+ usage();
+
+ c = chancreate(sizeof(ulong), nbuf);
+ mk(countthread, c, STACK);
+ mk(filterthread, c, STACK);
+}
diff --git a/src/libthread/tspawn.c b/src/libthread/test/tspawn.c
index 97962c5d..ed4df3c4 100644
--- a/src/libthread/tspawn.c
+++ b/src/libthread/test/tspawn.c
@@ -1,17 +1,6 @@
-#include <lib9.h>
-#include <thread.h>
-extern int _threaddebuglevel;
-
-void
-doexec(void *v)
-{
- int fd[3];
- char **argv = v;
-
- print("exec failed: %r\n");
- sendp(threadwaitchan(), nil);
- threadexits(nil);
-}
+#include "u.h"
+#include "libc.h"
+#include "thread.h"
void
threadmain(int argc, char **argv)
@@ -22,7 +11,6 @@ threadmain(int argc, char **argv)
ARGBEGIN{
case 'D':
- _threaddebuglevel = ~0;
break;
}ARGEND
@@ -32,6 +20,16 @@ threadmain(int argc, char **argv)
fd[2] = dup(2, -1);
if(threadspawn(fd, argv[0], argv) < 0)
sysfatal("threadspawn: %r");
+ fd[0] = dup(0, -1);
+ fd[1] = dup(1, -1);
+ fd[2] = dup(2, -1);
+ if(threadspawn(fd, argv[0], argv) < 0)
+ sysfatal("threadspawn: %r");
+ w = recvp(c);
+ if(w == nil)
+ print("exec/recvp failed: %r\n");
+ else
+ print("%d %lud %lud %lud %s\n", w->pid, w->time[0], w->time[1], w->time[2], w->msg);
w = recvp(c);
if(w == nil)
print("exec/recvp failed: %r\n");
diff --git a/src/libthread/test/tspawnloop.c b/src/libthread/test/tspawnloop.c
new file mode 100644
index 00000000..8835267f
--- /dev/null
+++ b/src/libthread/test/tspawnloop.c
@@ -0,0 +1,41 @@
+#include "u.h"
+#include "libc.h"
+#include "thread.h"
+
+void
+execproc(void *v)
+{
+ int i, fd[3];
+ char buf[100], *args[3];
+
+ i = (int)v;
+ sprint(buf, "%d", i);
+ fd[0] = dup(0, -1);
+ fd[1] = dup(1, -1);
+ fd[2] = dup(2, -1);
+ args[0] = "echo";
+ args[1] = buf;
+ args[2] = nil;
+ threadexec(nil, fd, args[0], args);
+}
+
+void
+threadmain(int argc, char **argv)
+{
+ int i;
+ Channel *c;
+ Waitmsg *w;
+
+ ARGBEGIN{
+ case 'D':
+ break;
+ }ARGEND
+
+ c = threadwaitchan();
+ for(i=0;; i++){
+ proccreate(execproc, (void*)i, 16384);
+ w = recvp(c);
+ if(w == nil)
+ sysfatal("exec/recvp failed: %r");
+ }
+}
diff --git a/src/libthread/texec.c b/src/libthread/texec.c
deleted file mode 100644
index c9682e35..00000000
--- a/src/libthread/texec.c
+++ /dev/null
@@ -1,45 +0,0 @@
-#include <lib9.h>
-#include <thread.h>
-extern int _threaddebuglevel;
-
-void
-doexec(void *v)
-{
- int fd[3];
- char **argv = v;
-
- fd[0] = dup(0, -1);
- fd[1] = dup(1, -1);
- fd[2] = dup(2, -1);
- threadexec(nil, fd, argv[0], argv);
- print("exec failed: %r\n");
- sendp(threadwaitchan(), nil);
- threadexits(nil);
-}
-
-void
-threadmain(int argc, char **argv)
-{
- Channel *c;
- Waitmsg *w;
- int (*mk)(void(*)(void*), void*, uint);
-
- mk = threadcreate;
- ARGBEGIN{
- case 'D':
- _threaddebuglevel = ~0;
- break;
- case 'p':
- mk = proccreate;
- break;
- }ARGEND
-
- c = threadwaitchan();
- mk(doexec, argv, 8192);
- w = recvp(c);
- if(w == nil)
- print("exec/recvp failed: %r\n");
- else
- print("%d %lud %lud %lud %s\n", w->pid, w->time[0], w->time[1], w->time[2], w->msg);
- threadexits(nil);
-}
diff --git a/src/libthread/tfork.c b/src/libthread/tfork.c
deleted file mode 100644
index 0cbb4be9..00000000
--- a/src/libthread/tfork.c
+++ /dev/null
@@ -1,23 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <thread.h>
-
-Channel *c;
-
-void
-f(void *v)
-{
- recvp(c);
-}
-
-void
-threadmain(int argc, char **argv)
-{
- int i;
-
- c = chancreate(sizeof(ulong), 0);
- for(i=0;; i++){
- print("%d\n", i);
- proccreate(f, nil, 8192);
- }
-}
diff --git a/src/libthread/thread.c b/src/libthread/thread.c
new file mode 100644
index 00000000..69895181
--- /dev/null
+++ b/src/libthread/thread.c
@@ -0,0 +1,535 @@
+#include "u.h"
+#include <linux/unistd.h>
+#include "libc.h"
+#include "thread.h"
+#include "threadimpl.h"
+
+ _syscall0(pid_t,gettid)
+
+int _threaddebuglevel;
+
+static uint threadnproc;
+static uint threadnsysproc;
+static Lock threadnproclock;
+static Ref threadidref;
+
+static void addthread(_Threadlist*, _Thread*);
+static void delthread(_Threadlist*, _Thread*);
+static void addthreadinproc(Proc*, _Thread*);
+static void delthreadinproc(Proc*, _Thread*);
+static void contextswitch(Context *from, Context *to);
+static void scheduler(void*);
+
+static _Thread*
+getthreadnow(void)
+{
+ return proc()->thread;
+}
+_Thread *(*threadnow)(void) = getthreadnow;
+
+static Proc*
+procalloc(void)
+{
+ Proc *p;
+
+ p = malloc(sizeof *p);
+ memset(p, 0, sizeof *p);
+ lock(&threadnproclock);
+ threadnproc++;
+ unlock(&threadnproclock);
+ return p;
+}
+
+static void
+threadstart(void *v)
+{
+ _Thread *t;
+
+ t = v;
+ t->startfn(t->startarg);
+ _threadexit();
+}
+
+static _Thread*
+threadalloc(void (*fn)(void*), void *arg, uint stack)
+{
+ _Thread *t;
+ sigset_t zero;
+
+ /* allocate the task and stack together */
+ t = malloc(sizeof *t+stack);
+ memset(t, 0, sizeof *t);
+ t->stk = (uchar*)(t+1);
+ t->stksize = stack;
+ t->id = incref(&threadidref);
+ t->startfn = fn;
+ t->startarg = arg;
+
+ /* do a reasonable initialization */
+ memset(&t->context.uc, 0, sizeof t->context.uc);
+ sigemptyset(&zero);
+ sigprocmask(SIG_BLOCK, &zero, &t->context.uc.uc_sigmask);
+
+ /* on Linux makecontext neglects floating point */
+ getcontext(&t->context.uc);
+
+ /* call makecontext to do the real work. */
+ /* leave a few words open on both ends */
+ t->context.uc.uc_stack.ss_sp = t->stk+8;
+ t->context.uc.uc_stack.ss_size = t->stksize-16;
+ makecontext(&t->context.uc, (void(*)())threadstart, 1, t);
+
+ return t;
+}
+
+_Thread*
+_threadcreate(Proc *p, void (*fn)(void*), void *arg, uint stack)
+{
+ _Thread *t;
+
+ t = threadalloc(fn, arg, stack);
+ t->proc = p;
+ addthreadinproc(p, t);
+ p->nthread++;
+ _threadready(t);
+ return t;
+}
+
+int
+threadcreate(void (*fn)(void*), void *arg, uint stack)
+{
+ _Thread *t;
+
+ t = _threadcreate(proc(), fn, arg, stack);
+ return t->id;
+}
+
+int
+proccreate(void (*fn)(void*), void *arg, uint stack)
+{
+ _Thread *t;
+ Proc *p;
+
+ p = procalloc();
+//print("pa %p\n", p);
+ t = _threadcreate(p, fn, arg, stack);
+//print("ps %p\n", p);
+ _procstart(p, scheduler);
+ return t->id;
+}
+
+void
+_threadswitch(void)
+{
+ Proc *p;
+
+ p = proc();
+ contextswitch(&p->thread->context, &p->schedcontext);
+}
+
+void
+_threadready(_Thread *t)
+{
+ Proc *p;
+
+ p = t->proc;
+ lock(&p->lock);
+ addthread(&p->runqueue, t);
+ _procwakeup(&p->runrend);
+ unlock(&p->lock);
+}
+
+void
+threadyield(void)
+{
+ _threadready(proc()->thread);
+ _threadswitch();
+}
+
+void
+_threadexit(void)
+{
+ proc()->thread->exiting = 1;
+ _threadswitch();
+}
+
+void
+threadexits(char *msg)
+{
+/*
+ Proc *p;
+
+ p = proc();
+ utfecpy(p->msg, p->msg+sizeof p->msg, msg);
+*/
+ _threadexit();
+}
+
+void
+threadexitsall(char *msg)
+{
+ if(msg && msg[0])
+ exit(1);
+ exit(0);
+}
+
+static void
+contextswitch(Context *from, Context *to)
+{
+ if(swapcontext(&from->uc, &to->uc) < 0){
+ fprint(2, "swapcontext failed: %r\n");
+ assert(0);
+ }
+}
+
+static void
+scheduler(void *v)
+{
+ _Thread *t;
+ Proc *p;
+
+ p = v;
+ setproc(p);
+ print("s %p %d\n", p, gettid());
+ p->tid = pthread_self();
+ pthread_detach(p->tid);
+ lock(&p->lock);
+ for(;;){
+ while((t = p->runqueue.head) == nil){
+ if(p->nthread == 0)
+ goto Out;
+ p->runrend.l = &p->lock;
+ _procsleep(&p->runrend);
+ }
+ delthread(&p->runqueue, t);
+ unlock(&p->lock);
+ p->thread = t;
+ // print("run %s %d\n", t->name, t->id);
+ contextswitch(&p->schedcontext, &t->context);
+ p->thread = nil;
+ lock(&p->lock);
+ if(t->exiting){
+ delthreadinproc(p, t);
+ p->nthread--;
+ free(t);
+ }
+ }
+
+Out:
+ lock(&threadnproclock);
+ if(p->sysproc)
+ --threadnsysproc;
+ if(--threadnproc == threadnsysproc)
+ exit(0);
+ unlock(&threadnproclock);
+ unlock(&p->lock);
+ free(p);
+ setproc(0);
+ print("e %p (tid %d)\n", p, gettid());
+ pthread_exit(nil);
+}
+
+void
+_threadsetsysproc(void)
+{
+ lock(&threadnproclock);
+ if(++threadnsysproc == threadnproc)
+ exit(0);
+ unlock(&threadnproclock);
+ proc()->sysproc = 1;
+}
+
+/*
+ * debugging
+ */
+void
+threadsetname(char *fmt, ...)
+{
+ va_list arg;
+ _Thread *t;
+
+ t = proc()->thread;
+ va_start(arg, fmt);
+ vsnprint(t->name, sizeof t->name, fmt, arg);
+ va_end(arg);
+}
+
+void
+threadsetstate(char *fmt, ...)
+{
+ va_list arg;
+ _Thread *t;
+
+ t = proc()->thread;
+ va_start(arg, fmt);
+ vsnprint(t->state, sizeof t->name, fmt, arg);
+ va_end(arg);
+}
+
+/*
+ * locking
+ */
+static int
+threadqlock(QLock *l, int block, ulong pc)
+{
+ lock(&l->l);
+ if(l->owner == nil){
+ l->owner = (*threadnow)();
+//print("qlock %p @%#x by %p\n", l, pc, l->owner);
+ unlock(&l->l);
+ return 1;
+ }
+ if(!block){
+ unlock(&l->l);
+ return 0;
+ }
+//print("qsleep %p @%#x by %p\n", l, pc, (*threadnow)());
+ addthread(&l->waiting, (*threadnow)());
+ unlock(&l->l);
+
+ _threadswitch();
+
+ if(l->owner != (*threadnow)()){
+ fprint(2, "qlock pc=0x%lux owner=%p self=%p oops\n", pc, l->owner, (*threadnow)());
+ abort();
+ }
+//print("qlock wakeup %p @%#x by %p\n", l, pc, (*threadnow)());
+ return 1;
+}
+
+static void
+threadqunlock(QLock *l, ulong pc)
+{
+ lock(&l->l);
+//print("qlock unlock %p @%#x by %p (owner %p)\n", l, pc, (*threadnow)(), l->owner);
+ if(l->owner == nil){
+ fprint(2, "qunlock pc=0x%lux owner=%p self=%p oops\n",
+ pc, l->owner, (*threadnow)());
+ abort();
+ }
+ if((l->owner = l->waiting.head) != nil){
+ delthread(&l->waiting, l->owner);
+ _threadready(l->owner);
+ }
+ unlock(&l->l);
+}
+
+static int
+threadrlock(RWLock *l, int block, ulong pc)
+{
+ USED(pc);
+
+ lock(&l->l);
+ if(l->writer == nil && l->wwaiting.head == nil){
+ l->readers++;
+ unlock(&l->l);
+ return 1;
+ }
+ if(!block){
+ unlock(&l->l);
+ return 0;
+ }
+ addthread(&l->rwaiting, (*threadnow)());
+ unlock(&l->l);
+ _threadswitch();
+ return 1;
+}
+
+static int
+threadwlock(RWLock *l, int block, ulong pc)
+{
+ USED(pc);
+
+ lock(&l->l);
+ if(l->writer == nil && l->readers == 0){
+ l->writer = (*threadnow)();
+ unlock(&l->l);
+ return 1;
+ }
+ if(!block){
+ unlock(&l->l);
+ return 0;
+ }
+ addthread(&l->wwaiting, (*threadnow)());
+ unlock(&l->l);
+ _threadswitch();
+ return 1;
+}
+
+static void
+threadrunlock(RWLock *l, ulong pc)
+{
+ _Thread *t;
+
+ USED(pc);
+ lock(&l->l);
+ --l->readers;
+ if(l->readers == 0 && (t = l->wwaiting.head) != nil){
+ delthread(&l->wwaiting, t);
+ l->writer = t;
+ _threadready(t);
+ }
+ unlock(&l->l);
+}
+
+static void
+threadwunlock(RWLock *l, ulong pc)
+{
+ _Thread *t;
+
+ USED(pc);
+ lock(&l->l);
+ l->writer = nil;
+ assert(l->readers == 0);
+ while((t = l->rwaiting.head) != nil){
+ delthread(&l->rwaiting, t);
+ l->readers++;
+ _threadready(t);
+ }
+ if(l->readers == 0 && (t = l->wwaiting.head) != nil){
+ delthread(&l->wwaiting, t);
+ l->writer = t;
+ _threadready(t);
+ }
+ unlock(&l->l);
+}
+
+/*
+ * sleep and wakeup
+ */
+static void
+threadrsleep(Rendez *r, ulong pc)
+{
+ addthread(&r->waiting, proc()->thread);
+ qunlock(r->l);
+ _threadswitch();
+ qlock(r->l);
+}
+
+static int
+threadrwakeup(Rendez *r, int all, ulong pc)
+{
+ int i;
+ _Thread *t;
+
+ for(i=0;; i++){
+ if(i==1 && !all)
+ break;
+ if((t = r->waiting.head) == nil)
+ break;
+ delthread(&r->waiting, t);
+ _threadready(t);
+ }
+ return i;
+}
+
+/*
+ * hooray for linked lists
+ */
+static void
+addthread(_Threadlist *l, _Thread *t)
+{
+ if(l->tail){
+ l->tail->next = t;
+ t->prev = l->tail;
+ }else{
+ l->head = t;
+ t->prev = nil;
+ }
+ l->tail = t;
+ t->next = nil;
+}
+
+static void
+delthread(_Threadlist *l, _Thread *t)
+{
+ if(t->prev)
+ t->prev->next = t->next;
+ else
+ l->head = t->next;
+ if(t->next)
+ t->next->prev = t->prev;
+ else
+ l->tail = t->prev;
+}
+
+static void
+addthreadinproc(Proc *p, _Thread *t)
+{
+ _Threadlist *l;
+
+ l = &p->allthreads;
+ if(l->tail){
+ l->tail->allnext = t;
+ t->allprev = l->tail;
+ }else{
+ l->head = t;
+ t->allprev = nil;
+ }
+ l->tail = t;
+ t->allnext = nil;
+}
+
+static void
+delthreadinproc(Proc *p, _Thread *t)
+{
+ _Threadlist *l;
+
+ l = &p->allthreads;
+ if(t->allprev)
+ t->allprev->allnext = t->allnext;
+ else
+ l->head = t->allnext;
+ if(t->allnext)
+ t->allnext->allprev = t->allprev;
+ else
+ l->tail = t->allprev;
+}
+
+void**
+procdata(void)
+{
+ return &proc()->udata;
+}
+
+static int threadargc;
+static char **threadargv;
+int mainstacksize;
+
+static void
+threadmainstart(void *v)
+{
+ USED(v);
+ threadmain(threadargc, threadargv);
+}
+
+int
+main(int argc, char **argv)
+{
+ Proc *p;
+
+ threadargc = argc;
+ threadargv = argv;
+
+ /*
+ * Install locking routines into C library.
+ */
+ _lock = _threadlock;
+ _unlock = _threadunlock;
+ _qlock = threadqlock;
+ _qunlock = threadqunlock;
+ _rlock = threadrlock;
+ _runlock = threadrunlock;
+ _wlock = threadwlock;
+ _wunlock = threadwunlock;
+ _rsleep = threadrsleep;
+ _rwakeup = threadrwakeup;
+
+ pthreadinit();
+ p = procalloc();
+ if(mainstacksize == 0)
+ mainstacksize = 65536;
+ _threadcreate(p, threadmainstart, nil, mainstacksize);
+ scheduler(p);
+ return 0; /* not reached */
+}
diff --git a/src/libthread/thread.sh b/src/libthread/thread.sh
deleted file mode 100644
index 818b509f..00000000
--- a/src/libthread/thread.sh
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/sh
-
-if [ `uname` = Linux ]
-then
- case `uname -r` in
- 2.[6789]*)
- echo pthread
- ;;
- *)
- echo Linux-clone
- ;;
- esac
-else
- echo pthread
-fi
diff --git a/src/libthread/threadimpl.h b/src/libthread/threadimpl.h
deleted file mode 100644
index 0ad4568e..00000000
--- a/src/libthread/threadimpl.h
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * Some notes on locking:
- *
- * All the locking woes come from implementing
- * threadinterrupt (and threadkill).
- *
- * _threadgetproc()->thread is always a live pointer.
- * p->threads, p->ready, and _threadrgrp also contain
- * live thread pointers. These may only be consulted
- * while holding p->lock; in procs other than p, the
- * pointers are only guaranteed to be live while the lock
- * is still being held.
- *
- * Thread structures can only be freed by the proc
- * they belong to. Threads marked with t->inrendez
- * need to be extracted from the _threadrgrp before
- * being freed.
- */
-
-#include <u.h>
-#include <assert.h>
-#include <libc.h>
-#include <thread.h>
-#include "label.h"
-
-typedef struct Thread Thread;
-typedef struct Proc Proc;
-typedef struct Tqueue Tqueue;
-typedef struct Pqueue Pqueue;
-typedef struct Execargs Execargs;
-typedef struct Jmp Jmp;
-
-/* sync with ../lib9/notify.c */
-struct Jmp
-{
- p9jmp_buf b;
-};
-
-
-typedef enum
-{
- Dead,
- Running,
- Ready,
- Rendezvous,
-} State;
-
-typedef enum
-{
- Channone,
- Chanalt,
- Chansend,
- Chanrecv,
-} Chanstate;
-
-enum
-{
- NPRIV = 8,
-};
-
-struct Tqueue /* Thread queue */
-{
- int asleep;
- Thread *head;
- Thread *tail;
-};
-
-struct Pqueue { /* Proc queue */
- Lock lock;
- Proc *head;
- Proc **tail;
-};
-
-struct Thread
-{
- Lock lock; /* protects thread data structure */
-
- int asleep; /* thread is in _threadsleep */
- Label context; /* for context switches */
- int grp; /* thread group */
- Proc *homeproc; /* ``home'' proc */
- int id; /* thread id */
- int moribund; /* thread needs to die */
- char *name; /* name of thread */
- Thread *next; /* next on ready queue */
- Thread *nextt; /* next on list of threads in this proc */
- Proc *nextproc; /* next proc in which to run (rarely changes) */
- State nextstate; /* next run state */
- Proc *proc; /* proc of this thread */
- Thread *prevt; /* prev on list of threads in this proc */
- int ret; /* return value for Exec, Fork */
- State state; /* run state */
- uchar *stk; /* top of stack (lowest address of stack) */
- uint stksize; /* stack size */
- void* udata[NPRIV]; /* User per-thread data pointer */
-
- /*
- * for debugging only
- * (could go away without impacting correct behavior):
- */
-
- Channel *altc;
- _Procrend altrend;
-
- Chanstate chan; /* which channel operation is current */
- Alt *alt; /* pointer to current alt structure (debugging) */
- ulong userpc;
- Channel *c;
-
-};
-
-struct Execargs
-{
- char *prog;
- char **args;
- int fd[2];
- int *stdfd;
-};
-
-struct Proc
-{
- Lock lock;
-
- Label context; /* for context switches */
- Proc *link; /* in ptab */
- int splhi; /* delay notes */
- Thread *thread; /* running thread */
- Thread *idle; /* idle thread */
- int id;
- int procid;
-
- int needexec;
- Execargs exec; /* exec argument */
- Proc *newproc; /* fork argument */
- char exitstr[ERRMAX]; /* exit status */
-
- int internal;
- int rforkflag;
- int nthreads;
- Tqueue threads; /* All threads of this proc */
- Tqueue ready; /* Runnable threads */
- Lock readylock;
-
- int blocked; /* In a rendezvous */
- int pending; /* delayed note pending */
- int nonotes; /* delay notes */
- uint nextID; /* ID of most recently created thread */
- Proc *next; /* linked list of Procs */
-
- Jmp sigjmp; /* for notify implementation */
-
- void (*schedfn)(Proc*); /* function to call in scheduler */
-
- _Procrend rend; /* sleep here for more ready threads */
-
- void *arg; /* passed between shared and unshared stk */
- char str[ERRMAX]; /* used by threadexits to avoid malloc */
- char errbuf[ERRMAX]; /* errstr */
- Waitmsg *waitmsg;
-
- void* udata; /* User per-proc data pointer */
- int nsched;
-
- /*
- * for debugging only
- */
- int pid; /* process id */
- int pthreadid; /* pthread id */
-};
-
-void _swaplabel(Label*, Label*);
-Proc* _newproc(void);
-int _newthread(Proc*, void(*)(void*), void*, uint, char*, int);
-int _sched(void);
-int _schedexec(Execargs*);
-void _schedexecwait(void);
-void _schedexit(Proc*);
-int _schedfork(Proc*);
-void _threadfree(Thread*);
-void _threadscheduler(void*);
-void _systhreadinit(void);
-void _threadassert(char*);
-void __threaddebug(ulong, char*, ...);
-#define _threaddebug if(!_threaddebuglevel){}else __threaddebug
-void _threadexitsall(char*);
-Proc* _threadgetproc(void);
-extern void _threadmultiproc(void);
-Proc* _threaddelproc(void);
-void _kthreadinitproc(Proc*);
-void _threadsetproc(Proc*);
-void _threadinitstack(Thread*, void(*)(void*), void*);
-void _threadlinkmain(void);
-void* _threadmalloc(long, int);
-void _threadnote(void*, char*);
-void _threadready(Thread*);
-void _threadschednote(void);
-void _threadsetidle(int);
-void _threadsleep(_Procrend*);
-void _threadwakeup(_Procrend*);
-void _threadsignal(void);
-void _threadsysfatal(char*, va_list);
-long _xdec(long*);
-void _xinc(long*);
-void _threadremove(Proc*, Thread*);
-void threadstatus(void);
-void _threadefork(int[3], int[2], char*, char**);
-Jmp* _threadgetjmp(void);
-void _kthreadinit(void);
-void _kthreadsetproc(Proc*);
-Proc* _kthreadgetproc(void);
-void _kthreadstartproc(Proc*);
-void _kthreadexitproc(char*);
-void _kthreadexitallproc(char*);
-void _threadinternalproc(void);
-void _threadbackgroundinit(void);
-void _kmaininit(void);
-
-extern int _threadnprocs;
-extern int _threaddebuglevel;
-extern char* _threadexitsallstatus;
-extern Pqueue _threadpq;
-extern Channel* _threadwaitchan;
-
-#define DBGAPPL (1 << 0)
-#define DBGSCHED (1 << 16)
-#define DBGCHAN (1 << 17)
-#define DBGREND (1 << 18)
-/* #define DBGKILL (1 << 19) */
-#define DBGNOTE (1 << 20)
-#define DBGEXEC (1 << 21)
-
-extern void _threadmemset(void*, int, int);
-extern void _threaddebugmemset(void*, int, int);
-extern int _threadprocs;
-extern void _threadstacklimit(void*, void*);
-extern void _procdelthread(Proc*, Thread*);
-extern void _procaddthread(Proc*, Thread*);
-
-extern void _threadmaininit(void);
-extern int _threadexec(Channel*, int[3], char*, char*[], int);
-extern int _kthreadexec(Channel*, int[3], char*, char*[], int);
diff --git a/src/libthread/tprimes.c b/src/libthread/tprimes.c
deleted file mode 100644
index 89d30c03..00000000
--- a/src/libthread/tprimes.c
+++ /dev/null
@@ -1,68 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <thread.h>
-
-enum
-{
- STACK = 8192
-};
-
-int quiet;
-int goal;
-int buffer;
-int (*fn)(void(*)(void*), void*, uint) = threadcreate;
-
-void
-primethread(void *arg)
-{
- Channel *c, *nc;
- int p, i;
-
- c = arg;
- p = recvul(c);
- if(p > goal)
- threadexitsall(nil);
- if(!quiet)
- print("%d\n", p);
- nc = chancreate(sizeof(ulong), buffer);
- (*fn)(primethread, nc, STACK);
- for(;;){
- i = recvul(c);
- if(i%p)
- sendul(nc, i);
- }
-}
-
-extern int _threaddebuglevel;
-
-void
-threadmain(int argc, char **argv)
-{
- int i;
- Channel *c;
-
- ARGBEGIN{
- case 'D':
- _threaddebuglevel = atoi(ARGF());
- break;
- case 'q':
- quiet = 1;
- break;
- case 'b':
- buffer = atoi(ARGF());
- break;
- case 'p':
- fn = proccreate;
- break;
- }ARGEND
-
- if(argc>0)
- goal = atoi(argv[0]);
- else
- goal = 100;
-
- c = chancreate(sizeof(ulong), buffer);
- (*fn)(primethread, c, STACK);
- for(i=2;; i++)
- sendul(c, i);
-}
diff --git a/src/libthread/trend.c b/src/libthread/trend.c
deleted file mode 100644
index 1ccf1a79..00000000
--- a/src/libthread/trend.c
+++ /dev/null
@@ -1,31 +0,0 @@
-#include <lib9.h>
-#include <thread.h>
-
-Channel *c[3];
-
-
-void
-pingpong(void *v)
-{
- int n;
- Channel **c;
-
- c = v;
- do{
- n = recvul(c[0]);
- sendul(c[1], n-1);
- }while(n > 0);
- exit(0);
-}
-
-void
-threadmain(int argc, char **argv)
-{
- c[0] = chancreate(sizeof(ulong), 1);
- c[1] = chancreate(sizeof(ulong), 1);
- c[2] = c[0];
-
- proccreate(pingpong, c, 16384);
- threadcreate(pingpong, c+1, 16384);
- sendul(c[0], atoi(argv[1]));
-}
diff --git a/src/libthread/tsignal.c b/src/libthread/tsignal.c
deleted file mode 100644
index 9c64c46b..00000000
--- a/src/libthread/tsignal.c
+++ /dev/null
@@ -1,43 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <thread.h>
-
-extern int _threaddebuglevel;
-
-void
-usage(void)
-{
- fprint(2, "usage: tsignal [-[ednf] note]*\n");
- threadexitsall("usage");
-}
-
-void
-threadmain(int argc, char **argv)
-{
- Channel *c;
- char *msg;
-
- ARGBEGIN{
- case 'D':
- _threaddebuglevel = ~0;
- break;
- default:
- usage();
- case 'e':
- notifyenable(EARGF(usage()));
- break;
- case 'd':
- notifydisable(EARGF(usage()));
- break;
- case 'n':
- notifyon(EARGF(usage()));
- break;
- case 'f':
- notifyoff(EARGF(usage()));
- break;
- }ARGEND
-
- c = threadnotechan();
- while((msg = recvp(c)) != nil)
- print("note: %s\n", msg);
-}
diff --git a/src/libthread/ucontext.c b/src/libthread/ucontext.c
deleted file mode 100644
index 98e92ccf..00000000
--- a/src/libthread/ucontext.c
+++ /dev/null
@@ -1,49 +0,0 @@
-#include "threadimpl.h"
-
-static void
-launcher(void (*f)(void*), void *arg)
-{
- f(arg);
- threadexits(nil);
-}
-
-void
-_threadinitstack(Thread *t, void (*f)(void*), void *arg)
-{
- sigset_t zero;
-
- /* do a reasonable initialization */
- memset(&t->context.uc, 0, sizeof t->context.uc);
- sigemptyset(&zero);
- sigprocmask(SIG_BLOCK, &zero, &t->context.uc.uc_sigmask);
-
- /* call getcontext, because on Linux makecontext neglects floating point */
- getcontext(&t->context.uc);
-
- /* call makecontext to do the real work. */
- /* leave a few words open on both ends */
- t->context.uc.uc_stack.ss_sp = t->stk+8;
- t->context.uc.uc_stack.ss_size = t->stksize-16;
- makecontext(&t->context.uc, (void(*)())launcher, 2, f, arg);
-}
-
-void
-_threadinswitch(int enter)
-{
- USED(enter);
-}
-
-void
-_threadstacklimit(void *bottom, void *top)
-{
- USED(bottom);
- USED(top);
-}
-
-void
-_swaplabel(Label *old, Label *new)
-{
- if(swapcontext(&old->uc, &new->uc) < 0)
- sysfatal("swapcontext: %r");
-}
-