better exec handling
diff --git a/src/libthread/Linux.c b/src/libthread/Linux.c
index d6d31af..357e926 100644
--- a/src/libthread/Linux.c
+++ b/src/libthread/Linux.c
@@ -99,13 +99,15 @@
 	sigdelset(&mask, SIGUSR1);
 	sigsuspend(&mask);
 
+//print("%d %d awake again\n", time(0), getpid());
+
 	/*
 	 * We're awake.  Make USR1 not interrupt system calls.
 	 */
 	lock(r->l);
 	ignusr1(1);
 	if(r->asleep && r->pid == getpid()){
-print("resleep %d\n", getpid());
+//print("resleep %d\n", getpid());
 		/* Didn't really wake up - signal from something else */
 		goto again;
 	}
@@ -266,35 +268,6 @@
 }
 
 /*
- * exec - need to arrange for wait proc to run
- * the execs so it gets the wait messages
- */
-int
-_runthreadspawn(int *fd, char *cmd, char **argv)
-{
-	Execjob e;
-	int pid;
-
-	e.fd = fd;
-	e.cmd = cmd;
-	e.argv = argv;
-	e.c = chancreate(sizeof(ulong), 0);	
-print("%d run\n", time(0));
-	qlock(&_threadexeclock);
-	sendp(_threadexecchan, &e);
-print("%d sent\n", time(0));
-	while(_threadexecproc == nil)
-		yield();
-	kill(_threadexecproc->osprocid, SIGUSR2);
-print("%d killed\n", time(0));
-	pid = recvul(e.c);
-	qunlock(&_threadexeclock);
-print("%d ran\n", time(0));
-	return pid;
-}
-
-
-/*
  * per-process data, indexed by pid
  *
  * could use modify_ldt and a segment register
diff --git a/src/libthread/exec.c b/src/libthread/exec.c
index dfdb71b..6a7ca1d 100644
--- a/src/libthread/exec.c
+++ b/src/libthread/exec.c
@@ -6,41 +6,42 @@
 
 static Lock thewaitlock;
 static Channel *thewaitchan;
-Channel	*_dowaitchan;
-Channel	*_threadexecchan;
-Proc	*_threadexecproc;
-QLock	_threadexeclock;
 
 static void
-execthread(void *v)
+execproc(void *v)
 {
-	Execjob *e;
-
-	USED(v);
-	while((e = recvp(_threadexecchan)) != nil){
-print("%d doexec pid %d\n", time(0), getpid());
-		sendul(e->c, _threadspawn(e->fd, e->cmd, e->argv));
-	}
-}
-
-static void
-waitproc(void *v)
-{
+	int pid;
 	Channel *c;
+	Execjob *e;
 	Waitmsg *w;
 
-	_threadsetsysproc();
-	_threadexecproc = proc();
-	threadcreate(execthread, nil, 65536);
-	for(;;){
-		while((w = wait()) == nil)
-			if(errno == ECHILD)
-				recvul(_dowaitchan);
+	e = v;
+	pid = _threadspawn(e->fd, e->cmd, e->argv);
+	sendul(e->c, pid);
+	if(pid > 0){
+		w = waitfor(pid);
 		if((c = thewaitchan) != nil)
 			sendp(c, w);
 		else
 			free(w);
 	}
+	threadexits(nil);
+}
+
+int
+_runthreadspawn(int *fd, char *cmd, char **argv)
+{
+	int pid;
+	Execjob e;
+
+	e.fd = fd;
+	e.cmd = cmd;
+	e.argv = argv;
+	e.c = chancreate(sizeof(void*), 0);
+	proccreate(execproc, &e, 65536);
+	pid = recvul(e.c);
+	chanfree(e.c);
+	return pid;
 }
 
 Channel*
@@ -104,28 +105,15 @@
 		close(fd[1]);
 	if(fd[2] != fd[1] && fd[2] != fd[0])
 		close(fd[2]);
-	channbsendul(_dowaitchan, 1);
 	return pid;
 }
 
 int
 threadspawn(int fd[3], char *cmd, char *argv[])
 {
-	if(_dowaitchan == nil){
-		lock(&thewaitlock);
-		if(_dowaitchan == nil){
-			_dowaitchan = chancreate(sizeof(ulong), 1);
-			chansetname(_dowaitchan, "dowaitchan");
-			_threadexecchan = chancreate(sizeof(void*), 1);
-			chansetname(_threadexecchan, "execchan");
-			proccreate(waitproc, nil, STACK);
-		}
-		unlock(&thewaitlock);
-	}
 	return _runthreadspawn(fd, cmd, argv);
 }
 
-
 int
 _threadexec(Channel *cpid, int fd[3], char *cmd, char *argv[])
 {
diff --git a/src/libthread/pthread.c b/src/libthread/pthread.c
index e1fed2b..2ddd8c7 100644
--- a/src/libthread/pthread.c
+++ b/src/libthread/pthread.c
@@ -130,9 +130,3 @@
 	pthread_key_create(&prockey, 0);
 }
 
-int
-_runthreadspawn(int *fd, char *cmd, char **argv)
-{
-	return _threadspawn(fd, cmd, argv);
-}
-
diff --git a/src/libthread/thread.c b/src/libthread/thread.c
index 8f838b6..1837e7d 100644
--- a/src/libthread/thread.c
+++ b/src/libthread/thread.c
@@ -138,15 +138,23 @@
 	p = t->proc;
 	lock(&p->lock);
 	addthread(&p->runqueue, t);
-	_procwakeup(&p->runrend);
+//print("%d wake for job %d->%d\n", time(0), getpid(), p->osprocid);
+	if(p != proc())
+		_procwakeup(&p->runrend);
 	unlock(&p->lock);
 }
 
-void
+int
 threadyield(void)
 {
-	_threadready(proc()->thread);
+	int n;
+	Proc *p;
+
+	p = proc();
+	n = p->nswitch;
+	_threadready(p->thread);
 	_threadswitch();
+	return p->nswitch - n;
 }
 
 void
@@ -184,13 +192,14 @@
 			if(p->nthread == 0)
 				goto Out;
 			p->runrend.l = &p->lock;
-print("sleep for jobs %d\n", getpid());
+//print("%d sleep for jobs %d\n", time(0), getpid());
 			_procsleep(&p->runrend);
-print("wake from jobs %d\n", getpid());
+//print("%d wake from jobs %d\n", time(0), getpid());
 		}
 		delthread(&p->runqueue, t);
 		unlock(&p->lock);
 		p->thread = t;
+		p->nswitch++;
 		// print("run %s %d\n", t->name, t->id);
 		contextswitch(&p->schedcontext, &t->context);
 		p->thread = nil;
diff --git a/src/libthread/threadimpl.h b/src/libthread/threadimpl.h
index 6bc8cbf..164ba97 100644
--- a/src/libthread/threadimpl.h
+++ b/src/libthread/threadimpl.h
@@ -74,6 +74,7 @@
 	uint		osprocid;
 #endif
 	Lock		lock;
+	int			nswitch;
 	_Thread		*thread;
 	_Threadlist	runqueue;
 	_Threadlist	allthreads;