make -> mk

remove clumsy stack hack.
fix exec.
fix nthreads maintenance.
fix threadexitsall not to kill self.
add sun support.
diff --git a/src/libthread/Makefile b/src/libthread/Makefile
deleted file mode 100644
index 654c031..0000000
--- a/src/libthread/Makefile
+++ /dev/null
@@ -1,52 +0,0 @@
-PLAN9=../..
-include $(PLAN9)/src/Makehdr
-
-LIB=libthread.a
-
-OFILES=\
-	$(OBJTYPE).$O\
-	asm-$(SYSNAME)-$(OBJTYPE).$O\
-	channel.$O\
-	chanprint.$O\
-	create.$O\
-	debug.$O\
-	exec-unix.$O\
-	exit.$O\
-	getpid.$O\
-	id.$O\
-	iocall.$O\
-	ioclose.$O\
-	ioopen.$O\
-	ioproc.$O\
-	ioread.$O\
-	ioreadn.$O\
-	iowrite.$O\
-	kill.$O\
-	lib.$O\
-	main.$O\
-	memset.$O\
-	memsetd.$O\
-	note.$O\
-	proctab.$O\
-	ref.$O\
-	rendez.$O\
-	sched.$O\
-
-HFILES=\
-	$(PLAN9)/include/thread.h\
-	label.h\
-	threadimpl.h\
-
-include $(PLAN9)/src/Makesyslib
-
-tprimes: tprimes.$O $(PLAN9)/lib/$(LIB)
-	$(LD) -o tprimes tprimes.$O $(LDFLAGS) -lthread -l9 -lfmt -lutf
-
-texec: texec.$O $(PLAN9)/lib/$(LIB)
-	$(LD) -o texec texec.$O $(LDFLAGS) -lthread -l9 -lfmt -lutf
-
-trend: trend.$O $(PLAN9)/lib/$(LIB)
-	$(LD) -o trend trend.$O $(LDFLAGS) -lthread -l9 -lfmt -lutf
-
-CLEANFILES+=tprimes texec
-
diff --git a/src/libthread/create.c b/src/libthread/create.c
index 49e1572..6a44c24 100644
--- a/src/libthread/create.c
+++ b/src/libthread/create.c
@@ -7,54 +7,10 @@
 /*
  * Create and initialize a new Thread structure attached to a given proc.
  */
-
-typedef struct Stack Stack;
-struct Stack {
-	ulong magic;
-	Thread *thr;
-	Stack *next;
-	uchar buf[STKSIZE-12];
-};
-
-static Stack *stkfree;
-static Lock stklock;
-
 void
 _stackfree(void *v)
 {
-	Stack *s;
-
-	s = v;
-	lock(&stklock);
-	s->thr = nil;
-	s->magic = 0;
-	s->next = stkfree;
-	stkfree = s;
-	unlock(&stklock);
-}
-
-static Stack*
-stackalloc(void)
-{
-	char *buf;
-	Stack *s;
-	int i;
-
-	lock(&stklock);
-	while(stkfree == nil){
-		unlock(&stklock);
-		assert(STKSIZE == sizeof(Stack));
-		buf = malloc(STKSIZE+128*STKSIZE);
-		s = (Stack*)(((ulong)buf+STKSIZE)&~(STKSIZE-1));
-		for(i=0; i<128; i++)
-			_stackfree(&s[i]);
-		lock(&stklock);
-	}
-	s = stkfree;
-	stkfree = stkfree->next;
-	unlock(&stklock);
-	s->magic = STKMAGIC;
-	return s;
+	free(v);
 }
 
 static int
@@ -62,16 +18,15 @@
 {
 	int id;
 	Thread *t;
-	Stack *s;
+	char *s;
 
 	if(stacksize < 32)
 		sysfatal("bad stacksize %d", stacksize);
 	t = _threadmalloc(sizeof(Thread), 1);
-	s = stackalloc();
-	s->thr = t;
+	s = _threadmalloc(stacksize, 0);
 	t->stk = (char*)s;
-	t->stksize = STKSIZE;
-	_threaddebugmemset(s->buf, 0xFE, sizeof s->buf);
+	t->stksize = stacksize;
+	_threaddebugmemset(s, 0xFE, stacksize);
 	_threadinitstack(t, f, arg);
 	t->proc = p;
 	t->grp = grp;
@@ -138,7 +93,7 @@
 		if(t->cmdname)
 			free(t->cmdname);
 		assert(t->stk != nil);
-		_stackfree((Stack*)t->stk);
+		_stackfree(t->stk);
 		nextt = t->nextt;
 		free(t);
 	}
diff --git a/src/libthread/exec-unix.c b/src/libthread/exec-unix.c
index 5a37e34..6e4f728 100644
--- a/src/libthread/exec-unix.c
+++ b/src/libthread/exec-unix.c
@@ -9,11 +9,13 @@
 	Proc *p;
 	Thread *t;
 
+print("procexec\n");
 	_threaddebug(DBGEXEC, "procexec %s", prog);
 	/* must be only thread in proc */
 	p = _threadgetproc();
 	t = p->thread;
 	if(p->threads.head != t || p->threads.head->nextt != nil){
+print("not only thread\n");
 		werrstr("not only thread in proc");
 	Bad:
 		if(pidc)
@@ -34,26 +36,35 @@
 	 * pipe to us.
 	 */
 	if(pipe(p->exec.fd) < 0)
+{
+print("pipe\n");
 		goto Bad;
+}
 	if(fcntl(p->exec.fd[1], F_SETFD, 1) < 0)
+{
+print("fcntl\n");
 		goto Bad;
+}
 
 	/* exec in parallel via the scheduler */
 	assert(p->needexec==0);
 	p->exec.prog = prog;
 	p->exec.args = args;
 	p->needexec = 1;
+print("sched\n");
 	_sched();
 
 	close(p->exec.fd[1]);
 	if((n = read(p->exec.fd[0], p->exitstr, ERRMAX-1)) > 0){	/* exec failed */
 		p->exitstr[n] = '\0';
+print("read got %s\n", p->exitstr);
 		errstr(p->exitstr, ERRMAX);
 		close(p->exec.fd[0]);
 		goto Bad;
 	}
 	close(p->exec.fd[0]);
 
+print("exec %d\n", pidc);
 	if(pidc)
 		sendul(pidc, t->ret);
 
diff --git a/src/libthread/exit.c b/src/libthread/exit.c
index ddf7001..511e5bc 100644
--- a/src/libthread/exit.c
+++ b/src/libthread/exit.c
@@ -1,5 +1,5 @@
-#include "threadimpl.h"
 #include <signal.h>
+#include "threadimpl.h"
 
 char *_threadexitsallstatus;
 Channel *_threadwaitchan;
@@ -13,6 +13,7 @@
 	p = _threadgetproc();
 	t = p->thread;
 	t->moribund = 1;
+	_threaddebug(DBGSCHED, "threadexits %s", exitstr);
 	if(exitstr==nil)
 		exitstr="";
 	utfecpy(p->exitstr, p->exitstr+ERRMAX, exitstr);
@@ -26,6 +27,7 @@
 	int *pid;
 	int i, npid, mypid;
 
+	_threaddebug(DBGSCHED, "threadexitsall %s", exitstr);
 	if(exitstr == nil)
 		exitstr = "";
 	_threadexitsallstatus = exitstr;
@@ -34,7 +36,7 @@
 
 	/*
 	 * signal others.
-	 * copying all the pids first avoids other threads
+	 * copying all the pids first avoids other thread's
 	 * teardown procedures getting in the way.
 	 */
 	lock(&_threadpq.lock);
@@ -46,9 +48,13 @@
 	for(p = _threadpq.head; p; p=p->next)
 		pid[npid++] = p->pid;
 	unlock(&_threadpq.lock);
-	for(i=0; i<npid; i++)
-		if(pid[i] != mypid)
+	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);
+	}
 
 	/* leave */
 	exit(0);
diff --git a/src/libthread/kill.c b/src/libthread/kill.c
index a9392ea..31dc3d5 100644
--- a/src/libthread/kill.c
+++ b/src/libthread/kill.c
@@ -1,5 +1,5 @@
-#include "threadimpl.h"
 #include <signal.h>
+#include "threadimpl.h"
 
 static void tinterrupt(Proc*, Thread*);
 
diff --git a/src/libthread/label.h b/src/libthread/label.h
index a1f6fa5..874fb07 100644
--- a/src/libthread/label.h
+++ b/src/libthread/label.h
@@ -32,6 +32,14 @@
 //	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 */
+};
 #else
 #error "Unknown or unsupported architecture"
 #endif
diff --git a/src/libthread/main.c b/src/libthread/main.c
index 1acd834..06c1293 100644
--- a/src/libthread/main.c
+++ b/src/libthread/main.c
@@ -1,5 +1,5 @@
-#include "threadimpl.h"
 #include <signal.h>
+#include "threadimpl.h"
 
 typedef struct Mainarg Mainarg;
 struct Mainarg
@@ -74,7 +74,13 @@
 int
 _schedfork(Proc *p)
 {
-	return ffork(RFMEM|RFNOWAIT, _schedinit, p);
+	int pid;
+	lock(&p->lock);
+	pid = ffork(RFMEM|RFNOWAIT, _schedinit, p);
+	p->pid = pid;
+	unlock(&p->lock);
+	return pid;
+	
 }
 
 void
diff --git a/src/libthread/mkfile b/src/libthread/mkfile
new file mode 100644
index 0000000..739aaf8
--- /dev/null
+++ b/src/libthread/mkfile
@@ -0,0 +1,52 @@
+PLAN9=../..
+<$PLAN9/src/mkhdr
+
+LIB=libthread.a
+
+OFILES=\
+	$OBJTYPE.$O\
+	asm-$SYSNAME-$OBJTYPE.$O\
+	channel.$O\
+	chanprint.$O\
+	create.$O\
+	debug.$O\
+	exec-unix.$O\
+	exit.$O\
+	getpid.$O\
+	id.$O\
+	iocall.$O\
+	ioclose.$O\
+	ioopen.$O\
+	ioproc.$O\
+	ioread.$O\
+	ioreadn.$O\
+	iowrite.$O\
+	kill.$O\
+	lib.$O\
+	main.$O\
+	memset.$O\
+	memsetd.$O\
+	note.$O\
+	proctab.$O\
+	ref.$O\
+	rendez.$O\
+	sched.$O\
+
+HFILES=\
+	$PLAN9/include/thread.h\
+	label.h\
+	threadimpl.h\
+
+<$PLAN9/src/mksyslib
+
+tprimes: tprimes.$O $PLAN9/lib/$LIB
+	$LD -o tprimes tprimes.$O $LDFLAGS -lthread -l9 -lfmt -lutf
+
+texec: texec.$O $PLAN9/lib/$LIB
+	$LD -o texec texec.$O $LDFLAGS -lthread -l9 -lfmt -lutf
+
+trend: trend.$O $PLAN9/lib/$LIB
+	$LD -o trend trend.$O $LDFLAGS -lthread -l9 -lfmt -lutf
+
+CLEANFILES=$CLEANFILES tprimes texec
+
diff --git a/src/libthread/sched.c b/src/libthread/sched.c
index 8609833..9ac2241 100644
--- a/src/libthread/sched.c
+++ b/src/libthread/sched.c
@@ -1,5 +1,5 @@
-#include "threadimpl.h"
 #include <signal.h>
+#include "threadimpl.h"
 
 //static Thread	*runthread(Proc*);
 
@@ -27,11 +27,11 @@
 	ignusr1();
 	signal(SIGTERM, _threaddie);
   
-
-
 	p = arg;
+	lock(&p->lock);
 	p->pid = _threadgetpid();
 	_threadsetproc(p);
+	unlock(&p->lock);
 	while(_setlabel(&p->sched))
 		;
 	_threaddebug(DBGSCHED, "top of schedinit, _threadexitsallstatus=%p", _threadexitsallstatus);
@@ -59,6 +59,7 @@
 			_stackfree(t->stk);
 			free(t->cmdname);
 			free(t);	/* XXX how do we know there are no references? */
+			p->nthreads--;
 			t = nil;
 			_sched();
 		}
@@ -94,7 +95,7 @@
 	lock(&p->readylock);
 	if(q->head == nil){
 		q->asleep = 1;
-		_threaddebug(DBGSCHED, "sleeping for more work");
+		_threaddebug(DBGSCHED, "sleeping for more work (%d threads)", p->nthreads);
 		unlock(&p->readylock);
 		while(rendezvous((ulong)q, 0) == ~0){
 			if(_threadexitsallstatus)
@@ -173,6 +174,7 @@
 		q->tail->next = t;
 	q->tail = t;
 	if(q->asleep){
+		assert(q->asleep == 1);
 		q->asleep = 0;
 		/* lock passes to runthread */
 		_threaddebug(DBGSCHED, "waking process %d", t->proc->pid);
diff --git a/src/libthread/texec.c b/src/libthread/texec.c
index 9ba8682..87c3f77 100644
--- a/src/libthread/texec.c
+++ b/src/libthread/texec.c
@@ -7,6 +7,7 @@
 {
 	char **argv = v;
 
+print("doexec\n");
 	procexec(nil, argv[0], argv);
 	sendp(threadwaitchan(), nil);
 }
@@ -27,8 +28,8 @@
 	proccreate(doexec, argv, 8192);
 	w = recvp(c);
 	if(w == nil)
-		print("exec failed\n");
+		print("exec failed: %r\n");
 	else
-		print("%d %lu %lu %lu %s\n", w->pid, w->time[0], w->time[1], w->time[2], w->msg);
+		print("%d %lud %lud %lud %s\n", w->pid, w->time[0], w->time[1], w->time[2], w->msg);
 	threadexits(nil);
 }