Browse Source

Plan 9 from Bell Labs 2013-09-18

David du Colombier 10 years ago
parent
commit
0da3f6b4a7

+ 0 - 1
acme/mail/src/dat.h

@@ -118,7 +118,6 @@ extern	void		rewritembox(Window*, Message*);
 
 extern	void		mkreply(Message*, char*, char*, Plumbattr*, char*);
 extern	void		delreply(Message*);
-extern	int		write2(int, int, char*, int, int);
 
 extern	int		mesgadd(Message*, char*, Dir*, char*);
 extern	void		mesgmenu(Window*, Message*);

+ 7 - 7
acme/mail/src/mesg.c

@@ -571,10 +571,12 @@ mesgsave(Message *m, char *s)
 	}
 	free(t);
 
-	all = emalloc(n+2);
-	memmove(all, raw, n);
-	memmove(all+n, "\n", 1);
-	n++;
+	all = emalloc(k+n+1);
+	memmove(all, unixheader, k);
+	memmove(all+k, raw, n);
+	memmove(all+k+n, "\n", 1);
+	n += k+1;
+	free(unixheader);
 	free(raw);
 	ret = 1;
 	s = estrdup(s);
@@ -584,12 +586,10 @@ mesgsave(Message *m, char *s)
 	if(ofd < 0){
 		fprint(2, "Mail: can't open %s: %r\n", s);
 		ret = 0;
-	}else if(seek(ofd, 0LL, 2) < 0 || write(ofd, unixheader, k) != k ||
-	    write2(-1, ofd, all, n, 1) < n){
+	}else if(seek(ofd, 0LL, 2)<0 || write(ofd, all, n)!=n){
 		fprint(2, "Mail: save failed: can't write %s: %r\n", s);
 		ret = 0;
 	}
-	free(unixheader);
 	free(all);
 	close(ofd);
 	free(s);

+ 2 - 0
sys/include/ape/stddef.h

@@ -8,7 +8,9 @@
 #define NULL ((void*)0)
 #endif
 #endif
+#ifndef offsetof
 #define offsetof(ty,mem) ((size_t) &(((ty *)0)->mem))
+#endif
 
 typedef long ptrdiff_t;
 #ifndef _SIZE_T

+ 12 - 0
sys/src/9/bcm/etherusb.c

@@ -414,10 +414,22 @@ etherusbpnp(Ether* edev)
 	edev->ctlr = ctlr;
 	edev->irq = -1;
 	edev->mbps = 100;	/* TODO: get this from usbether */
+
+	/*
+	 * Linkage to the generic ethernet driver.
+	 */
 	edev->attach = etherusbattach;
 	edev->transmit = etherusbtransmit;
+	edev->interrupt = nil;
 	edev->ifstat = etherusbifstat;
 	edev->ctl = etherusbctl;
+
+	edev->arg = edev;
+	/* TODO: promiscuous, multicast (for ipv6), shutdown (for reboot) */
+//	edev->promiscuous = etherusbpromiscuous;
+//	edev->shutdown = etherusbshutdown;
+//	edev->multicast = etherusbmulticast;
+
 	return 0;
 }
 

+ 13 - 5
sys/src/ape/lib/ap/386/vlop.s

@@ -13,16 +13,24 @@ TEXT	_mulv(SB), $0
 	MOVL	BX, 4(CX)
 	RET
 
+/*
+ * _mul64by32(uint64 *r, uint64 a, uint32 b)
+ * sets *r = low 64 bits of 96-bit product a*b; returns high 32 bits.
+ */
 TEXT	_mul64by32(SB), $0
 	MOVL	r+0(FP), CX
 	MOVL	a+4(FP), AX
 	MULL	b+12(FP)
-	MOVL	AX, 0(CX)
-	MOVL	DX, BX
+	MOVL	AX, 0(CX)	/* *r = low 32 bits of a*b */
+	MOVL	DX, BX		/* BX = high 32 bits of a*b */
+
 	MOVL	a+8(FP), AX
-	MULL	b+12(FP)
-	ADDL	AX, BX
-	MOVL	BX, 4(CX)
+	MULL	b+12(FP)	/* hi = (a>>32) * b */
+	ADDL	AX, BX		/* BX += low 32 bits of hi */
+	ADCL	$0, DX		/* DX = high 32 bits of hi + carry */
+	MOVL	BX, 4(CX)	/* *r |= (high 32 bits of a*b) << 32 */
+
+	MOVL	DX, AX		/* return hi>>32 */
 	RET
 
 TEXT	_div64by32(SB), $0

+ 3 - 3
sys/src/ape/lib/ap/386/vlrt.c

@@ -125,7 +125,7 @@ _v2f(Vlong x)
 }
 
 ulong	_div64by32(Vlong, ulong, ulong*);
-void	_mul64by32(Vlong*, Vlong, ulong);
+int	_mul64by32(Vlong*, Vlong, ulong);
 
 static void
 dodiv(Vlong num, Vlong den, Vlong *qp, Vlong *rp)
@@ -148,8 +148,8 @@ dodiv(Vlong num, Vlong den, Vlong *qp, Vlong *rp)
 	if(den.hi != 0){
 		q.hi = 0;
 		n = num.hi/den.hi;
-		_mul64by32(&x, den, n);
-		if(x.hi > num.hi || (x.hi == num.hi && x.lo > num.lo)){
+		if(_mul64by32(&x, den, n) || x.hi > num.hi ||
+		    (x.hi == num.hi && x.lo > num.lo)){
 			n--;
 			_mul64by32(&x, den, n);
 		}

+ 10 - 10
sys/src/cmd/dial/at.c

@@ -13,15 +13,15 @@ struct {
 	int	ok;
 } tab[] =
 {
-	{ "ok",			1 },
-	{ "connect",		1 },
-	{ "no carrier",		0 },
-	{ "no dialtone",	0 },
-	{ "error",		0 },
-	{ "busy",		0 },
-	{ "no answer",		0 },
-	{ "delayed",		0 },
-	{ "blacklisted",	0 },
+	{ "ok\n",		1 },
+	{ "connect\n",		1 },
+	{ "no carrier\n",	0 },
+	{ "no dialtone\n",	0 },
+	{ "error\n",		0 },
+	{ "busy\n",		0 },
+	{ "no answer\n",	0 },
+	{ "delayed\n",		0 },
+	{ "blacklisted\n",	0 },
 };
 
 int
@@ -98,7 +98,7 @@ docmd(char *cmd, int timeout, int quiet, int consfd)
 		if(!quiet)
 			writewithoutcr(consfd, buf, i);
 		for(i = 0; i < nelem(tab); i++)
-			if(cistrstr(buf, tab[i].resp)){
+			if(cistrcmp(buf, tab[i].resp) == 0){
 				if(tab[i].ok)
 					goto out;
 				else

+ 16 - 4
sys/src/cmd/ip/snoopy/ip.c

@@ -191,7 +191,8 @@ p_filter(Filter *f, Msg *m)
 static int
 p_seprint(Msg *m)
 {
-	int f, len;
+	int f, len, hl;
+	uchar *p;
 	Hdr *h;
 
 	if(m->pe - m->ps < IPHDR)
@@ -210,11 +211,22 @@ p_seprint(Msg *m)
 		m->pe = m->ps + len;
 
 	/* next header */
-	m->ps += (h->vihl  &0xf) << 2;
+	hl = (h->vihl  &0xf) << 2;
 
-	m->p = seprint(m->p, m->e, "s=%V d=%V id=%4.4ux frag=%4.4ux ttl=%3d pr=%d ln=%d",
+	m->p = seprint(m->p, m->e, "s=%V d=%V id=%4.4ux frag=%4.4ux ttl=%3d pr=%d ln=%d hl=%d",
 		h->src, h->dst, NetS(h->id), NetS(h->frag), h->ttl, h->proto,
-		NetS(h->length));
+		NetS(h->length),
+		(h->vihl & 0xf) << 2);
+
+	m->ps += hl;
+	p = (uchar *)(h + 1);
+	if(p < m->ps){
+		m->p = seprint(m->p, m->e, " opts=(");
+		while(p < m->ps)
+			m->p = seprint(m->p, m->e, "%.2ux", *p++);
+		m->p = seprint(m->p, m->e, ")");
+	}
+
 	return 0;
 }
 

+ 1 - 1
sys/src/cmd/ip/snoopy/main.c

@@ -149,7 +149,7 @@ main(int argc, char **argv)
 		snprint(buf, Blen, "%s!-1", file);
 		fd = dial(buf, 0, 0, &cfd);
 		if(fd < 0)
-			sysfatal("dialing %s", buf);
+			sysfatal("dialing %s: %r", buf);
 		if(pflag && fprint(cfd, prom, strlen(prom)) < 0)
 			sysfatal("setting %s", prom);
 	} else if((!tiflag) && strstr(file, "ipifc")){

+ 1 - 1
sys/src/cmd/ip/telnet.c

@@ -161,7 +161,7 @@ telnet(int net)
 		fromkbd(net);
 		if(notkbd)
 			for(;;)
-				sleep(0);
+				sleep(1000); // sleep(0) is a cpuhog
 		if (svc)
 			remove(svc);
 		sendnote(netpid, "die");

+ 2 - 1
sys/src/cmd/page/filter.c

@@ -97,7 +97,8 @@ initdvi(Biobuf *b, int argc, char **argv, uchar *buf, int nbuf)
 Document*
 inittroff(Biobuf *b, int argc, char **argv, uchar *buf, int nbuf)
 {
-	return initfilt(b, argc, argv, buf, nbuf, "troff", "lp -dstdout", 1);
+	/* Added -H to eliminate header page [sape] */
+	return initfilt(b, argc, argv, buf, nbuf, "troff", "lp -H -dstdout", 1);
 }
 
 Document*

+ 1 - 1
sys/src/cmd/plumb/match.c

@@ -389,7 +389,7 @@ enum
 {
 	NARGS		= 100,
 	NARGCHAR	= 8*1024,
-	EXECSTACK 	= 4096+(NARGS+1)*sizeof(char*)+NARGCHAR
+	EXECSTACK 	= 8192+(NARGS+1)*sizeof(char*)+NARGCHAR
 };
 
 /* copy argv to stack and free the incoming strings, so we don't leak argument vectors */

+ 3 - 1
sys/src/cmd/replica/db.c

@@ -58,10 +58,12 @@ static int
 entrycmp(Avl *a, Avl *b)
 {
 	Entry *ea, *eb;
+	int r;
 
 	ea = (Entry*)a;
 	eb = (Entry*)b;
-	return strcmp(ea->name, eb->name);
+	r = strcmp(ea->name, eb->name);
+	return r > 0 ? 1 : r < 0 ? -1 : 0;
 }
 
 Db*

+ 13 - 9
sys/src/cmd/stats.c

@@ -15,7 +15,7 @@ struct Graph
 {
 	int		colindex;
 	Rectangle	r;
-	int		*data;
+	uvlong		*data;
 	int		ndata;
 	char		*label;
 	void		(*newvalue)(Machine*, uvlong*, uvlong*, int);
@@ -358,10 +358,13 @@ datapoint(Graph *g, int x, uvlong v, uvlong vmax)
 			y = (y+2.)/3.;
 		}
 	}
-	p.y = g->r.max.y - Dy(g->r)*y - Dot;
-	if(p.y < g->r.min.y)
-		p.y = g->r.min.y;
-	if(p.y > g->r.max.y-Dot)
+	if(y < 0x7fffffff){	/* avoid floating overflow */
+		p.y = g->r.max.y - Dy(g->r)*y - Dot;
+		if(p.y < g->r.min.y)
+			p.y = g->r.min.y;
+		if(p.y > g->r.max.y-Dot)
+			p.y = g->r.max.y-Dot;
+	}else
 		p.y = g->r.max.y-Dot;
 	return p;
 }
@@ -430,7 +433,7 @@ int
 readnums(Machine *m, int n, uvlong *a, int spanlines)
 {
 	int i;
-	char *p, *ep;
+	char *p, *q, *ep;
 
 	if(spanlines)
 		ep = m->ebufp;
@@ -444,7 +447,8 @@ readnums(Machine *m, int n, uvlong *a, int spanlines)
 			p++;
 		if(p == ep)
 			break;
-		a[i] = strtoull(p, &p, 10);
+		a[i] = strtoull(p, &q, 10);
+		p = q;
 	}
 	if(ep < m->ebufp)
 		ep++;
@@ -1199,9 +1203,9 @@ resize(void)
 			/* allocate data */
 			ondata = g->ndata;
 			g->ndata = Dx(machr)+1;	/* may be too many if label will be drawn here; so what? */
-			g->data = erealloc(g->data, g->ndata*sizeof(ulong));
+			g->data = erealloc(g->data, g->ndata*sizeof(g->data[0]));
 			if(g->ndata > ondata)
-				memset(g->data+ondata, 0, (g->ndata-ondata)*sizeof(ulong));
+				memset(g->data+ondata, 0, (g->ndata-ondata)*sizeof(g->data[0]));
 			/* set geometry */
 			g->r = machr;
 			g->r.min.y = y;

+ 6 - 1
sys/src/cmd/tbl/t6.c

@@ -192,7 +192,12 @@ maktab(void)			/* define the tab stops of the table */
 	if (boxflg || allflg || dboxflg)
 		Bprint(&tabout, ".nr TW +((%d*\\n(%d)/2)\n", tsep, TMP);
 	Bprint(&tabout,
-	    ".if t .if (\\n(TW+\\n(.o)>7.65i .tm Table at line %d file %s is too wide - \\n(TW units\n", iline - 1, ifile);
+	    ".if t .if (\\n(TW>\\n(.l .tm Table at line %d file %s is too wide - \\n(TW units\n", iline - 1, ifile);
+/*
+ * Used to be:
+ 	    ".if t .if (\\n(TW+\\n(.o)>7.65i .tm Table at line %d file %s is too wide - \\n(TW units\n", iline - 1, ifile);
+ * but that gives warnings where none are necessary (or desired) [sape]
+ */
 }
 
 

+ 4 - 0
sys/src/cmd/tcs/tcs.c

@@ -503,6 +503,10 @@ struct convert convert[] =
 	{ "ebcdic", "EBCDIC", Table, (void *)tabebcdic },	/* 6f is recommended bad map */
 	{ "euc-k", "Korean EUC: ASCII+KS C 5601 1987", From|Func, 0, (Fnptr)uksc_in },
 	{ "euc-k", "Korean EUC: ASCII+KS C 5601 1987", Func, 0, (Fnptr)uksc_out },
+ 	{ "euc-kr", "Korean EUC: ASCII+KS C 5601 1987", From|Func, 0, (Fnptr)uksc_in },
+ 	{ "euc-kr", "Korean EUC: ASCII+KS C 5601 1987", Func, 0, (Fnptr)uksc_out },
+ 	{ "ks_c_5601-1987", "Korean EUC: ASCII+KS C 5601 1987", From|Func, 0, (Fnptr)uksc_in },
+ 	{ "ks_c_5601-1987", "Korean EUC: ASCII+KS C 5601 1987", Func, 0, (Fnptr)uksc_out },
 	{ "gb2312", "GB2312-80 (Chinese)", From|Func, 0, (Fnptr)gb_in },
 	{ "gb2312", "GB2312-80 (Chinese)", Func, 0, (Fnptr)gb_out },
 	{ "gbk", "GBK (Chinese)", From|Func, 0, (Fnptr)gbk_in },

+ 1 - 1
sys/src/cmd/usb/ether/asix.c

@@ -425,7 +425,7 @@ asixpromiscuous(Ether *e, int on)
 {
 	int rxctl;
 
-	deprint(2, "%s: aixprompiscuous %d\n", argv0, on);
+	deprint(2, "%s: asixpromiscuous %d\n", argv0, on);
 	rxctl = getrxctl(e->dev);
 	if(on != 0)
 		rxctl |= Rxctlprom;

+ 39 - 0
sys/src/cmd/usb/ether/smsc.c

@@ -320,6 +320,43 @@ smscbwrite(Ether *e, Buf *bp)
 	return n;
 }
 
+static int
+smscpromiscuous(Ether *e, int on)
+{
+	USED(on, e);
+#ifdef TODO		/* copied from asix */
+	int rxctl;
+
+	deprint(2, "%s: smscpromiscuous %d\n", argv0, on);
+	rxctl = getrxctl(e->dev);
+	if(on != 0)
+		rxctl |= Rxctlprom;
+	else
+		rxctl &= ~Rxctlprom;
+	return wr(e->dev, Cwrxctl, rxctl);
+#endif
+	return -1;
+}
+
+static int
+smscmulticast(Ether *e, uchar *addr, int on)
+{
+	USED(addr, on, e);
+#ifdef TODO		/* needed for ipv6; copied from asix */
+	int rxctl;
+
+	/* BUG: should write multicast filter */
+	rxctl = getrxctl(e->dev);
+	if(e->nmcasts != 0)
+		rxctl |= Rxctlamall;
+	else
+		rxctl &= ~Rxctlamall;
+	deprint(2, "%s: smscmulticast %d\n", argv0, e->nmcasts);
+	return wr(e->dev, Cwrxctl, rxctl);
+#endif
+	return -1;
+}
+
 static void
 smscfree(Ether *ether)
 {
@@ -354,6 +391,8 @@ smscreset(Ether *ether)
 			ether->free = smscfree;
 			ether->bread = smscbread;
 			ether->bwrite = smscbwrite;
+			ether->promiscuous = smscpromiscuous;
+			ether->multicast = smscmulticast;
 			ether->mbps = 100;	/* BUG */
 			return 0;
 		}

+ 2 - 1
sys/src/cmd/usb/serial/serial.c

@@ -464,7 +464,7 @@ dirgen(Usbfs *fs, Qid, int i, Dir *d, void *p)
 }
 
 enum {
-	Serbufsize	= 255,
+	Serbufsize	= 256,
 };
 
 static long
@@ -494,6 +494,7 @@ dread(Usbfs *fs, Fid *fid, void *data, long count, vlong offset)
 	case Qdata:
 		if(count > ser->maxread)
 			count = ser->maxread;
+
 		dsprint(2, "serial: reading from data\n");
 		do {
 			err[0] = 0;

+ 13 - 5
sys/src/libc/386/vlop.s

@@ -13,16 +13,24 @@ TEXT	_mulv(SB), $0
 	MOVL	BX, 4(CX)
 	RET
 
+/*
+ * _mul64by32(uint64 *r, uint64 a, uint32 b)
+ * sets *r = low 64 bits of 96-bit product a*b; returns high 32 bits.
+ */
 TEXT	_mul64by32(SB), $0
 	MOVL	r+0(FP), CX
 	MOVL	a+4(FP), AX
 	MULL	b+12(FP)
-	MOVL	AX, 0(CX)
-	MOVL	DX, BX
+	MOVL	AX, 0(CX)	/* *r = low 32 bits of a*b */
+	MOVL	DX, BX		/* BX = high 32 bits of a*b */
+
 	MOVL	a+8(FP), AX
-	MULL	b+12(FP)
-	ADDL	AX, BX
-	MOVL	BX, 4(CX)
+	MULL	b+12(FP)	/* hi = (a>>32) * b */
+	ADDL	AX, BX		/* BX += low 32 bits of hi */
+	ADCL	$0, DX		/* DX = high 32 bits of hi + carry */
+	MOVL	BX, 4(CX)	/* *r |= (high 32 bits of a*b) << 32 */
+
+	MOVL	DX, AX		/* return hi>>32 */
 	RET
 
 TEXT	_div64by32(SB), $0

+ 3 - 3
sys/src/libc/386/vlrt.c

@@ -114,7 +114,7 @@ _v2f(Vlong x)
 }
 
 ulong	_div64by32(Vlong, ulong, ulong*);
-void	_mul64by32(Vlong*, Vlong, ulong);
+int	_mul64by32(Vlong*, Vlong, ulong);
 
 static void
 slowdodiv(Vlong num, Vlong den, Vlong *q, Vlong *r)
@@ -199,8 +199,8 @@ dodiv(Vlong num, Vlong den, Vlong *qp, Vlong *rp)
 	if(den.hi != 0){
 		q.hi = 0;
 		n = num.hi/den.hi;
-		_mul64by32(&x, den, n);
-		if(x.hi > num.hi || (x.hi == num.hi && x.lo > num.lo))
+		if(_mul64by32(&x, den, n) || x.hi > num.hi ||
+		    (x.hi == num.hi && x.lo > num.lo))
 			slowdodiv(num, den, &q, &r);
 		else {
 			q.lo = n;

+ 80 - 46
sys/src/libc/port/cleanname.c

@@ -8,56 +8,90 @@
 char*
 cleanname(char *name)
 {
-	char *p, *q, *dotdot;
-	int rooted, erasedprefix;
+	char *s;	/* source of copy */
+	char *d;	/* destination of copy */
+	char *d0;	/* start of path afer the root name */
+	Rune r;
+	int rooted;
 
-	rooted = name[0] == '/';
-	erasedprefix = 0;
+	if(name[0] == 0)
+		return strcpy(name, ".");
+	rooted = 0;
+	d0 = name;
+	if(d0[0] == '#'){
+		if(d0[1] == 0)
+			return d0;
+		d0  += 1 + chartorune(&r, d0+1); /* ignore slash: #/ */
+		while(!SEP(*d0))
+			d0 += chartorune(&r, d0);
+		if(d0 == 0)
+			return name;
+		d0++;	/* keep / after #<name> */
+		rooted = 1;
+	}else if(d0[0] == '/'){
+		rooted = 1;
+		d0++;
+	}
+
+	s = d0;
+	if(rooted){
+		/* skip extra '/' at root name */
+		for(; *s == '/'; s++)
+			;
+	}
+	/* remove dup slashes */
+	for(d = d0; *s != 0; s++){
+		*d++ = *s;
+		if(*s == '/')
+			while(s[1] == '/')
+				s++;
+	}
+	*d = 0;
 
-	/*
-	 * invariants:
-	 *	p points at beginning of path element we're considering.
-	 *	q points just past the last path element we wrote (no slash).
-	 *	dotdot points just past the point where .. cannot backtrack
-	 *		any further (no slash).
-	 */
-	p = q = dotdot = name+rooted;
-	while(*p) {
-		if(p[0] == '/')	/* null element */
-			p++;
-		else if(p[0] == '.' && SEP(p[1])) {
-			if(p == name)
-				erasedprefix = 1;
-			p += 1;	/* don't count the separator in case it is nul */
-		} else if(p[0] == '.' && p[1] == '.' && SEP(p[2])) {
-			p += 2;
-			if(q > dotdot) {	/* can backtrack */
-				while(--q > dotdot && *q != '/')
-					;
-			} else if(!rooted) {	/* /.. is / but ./../ is .. */
-				if(q != name)
-					*q++ = '/';
-				*q++ = '.';
-				*q++ = '.';
-				dotdot = q;
+	d = d0;
+	s = d0;
+	while(*s != 0){
+		if(s[0] == '.' && SEP(s[1])){
+			if(s[1] == 0)
+				break;
+			s+= 2;
+			continue;
+		}
+		if(s[0] == '.' && s[1] == '.' && SEP(s[2])){
+			if(d == d0){
+				if(rooted){
+					/* /../x -> /x */
+					if(s[2] == 0)
+						break;
+					s += 3;
+					continue;
+				}else{
+					/* ../x -> ../x; and never collect ../ */
+					d0 += 3;
+				}
+			}
+			if(d > d0){
+				/* a/../x -> x */
+				assert(d-2 >= d0 && d[-1] == '/');
+				for(d -= 2; d > d0 && d[-1] != '/'; d--)
+						;
+				if(s[2] == 0)
+					break;
+				s += 3;
+				continue;
 			}
-			if(q == name)
-				erasedprefix = 1;	/* erased entire path via dotdot */
-		} else {	/* real path element */
-			if(q != name+rooted)
-				*q++ = '/';
-			while((*q = *p) != '/' && *q != 0)
-				p++, q++;
 		}
+		while(!SEP(*s))
+			*d++ = *s++;
+		if(*s == 0)
+			break;
+		
+		*d++ = *s++;
 	}
-	if(q == name)	/* empty string is really ``.'' */
-		*q++ = '.';
-	*q = '\0';
-	if(erasedprefix && name[0] == '#'){	
-		/* this was not a #x device path originally - make it not one now */
-		memmove(name+2, name, strlen(name)+1);
-		name[0] = '.';
-		name[1] = '/';
-	}
+	*d = 0;
+	if(d-1 > name && d[-1] == '/')	/* thanks to #/ */
+		*--d = 0;
+	if(name[0] == 0)
+		strcpy(name, ".");
 	return name;
 }

+ 1 - 1
sys/src/libndb/ndbopen.c

@@ -22,7 +22,7 @@ ndbopen(char *file)
 	Ndbs s;
 	Ndbtuple *t, *nt;
 
-	if(file == 0)
+	if(file == nil && (file = getenv("NDBFILE")) == nil)
 		file = deffile;
 	db = doopen(file);
 	if(db == 0)

+ 2 - 0
sys/src/libthread/threadimpl.h

@@ -180,6 +180,8 @@ void*	_threadrendezvous(void*, void*);
 void	_threadsignal(void);
 void	_threadsysfatal(char*, va_list);
 void**	_workerdata(void);
+void	_xinc(long*);
+long	_xdec(long*);
 
 extern int			_threaddebuglevel;
 extern char*		_threadexitsallstatus;