summaryrefslogtreecommitdiff
path: root/src/pkg/runtime/thread_plan9.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/runtime/thread_plan9.c')
-rw-r--r--src/pkg/runtime/thread_plan9.c237
1 files changed, 237 insertions, 0 deletions
diff --git a/src/pkg/runtime/thread_plan9.c b/src/pkg/runtime/thread_plan9.c
new file mode 100644
index 000000000..a9b156d02
--- /dev/null
+++ b/src/pkg/runtime/thread_plan9.c
@@ -0,0 +1,237 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "runtime.h"
+#include "os_GOOS.h"
+#include "arch_GOARCH.h"
+
+int8 *goos = "plan9";
+
+void
+runtime·minit(void)
+{
+}
+
+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
+runtime·goenvs(void)
+{
+}
+
+void
+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);
+}
+
+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;
+}
+
+void
+time·now(int64 sec, int32 nsec)
+{
+ int64 ns;
+
+ ns = runtime·nanotime();
+ sec = ns / 1000000000LL;
+ nsec = ns - sec * 1000000000LL;
+ FLUSH(&sec);
+ FLUSH(&nsec);
+}
+
+extern Tos *_tos;
+void
+runtime·exit(int32)
+{
+ int32 fd;
+ uint8 buf[128];
+ uint8 tmp[16];
+ uint8 *p, *q;
+ int32 pid;
+
+ runtime·memclr(buf, sizeof buf);
+ runtime·memclr(tmp, sizeof tmp);
+ pid = _tos->pid;
+
+ /* build path string /proc/pid/notepg */
+ for(q=tmp; pid > 0;) {
+ *q++ = '0' + (pid%10);
+ pid = pid/10;
+ }
+ p = buf;
+ runtime·memmove((void*)p, (void*)"/proc/", 6);
+ p += 6;
+ for(q--; q >= tmp;)
+ *p++ = *q--;
+ runtime·memmove((void*)p, (void*)"/notepg", 7);
+
+ /* post interrupt note */
+ fd = runtime·open(buf, OWRITE);
+ runtime·write(fd, "interrupt", 9);
+ runtime·exits(nil);
+}
+
+void
+runtime·newosproc(M *m, G *g, void *stk, void (*fn)(void))
+{
+ m->tls[0] = m->id; // so 386 asm can find it
+ if(0){
+ runtime·printf("newosproc stk=%p m=%p g=%p fn=%p rfork=%p id=%d/%d ostk=%p\n",
+ stk, m, g, fn, runtime·rfork, m->id, m->tls[0], &m);
+ }
+
+ if(runtime·rfork(RFPROC|RFMEM|RFNOWAIT, stk, m, g, fn) < 0)
+ runtime·throw("newosproc: rfork failed");
+}
+
+uintptr
+runtime·semacreate(void)
+{
+ return 1;
+}
+
+int32
+runtime·semasleep(int64 ns)
+{
+ int32 ret;
+ int32 ms;
+
+ if(ns >= 0) {
+ // TODO: Plan 9 needs a new system call, tsemacquire.
+ // The kernel implementation is the same as semacquire
+ // except with a tsleep and check for timeout.
+ // It would be great if the implementation returned the
+ // value that was added to the semaphore, so that on
+ // timeout the return value would be 0, on success 1.
+ // Then the error string does not have to be parsed
+ // to detect timeout.
+ //
+ // If a negative time indicates no timeout, then
+ // semacquire can be implemented (in the kernel)
+ // as tsemacquire(p, v, -1).
+ runtime·throw("semasleep: timed sleep not implemented on Plan 9");
+
+ /*
+ if(ns < 0)
+ ms = -1;
+ else if(ns/1000 > 0x7fffffffll)
+ ms = 0x7fffffff;
+ else
+ ms = ns/1000;
+ ret = runtime·plan9_tsemacquire(&m->waitsemacount, 1, ms);
+ if(ret == 1)
+ return 0; // success
+ return -1; // timeout or interrupted
+ */
+ }
+
+ while(runtime·plan9_semacquire(&m->waitsemacount, 1) < 0) {
+ /* interrupted; try again */
+ }
+ return 0; // success
+}
+
+void
+runtime·semawakeup(M *mp)
+{
+ runtime·plan9_semrelease(&mp->waitsemacount, 1);
+}
+
+void
+os·sigpipe(void)
+{
+ runtime·throw("too many writes on closed pipe");
+}
+
+/*
+ * placeholder - once notes are implemented,
+ * a signal generating a panic must appear as
+ * a call to this function for correct handling by
+ * traceback.
+ */
+void
+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);
+}