runtime: fix Plan 9 build

This change adds the osyield and usleep
functions and code to read the number of
processors from /dev/sysstat.

I also changed SysAlloc to return nil
when brk fails (it was returning -1).

R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/5177049
diff --git a/src/pkg/runtime/plan9/386/sys.s b/src/pkg/runtime/plan9/386/sys.s
index 1cb570b..a15362f 100644
--- a/src/pkg/runtime/plan9/386/sys.s
+++ b/src/pkg/runtime/plan9/386/sys.s
@@ -14,9 +14,21 @@
 	INT     $64
 	RET
 
+// TODO(ality): remove use of deprecated system calls
+
+TEXT runtime·read(SB),7,$0
+	MOVL	$15, AX
+	INT		$64
+	RET
+
 TEXT runtime·write(SB),7,$0
-	MOVL    $20, AX
-	INT     $64
+	MOVL	$20, AX
+	INT		$64
+	RET
+
+TEXT runtime·close(SB),7,$0
+	MOVL	$4, AX
+	INT		$64
 	RET
 
 TEXT runtime·exits(SB),7,$0
@@ -29,6 +41,11 @@
 	INT     $64
 	RET
 
+TEXT runtime·sleep(SB),7,$0
+	MOVL    $17, AX
+	INT     $64
+	RET
+
 TEXT runtime·plan9_semacquire(SB),7,$0
 	MOVL	$37, AX
 	INT	$64
diff --git a/src/pkg/runtime/plan9/mem.c b/src/pkg/runtime/plan9/mem.c
index f795b2c..e7347d9 100644
--- a/src/pkg/runtime/plan9/mem.c
+++ b/src/pkg/runtime/plan9/mem.c
@@ -26,7 +26,7 @@
 	bl = ((uintptr)bloc + Round) & ~Round;
 	if(runtime·brk_((void*)(bl + nbytes)) < 0) {
 		runtime·unlock(&memlock);
-		return (void*)-1;
+		return nil;
 	}
 	bloc = (byte*)bl + nbytes;
 	runtime·unlock(&memlock);
diff --git a/src/pkg/runtime/plan9/os.h b/src/pkg/runtime/plan9/os.h
index b2f7357..dcbdab2 100644
--- a/src/pkg/runtime/plan9/os.h
+++ b/src/pkg/runtime/plan9/os.h
@@ -2,9 +2,16 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-extern int32 runtime·write(int32 fd, void* buffer, int32 nbytes);
-extern void runtime·exits(int8* msg);
-extern int32 runtime·brk_(void*);
+// Plan 9-specific system calls
+int32	runtime·open(uint8 *file, int32 mode);
+int32	runtime·read(int32 fd, void *buf, int32 nbytes);
+int32	runtime·close(int32 fd);
+void	runtime·exits(int8* msg);
+int32	runtime·brk_(void*);
+int32	runtime·sleep(int32 ms);
+int32	runtime·rfork(int32 flags, void *stk, M *m, G *g, void (*fn)(void));
+int32	runtime·plan9_semacquire(uint32 *addr, int32 block);
+int32 	runtime·plan9_semrelease(uint32 *addr, int32 count);
 
 /* open */
 enum
@@ -52,6 +59,3 @@
 	/* top of stack is here */
 };
 
-extern int32 runtime·rfork(int32 flags, void *stk, M *m, G *g, void (*fn)(void));
-extern int32 runtime·plan9_semacquire(uint32 *addr, int32 block);
-extern int32 runtime·plan9_semrelease(uint32 *addr, int32 count);
diff --git a/src/pkg/runtime/plan9/thread.c b/src/pkg/runtime/plan9/thread.c
index 7769892..0334ccc 100644
--- a/src/pkg/runtime/plan9/thread.c
+++ b/src/pkg/runtime/plan9/thread.c
@@ -12,9 +12,33 @@
 {
 }
 
+static int32
+getproccount(void)
+{
+	int32 fd, i, n, ncpu;
+	byte buf[2048];
+
+	fd = runtime·open((byte*)"/dev/sysstat", OREAD);
+	if(fd < 0)
+		return 1;
+	ncpu = 0;
+	for(;;) {
+		n = runtime·read(fd, buf, sizeof buf);
+		if(n <= 0)
+			break;
+		for(i = 0; i < n; i++) {
+			if(buf[i] == '\n')
+				ncpu++;
+		}
+	}
+	runtime·close(fd);
+	return ncpu > 0 ? ncpu : 1;
+}
+
 void
 runtime·osinit(void)
 {
+	runtime·ncpu = getproccount();
 }
 
 void
@@ -23,10 +47,27 @@
 }
 
 void
-runtime·initsig(int32 queue)
+runtime·initsig(int32)
 {
 }
 
+void
+runtime·osyield(void)
+{
+	runtime·sleep(0);
+}
+
+void
+runtime·usleep(uint32 µs)
+{
+	uint32 ms;
+
+	ms = µs/1000;
+	if(ms == 0)
+		ms = 1;
+	runtime·sleep(ms);
+}
+
 extern Tos *_tos;
 void
 runtime·exit(int32)
@@ -68,7 +109,7 @@
 			stk, m, g, fn, runtime·rfork, m->id, m->tls[0], &m);
 	}        
 	
-	if (runtime·rfork(RFPROC|RFMEM|RFNOWAIT, stk, m, g, fn) < 0 )
+	if(runtime·rfork(RFPROC|RFMEM|RFNOWAIT, stk, m, g, fn) < 0)
 		runtime·throw("newosproc: rfork failed");
 }