Fix small bugs.
diff --git a/include/thread.h b/include/thread.h
index 356d7b6..2721fb4 100644
--- a/include/thread.h
+++ b/include/thread.h
@@ -121,7 +121,7 @@
 int	tprivalloc(void);
 void	tprivfree(int);
 void	**tprivaddr(int);
-void		yield(void);
+int	yield(void);
 
 long		threadstack(void);
 
diff --git a/src/cmd/ls.C b/src/cmd/ls.C
index de2bee9..8bdeab6 100644
--- a/src/cmd/ls.C
+++ b/src/cmd/ls.C
@@ -101,6 +101,8 @@
 		return 1;
 	}
 	if(db->qid.type&QTDIR && dflag==0){
+		free(db);
+		db = nil;
 		output();
 		fd = open(s, OREAD);
 		if(fd == -1)
diff --git a/src/cmd/rc/plan9ish.c b/src/cmd/rc/plan9ish.c
index 2b9011c..6644778 100644
--- a/src/cmd/rc/plan9ish.c
+++ b/src/cmd/rc/plan9ish.c
@@ -71,7 +71,7 @@
 		for(s=*env;*s && *s!='(' && *s!='=';s++);
 		switch(*s){
 		case '\0':
-			pfmt(err, "rc: odd environment %q?\n", *env);
+		//	pfmt(err, "rc: odd environment %q?\n", *env);
 			break;
 		case '=':
 			*s='\0';
diff --git a/src/cmd/time.c b/src/cmd/time.c
index d82eaa9..3b52216 100644
--- a/src/cmd/time.c
+++ b/src/cmd/time.c
@@ -11,6 +11,7 @@
 {
 	int i;
 	Waitmsg *w;
+	vlong t0, t1;
 	long l;
 	char *p;
 	char err[ERRMAX];
@@ -20,6 +21,7 @@
 		exits("usage");
 	}
 
+	t0 = nsec();
 	switch(fork()){
 	case -1:
 		error("fork");
@@ -37,8 +39,9 @@
 
     loop:
 	w = wait();
+	t1 = nsec();
 	if(w == nil){
-		errstr(err, sizeof err);
+		rerrstr(err, sizeof err);
 		if(strcmp(err, "interrupted") == 0)
 			goto loop;
 		error("wait");
@@ -47,7 +50,7 @@
 	add("%ld.%.2ldu", l/1000, (l%1000)/10);
 	l = w->time[1];
 	add("%ld.%.2lds", l/1000, (l%1000)/10);
-	l = w->time[2];
+	l = (t1-t0)/1000000;
 	add("%ld.%.2ldr", l/1000, (l%1000)/10);
 	add("\t");
 	for(i=1; i<argc; i++){
diff --git a/src/lib9/notify.c b/src/lib9/notify.c
index 79a5e62..26487ba 100644
--- a/src/lib9/notify.c
+++ b/src/lib9/notify.c
@@ -66,7 +66,7 @@
 notify(void (*f)(void*, char*))
 {
 	int i;
-	struct sigaction sa;
+	struct sigaction sa, osa;
 
 	_p9uproc(0);
 	memset(&sa, 0, sizeof sa);
@@ -77,11 +77,22 @@
 		sa.sa_handler = notifysigf;
 	}
 	for(i=0; i<nelem(sigs); i++){
+		/*
+		 * If someone has already installed a handler,
+		 * It's probably some ld preload nonsense,
+		 * like pct (a SIGVTALRM-based profiler).
+		 * Leave it alone.
+		 */
+		sigaction(sigs[i].sig, nil, &osa);
+		if(osa.sa_handler != SIG_DFL)
+			continue;
+		sigemptyset(&sa.sa_mask);
+		sigaddset(&sa.sa_mask, i);
 		if(sigs[i].restart)
 			sa.sa_flags |= SA_RESTART;
 		else
 			sa.sa_flags &= ~SA_RESTART;
-		sigaction(sigs[i].sig, &sa, 0);
+		sigaction(sigs[i].sig, &sa, nil);
 	}
 	return 0;
 }
diff --git a/src/libthread/386.c b/src/libthread/386.c
index d8052f0..2c611e4 100644
--- a/src/libthread/386.c
+++ b/src/libthread/386.c
@@ -15,7 +15,7 @@
 
 	p = _threadgetproc();
 	t = p->thread;
-	_threadstacklimit(t->stk);
+	_threadstacklimit(t->stk, t->stk+t->stksize);
 
 	(*f)(arg);
 	threadexits(nil);
@@ -39,18 +39,19 @@
 	USED(enter);
 #ifdef USEVALGRIND
 	if(enter)
-		VALGRIND_SET_STACK_LIMIT(0, 0, 1);
-	else
 		VALGRIND_SET_STACK_LIMIT(0, 0, 0);
+	else
+		VALGRIND_SET_STACK_LIMIT(0, 0, 1);
 #endif
 }
 
 void
-_threadstacklimit(void *addr)
+_threadstacklimit(void *bottom, void *top)
 {
-	USED(addr);
+	USED(bottom);
+	USED(top);
 
 #ifdef USEVALGRIND
-	VALGRIND_SET_STACK_LIMIT(1, addr, 0);
+	VALGRIND_SET_STACK_LIMIT(1, bottom, top);
 #endif
 }
diff --git a/src/libthread/PowerMacintosh.c b/src/libthread/PowerMacintosh.c
index 21f6041..94d4db9 100644
--- a/src/libthread/PowerMacintosh.c
+++ b/src/libthread/PowerMacintosh.c
@@ -32,7 +32,7 @@
 }
 
 void
-_threadstacklimit(void *addr)
+_threadstacklimit(void *addr, void *addr2)
 {
 	USED(addr);
 }
diff --git a/src/libthread/create.c b/src/libthread/create.c
index b63fee4..f5f0d6c 100644
--- a/src/libthread/create.c
+++ b/src/libthread/create.c
@@ -24,6 +24,7 @@
 	if(stacksize < 32)
 		sysfatal("bad stacksize %d", stacksize);
 	t = _threadmalloc(sizeof(Thread), 1);
+	t->lastfd = -1;
 	s = _threadmalloc(stacksize, 0);
 	t->stk = (uchar*)s;
 	t->stksize = stacksize;
diff --git a/src/libthread/fdwait.c b/src/libthread/fdwait.c
index 927fc64..a689033 100644
--- a/src/libthread/fdwait.c
+++ b/src/libthread/fdwait.c
@@ -2,12 +2,13 @@
 #include <u.h>
 #include <libc.h>
 #include <thread.h>
-
+#include "threadimpl.h"
 #include <errno.h>
 #include <unistd.h>
 #include <fcntl.h>
 
 #define debugpoll 0
+static int noblocked[4096/32];
 
 #ifdef __APPLE__
 #include <sys/time.h>
@@ -174,11 +175,15 @@
 
 	struct {
 		Channel c;
+		Alt *qentry[2];
 		ulong x;
 	} 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;
@@ -223,7 +228,25 @@
 void
 threadfdnoblock(int fd)
 {
+	Thread *t;
+
+	if(fd<0)
+		return;
+	if(fd < 8*sizeof(int)*nelem(noblocked)
+	&& (noblocked[fd/(8*sizeof(int))] & (1<<(fd%(8*sizeof(int))))))
+		return;
+	t = _threadgetproc()->thread;
+	if(t && t->lastfd == fd)
+		return;
 	fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0)|O_NONBLOCK);
+	if(t)
+		t->lastfd = fd;
+
+	/* We could lock this but we're probably single-threaded
+	 * and the worst that will happen is we'll run fcntl
+	 * a few more times.
+	 */
+	noblocked[fd/(8*sizeof(int))] |= 1<<(fd%(8*sizeof(int)));
 }
 
 long
diff --git a/src/libthread/main.c b/src/libthread/main.c
index 04e6cd9..bc7ad0f 100644
--- a/src/libthread/main.c
+++ b/src/libthread/main.c
@@ -32,24 +32,12 @@
 		exit(_threadexitsallstatus[0] ? 1 : 0);
 }
 
-static void
-_nop(int x)
-{
-	USED(x);
-}
-
 int
 main(int argc, char **argv)
 {
 	Mainarg *a;
 	Proc *p;
 
-	signal(SIGTERM, _threaddie);
-	signal(SIGCHLD, _nop);
-	signal(SIGALRM, _nop);
-//	signal(SIGINFO, _threadstatus);
-//	rfork(RFREND);
-
 //_threaddebuglevel = (DBGSCHED|DBGCHAN|DBGREND)^~0;
 	_systhreadinit();
 	_qlockinit(_threadrendezvous);
diff --git a/src/libthread/mkfile b/src/libthread/mkfile
index 1ced902..f8ec8e8 100644
--- a/src/libthread/mkfile
+++ b/src/libthread/mkfile
@@ -59,6 +59,7 @@
 
 # sorry
 VG=`test -d /home/rsc/pub/valgrind-debian && echo -DUSEVALGRIND`
+# VG=
 
 CFLAGS=$CFLAGS $VG
 
diff --git a/src/libthread/sched.c b/src/libthread/sched.c
index 9ad7298..bdb9ad6 100644
--- a/src/libthread/sched.c
+++ b/src/libthread/sched.c
@@ -171,7 +171,7 @@
 	}
 }
 
-void
+int
 _sched(void)
 {
 	Proc *p;
@@ -186,8 +186,8 @@
 	//		psstate(t->state), &t->sched, &p->sched);
 		if(_setlabel(&t->sched)==0)
 			_gotolabel(&p->sched);
-		_threadstacklimit(t->stk);
-		return;
+		_threadstacklimit(t->stk, t->stk+t->stksize);
+		return p->nsched++;
 	}else{
 		t = runthread(p);
 		if(t == nil){
@@ -277,10 +277,15 @@
 	unlock(&p->readylock);
 }
 
-void
+int
 yield(void)
 {
-	_sched();
+	Proc *p;
+	int nsched;
+
+	p = _threadgetproc();
+	nsched = p->nsched;
+	return _sched() - nsched;
 }
 
 void
diff --git a/src/libthread/sun4u.c b/src/libthread/sun4u.c
index 6312dac..0d2d8d2 100644
--- a/src/libthread/sun4u.c
+++ b/src/libthread/sun4u.c
@@ -46,7 +46,7 @@
 }
 
 void
-_threadstacklimit(void *addr)
+_threadstacklimit(void *addr, void *addr2)
 {
 	USED(addr);
 }
diff --git a/src/libthread/threadimpl.h b/src/libthread/threadimpl.h
index 373164a..7e44e64 100644
--- a/src/libthread/threadimpl.h
+++ b/src/libthread/threadimpl.h
@@ -99,6 +99,7 @@
 	ulong		userpc;
 
 	void*	udata[NPRIV];	/* User per-thread data pointer */
+	int		lastfd;
 };
 
 struct Execargs
@@ -143,6 +144,7 @@
 	Waitmsg		*waitmsg;
 
 	void*	udata;		/* User per-proc data pointer */
+	int		nsched;
 };
 
 struct Pqueue {		/* Proc queue */
@@ -169,7 +171,7 @@
 Proc*	_newproc(void(*)(void*), void*, uint, char*, int, int);
 int		_procsplhi(void);
 void		_procsplx(int);
-void		_sched(void);
+int		_sched(void);
 int		_schedexec(Execargs*);
 void		_schedexecwait(void);
 void		_schedexit(Proc*);
@@ -219,4 +221,4 @@
 extern void _threadmemset(void*, int, int);
 extern void _threaddebugmemset(void*, int, int);
 extern int _threadprocs;
-extern void _threadstacklimit(void*);
+extern void _threadstacklimit(void*, void*);