runtime: add nanotime for Plan 9

R=paulzhol, rsc, dave, rminnich
CC=golang-dev
https://golang.org/cl/5327063
diff --git a/src/pkg/runtime/plan9/386/signal.c b/src/pkg/runtime/plan9/386/signal.c
index 77e40d3..c0b759c 100644
--- a/src/pkg/runtime/plan9/386/signal.c
+++ b/src/pkg/runtime/plan9/386/signal.c
@@ -4,12 +4,6 @@
 
 #include "runtime.h"
 
-int64
-runtime·nanotime(void) 
-{
-	// Won't compile.
-}
-
 String
 runtime·signame(int32)
 {
diff --git a/src/pkg/runtime/plan9/386/sys.s b/src/pkg/runtime/plan9/386/sys.s
index a15362f..97be276 100644
--- a/src/pkg/runtime/plan9/386/sys.s
+++ b/src/pkg/runtime/plan9/386/sys.s
@@ -14,16 +14,14 @@
 	INT     $64
 	RET
 
-// TODO(ality): remove use of deprecated system calls
-
-TEXT runtime·read(SB),7,$0
-	MOVL	$15, AX
-	INT		$64
+TEXT runtime·pread(SB),7,$0
+	MOVL    $50, AX
+	INT     $64
 	RET
 
-TEXT runtime·write(SB),7,$0
-	MOVL	$20, AX
-	INT		$64
+TEXT runtime·pwrite(SB),7,$0
+	MOVL    $51, AX
+	INT     $64
 	RET
 
 TEXT runtime·close(SB),7,$0
@@ -90,9 +88,9 @@
 	MOVL	0(BX), BX
 	
 	// more paranoia; check that stack splitting code works
-	PUSHAL
+	PUSHL	SI
 	CALL	runtime·emptyfunc(SB)
-	POPAL
+	POPL	SI
 	
 	CALL	SI	// fn()
 	CALL	runtime·exit(SB)
diff --git a/src/pkg/runtime/plan9/os.h b/src/pkg/runtime/plan9/os.h
index dcbdab2..b7b8383 100644
--- a/src/pkg/runtime/plan9/os.h
+++ b/src/pkg/runtime/plan9/os.h
@@ -4,6 +4,8 @@
 
 // Plan 9-specific system calls
 int32	runtime·open(uint8 *file, int32 mode);
+int32	runtime·pread(int32 fd, void *buf, int32 nbytes, int64 offset);
+int32	runtime·pwrite(int32 fd, void *buf, int32 nbytes, int64 offset);
 int32	runtime·read(int32 fd, void *buf, int32 nbytes);
 int32	runtime·close(int32 fd);
 void	runtime·exits(int8* msg);
@@ -16,9 +18,14 @@
 /* open */
 enum
 {
-	OREAD			= 0,
-	OWRITE			= 1,
-	ORDWR			= 2
+	OREAD	= 0,
+	OWRITE	= 1,
+	ORDWR	= 2,
+	OEXEC	= 3,
+	OTRUNC	= 16,
+	OCEXEC	= 32,
+	ORCLOSE	= 64,
+	OEXCL	= 0x1000
 };
 
 /* rfork */
diff --git a/src/pkg/runtime/plan9/thread.c b/src/pkg/runtime/plan9/thread.c
index 8ad06ca..87ea8a2 100644
--- a/src/pkg/runtime/plan9/thread.c
+++ b/src/pkg/runtime/plan9/thread.c
@@ -69,6 +69,34 @@
 	runtime·sleep(ms);
 }
 
+int64
+runtime·nanotime(void)
+{
+	static int32 fd = -1;
+	byte b[8];
+	uint32 hi, lo;
+
+	// As long as all goroutines share the same file
+	// descriptor table we can get away with using
+	// just a static fd.  Without a lock the file can
+	// be opened twice but that's okay.
+	//
+	// Using /dev/bintime gives us a latency on the
+	// order of ten microseconds between two calls.
+	//
+	// The naïve implementation (without the cached
+	// file descriptor) is roughly four times slower
+	// in 9vx on a 2.16 GHz Intel Core 2 Duo.
+	
+	if(fd < 0 && (fd = runtime·open((byte*)"/dev/bintime", OREAD|OCEXEC)) < 0)
+		return 0;
+	if(runtime·pread(fd, b, sizeof b, 0) != sizeof b)
+		return 0;
+	hi = b[0]<<24 | b[1]<<16 | b[2]<<8 | b[3];
+	lo = b[4]<<24 | b[5]<<16 | b[6]<<8 | b[7];
+	return (int64)hi<<32 | (int64)lo;
+}
+
 extern Tos *_tos;
 void
 runtime·exit(int32)
@@ -183,3 +211,15 @@
 runtime·sigpanic(void)
 {
 }
+
+int32
+runtime·read(int32 fd, void *buf, int32 nbytes)
+{
+	return runtime·pread(fd, buf, nbytes, -1LL);
+}
+
+int32
+runtime·write(int32 fd, void *buf, int32 nbytes)
+{
+	return runtime·pwrite(fd, buf, nbytes, -1LL);
+}