diff options
Diffstat (limited to 'src/runtime/os_plan9.c')
-rw-r--r-- | src/runtime/os_plan9.c | 362 |
1 files changed, 362 insertions, 0 deletions
diff --git a/src/runtime/os_plan9.c b/src/runtime/os_plan9.c new file mode 100644 index 000000000..f8c543f6f --- /dev/null +++ b/src/runtime/os_plan9.c @@ -0,0 +1,362 @@ +// 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" +#include "textflag.h" +#include "malloc.h" + +int8 *goos = "plan9"; +extern SigTab runtime·sigtab[]; + +int32 runtime·postnote(int32, int8*); + +// Called to initialize a new m (including the bootstrap m). +// Called on the parent thread (main thread in case of bootstrap), can allocate memory. +void +runtime·mpreinit(M *mp) +{ + // Initialize stack and goroutine for note handling. + mp->gsignal = runtime·malg(32*1024); + mp->gsignal->m = mp; + mp->notesig = (int8*)runtime·mallocgc(ERRMAX*sizeof(int8), nil, FlagNoScan); + + // Initialize stack for handling strings from the + // errstr system call, as used in package syscall. + mp->errstr = (byte*)runtime·mallocgc(ERRMAX*sizeof(byte), nil, FlagNoScan); +} + +// Called to initialize a new m (including the bootstrap m). +// Called on the new thread, can not allocate memory. +void +runtime·minit(void) +{ + // Mask all SSE floating-point exceptions + // when running on the 64-bit kernel. + runtime·setfpmasks(); +} + +// Called from dropm to undo the effect of an minit. +void +runtime·unminit(void) +{ +} + + +static int32 +getproccount(void) +{ + int32 fd, i, n, ncpu; + byte buf[2048]; + + fd = runtime·open("/dev/sysstat", OREAD, 0); + 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; +} + +static int32 +getpid(void) +{ + byte b[20], *c; + int32 fd; + + runtime·memclr(b, sizeof(b)); + fd = runtime·open("#c/pid", 0, 0); + if(fd >= 0) { + runtime·read(fd, b, sizeof(b)); + runtime·close(fd); + } + c = b; + while(*c == ' ' || *c == '\t') + c++; + return runtime·atoi(c); +} + +void +runtime·osinit(void) +{ + runtime·ncpu = getproccount(); + g->m->procid = getpid(); + runtime·notify(runtime·sigtramp); +} + +void +runtime·crash(void) +{ + runtime·notify(nil); + *(int32*)0 = 0; +} + +#pragma textflag NOSPLIT +void +runtime·get_random_data(byte **rnd, int32 *rnd_len) +{ + static byte random_data[HashRandomBytes]; + int32 fd; + + fd = runtime·open("/dev/random", 0 /* O_RDONLY */, 0); + if(runtime·read(fd, random_data, HashRandomBytes) == HashRandomBytes) { + *rnd = random_data; + *rnd_len = HashRandomBytes; + } else { + *rnd = nil; + *rnd_len = 0; + } + runtime·close(fd); +} + +void +runtime·goenvs(void) +{ +} + +void +runtime·initsig(void) +{ +} + +#pragma textflag NOSPLIT +void +runtime·osyield(void) +{ + runtime·sleep(0); +} + +#pragma textflag NOSPLIT +void +runtime·usleep(uint32 µs) +{ + uint32 ms; + + ms = µs/1000; + if(ms == 0) + ms = 1; + runtime·sleep(ms); +} + +#pragma textflag NOSPLIT +int64 +runtime·nanotime(void) +{ + int64 ns, scratch; + + ns = runtime·nsec(&scratch); + // TODO(aram): remove hack after I fix _nsec in the pc64 kernel. + if(ns == 0) + return scratch; + return ns; +} + +#pragma textflag NOSPLIT +void +runtime·itoa(int32 n, byte *p, uint32 len) +{ + byte *q, c; + uint32 i; + + if(len <= 1) + return; + + runtime·memclr(p, len); + q = p; + + if(n==0) { + *q++ = '0'; + USED(q); + return; + } + if(n < 0) { + *q++ = '-'; + p++; + n = -n; + } + for(i=0; n > 0 && i < len; i++) { + *q++ = '0' + (n%10); + n = n/10; + } + for(q--; q >= p; ) { + c = *p; + *p++ = *q; + *q-- = c; + } +} + +void +runtime·goexitsall(int8 *status) +{ + int8 buf[ERRMAX]; + M *mp; + int32 pid; + + runtime·snprintf((byte*)buf, sizeof buf, "go: exit %s", status); + pid = getpid(); + for(mp=runtime·atomicloadp(&runtime·allm); mp; mp=mp->alllink) + if(mp->procid != pid) + runtime·postnote(mp->procid, buf); +} + +int32 +runtime·postnote(int32 pid, int8* msg) +{ + int32 fd; + intgo len; + uint8 buf[128]; + uint8 tmp[16]; + uint8 *p, *q; + + runtime·memclr(buf, sizeof buf); + + /* build path string /proc/pid/note */ + q = tmp; + p = buf; + runtime·itoa(pid, tmp, sizeof tmp); + runtime·memmove((void*)p, (void*)"/proc/", 6); + for(p += 6; *p++ = *q++; ); + p--; + runtime·memmove((void*)p, (void*)"/note", 5); + + fd = runtime·open((int8*)buf, OWRITE, 0); + if(fd < 0) + return -1; + + len = runtime·findnull((byte*)msg); + if(runtime·write(fd, msg, len) != len) { + runtime·close(fd); + return -1; + } + runtime·close(fd); + return 0; +} + +static void exit(void); + +#pragma textflag NOSPLIT +void +runtime·exit(int32 e) +{ + void (*fn)(void); + + g->m->scalararg[0] = e; + fn = exit; + runtime·onM(&fn); +} + +static void +exit(void) +{ + int32 e; + byte tmp[16]; + int8 *status; + + e = g->m->scalararg[0]; + g->m->scalararg[0] = 0; + + if(e == 0) + status = ""; + else { + /* build error string */ + runtime·itoa(e, tmp, sizeof tmp); + status = (int8*)tmp; + } + + runtime·goexitsall(status); + runtime·exits(status); +} + +void +runtime·newosproc(M *mp, void *stk) +{ + int32 pid; + + if(0) + runtime·printf("newosproc mp=%p ostk=%p\n", mp, &mp); + + USED(stk); + if((pid = runtime·rfork(RFPROC|RFMEM|RFNOWAIT)) < 0) + runtime·throw("newosproc: rfork failed\n"); + if(pid == 0) + runtime·tstart_plan9(mp); +} + +#pragma textflag NOSPLIT +uintptr +runtime·semacreate(void) +{ + return 1; +} + +#pragma textflag NOSPLIT +int32 +runtime·semasleep(int64 ns) +{ + int32 ret; + int32 ms; + + if(ns >= 0) { + ms = runtime·timediv(ns, 1000000, nil); + if(ms == 0) + ms = 1; + ret = runtime·plan9_tsemacquire(&g->m->waitsemacount, ms); + if(ret == 1) + return 0; // success + return -1; // timeout or interrupted + } + + while(runtime·plan9_semacquire(&g->m->waitsemacount, 1) < 0) { + /* interrupted; try again (c.f. lock_sema.c) */ + } + return 0; // success +} + +#pragma textflag NOSPLIT +void +runtime·semawakeup(M *mp) +{ + runtime·plan9_semrelease(&mp->waitsemacount, 1); +} + +#pragma textflag NOSPLIT +int32 +runtime·read(int32 fd, void *buf, int32 nbytes) +{ + return runtime·pread(fd, buf, nbytes, -1LL); +} + +#pragma textflag NOSPLIT +int32 +runtime·write(uintptr fd, void *buf, int32 nbytes) +{ + return runtime·pwrite((int32)fd, buf, nbytes, -1LL); +} + +uintptr +runtime·memlimit(void) +{ + return 0; +} + +#pragma dataflag NOPTR +static int8 badsignal[] = "runtime: signal received on thread not created by Go.\n"; + +// This runs on a foreign stack, without an m or a g. No stack split. +#pragma textflag NOSPLIT +void +runtime·badsignal2(void) +{ + runtime·pwrite(2, badsignal, sizeof badsignal - 1, -1LL); + runtime·exits(badsignal); +} |