]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.cc] runtime: convert Plan 9 port to Go
authorDavid du Colombier <0intro@gmail.com>
Fri, 21 Nov 2014 18:39:01 +0000 (19:39 +0100)
committerDavid du Colombier <0intro@gmail.com>
Fri, 21 Nov 2014 18:39:01 +0000 (19:39 +0100)
Thanks to Aram Hăvărneanu, Nick Owens
and Russ Cox for the early reviews.

LGTM=aram, rsc
R=rsc, lucio.dere, aram, ality
CC=golang-codereviews, mischief
https://golang.org/cl/175370043

18 files changed:
src/runtime/defs_plan9_386.go
src/runtime/defs_plan9_amd64.go
src/runtime/env_plan9.go
src/runtime/mem_plan9.c [deleted file]
src/runtime/mem_plan9.go [new file with mode: 0644]
src/runtime/netpoll_stub.go [moved from src/runtime/netpoll_stub.c with 81% similarity]
src/runtime/os1_plan9.go [new file with mode: 0644]
src/runtime/os2_plan9.go [new file with mode: 0644]
src/runtime/os_plan9.c [deleted file]
src/runtime/os_plan9.go
src/runtime/os_plan9.h [deleted file]
src/runtime/os_plan9_386.c [deleted file]
src/runtime/os_plan9_386.go [new file with mode: 0644]
src/runtime/os_plan9_amd64.c [deleted file]
src/runtime/os_plan9_amd64.go [new file with mode: 0644]
src/runtime/signal_plan9.go [moved from src/runtime/signals_plan9.h with 54% similarity]
src/runtime/stubs2.go
src/runtime/stubs3.go [new file with mode: 0644]

index 170506b230a242f765a142145551891398e3222d..212ecdf14aba8163de7ef0e19b07d7852377bd26 100644 (file)
@@ -1,5 +1,7 @@
 package runtime
 
+const _PAGESIZE = 0x1000
+
 type ureg struct {
        di    uint32 /* general registers */
        si    uint32 /* ... */
index 17becfb66f13bd3d8cf74554309cbdfa2d309702..510da0e994b98a4bddee8a849b0ebe0b17738d0c 100644 (file)
@@ -1,5 +1,7 @@
 package runtime
 
+const _PAGESIZE = 0x1000
+
 type ureg struct {
        ax  uint64
        bx  uint64
index e442c34835ef9c5b79d3ad9fe6fe7e514d827236..ec50cac484a61d12a488a51310f0006a18a99eb9 100644 (file)
@@ -54,3 +54,6 @@ func gogetenv(key string) string {
        sp.len = int(r)
        return s
 }
+
+var _cgo_setenv unsafe.Pointer   // pointer to C function
+var _cgo_unsetenv unsafe.Pointer // pointer to C function
diff --git a/src/runtime/mem_plan9.c b/src/runtime/mem_plan9.c
deleted file mode 100644 (file)
index d673d6f..0000000
+++ /dev/null
@@ -1,121 +0,0 @@
-// 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 "defs_GOOS_GOARCH.h"
-#include "arch_GOARCH.h"
-#include "malloc.h"
-#include "os_GOOS.h"
-#include "textflag.h"
-
-extern byte runtime·end[];
-#pragma dataflag NOPTR
-static byte *bloc = { runtime·end };
-static Mutex memlock;
-
-enum
-{
-       Round = PAGESIZE-1
-};
-
-static void*
-brk(uintptr nbytes)
-{
-       uintptr bl;
-
-       runtime·lock(&memlock);
-       // Plan 9 sbrk from /sys/src/libc/9sys/sbrk.c
-       bl = ((uintptr)bloc + Round) & ~Round;
-       if(runtime·brk_((void*)(bl + nbytes)) < 0) {
-               runtime·unlock(&memlock);
-               return nil;
-       }
-       bloc = (byte*)bl + nbytes;
-       runtime·unlock(&memlock);
-       return (void*)bl;       
-}
-
-static void
-sysalloc(void)
-{
-       uintptr nbytes;
-       uint64 *stat;
-       void *p;
-
-       nbytes = g->m->scalararg[0];
-       stat = g->m->ptrarg[0];
-       g->m->scalararg[0] = 0;
-       g->m->ptrarg[0] = nil;
-
-       p = brk(nbytes);
-       if(p != nil)
-               runtime·xadd64(stat, nbytes);
-
-       g->m->ptrarg[0] = p;
-}
-
-#pragma textflag NOSPLIT
-void*
-runtime·sysAlloc(uintptr nbytes, uint64 *stat)
-{
-       void (*fn)(void);
-       void *p;
-
-       g->m->scalararg[0] = nbytes;
-       g->m->ptrarg[0] = stat;
-       fn = sysalloc;
-       runtime·onM(&fn);
-       p = g->m->ptrarg[0];
-       g->m->ptrarg[0] = nil;
-       return p;
-}
-
-void
-runtime·SysFree(void *v, uintptr nbytes, uint64 *stat)
-{
-       runtime·xadd64(stat, -(uint64)nbytes);
-       runtime·lock(&memlock);
-       // from tiny/mem.c
-       // Push pointer back if this is a free
-       // of the most recent sysAlloc.
-       nbytes += (nbytes + Round) & ~Round;
-       if(bloc == (byte*)v+nbytes)
-               bloc -= nbytes;
-       runtime·unlock(&memlock);
-}
-
-void
-runtime·SysUnused(void *v, uintptr nbytes)
-{
-       USED(v, nbytes);
-}
-
-void
-runtime·SysUsed(void *v, uintptr nbytes)
-{
-       USED(v, nbytes);
-}
-
-void
-runtime·SysMap(void *v, uintptr nbytes, bool reserved, uint64 *stat)
-{
-       // SysReserve has already allocated all heap memory,
-       // but has not adjusted stats.
-       USED(v, reserved);
-       runtime·xadd64(stat, nbytes);
-}
-
-void
-runtime·SysFault(void *v, uintptr nbytes)
-{
-       USED(v, nbytes);
-}
-
-void*
-runtime·SysReserve(void *v, uintptr nbytes, bool *reserved)
-{
-       USED(v);
-       *reserved = true;
-       return brk(nbytes);
-}
diff --git a/src/runtime/mem_plan9.go b/src/runtime/mem_plan9.go
new file mode 100644 (file)
index 0000000..a5d7c1a
--- /dev/null
@@ -0,0 +1,70 @@
+// 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.
+
+package runtime
+
+import "unsafe"
+
+var bloc uintptr
+var memlock mutex
+
+const memRound = _PAGESIZE - 1
+
+func initBloc() {
+       bloc = uintptr(unsafe.Pointer(&end))
+}
+
+func sbrk(n uintptr) unsafe.Pointer {
+       lock(&memlock)
+       // Plan 9 sbrk from /sys/src/libc/9sys/sbrk.c
+       bl := (bloc + memRound) &^ memRound
+       if brk_(unsafe.Pointer(bl+n)) < 0 {
+               unlock(&memlock)
+               return nil
+       }
+       bloc = bl + n
+       unlock(&memlock)
+       return unsafe.Pointer(bl)
+}
+
+func sysAlloc(n uintptr, stat *uint64) unsafe.Pointer {
+       p := sbrk(n)
+       if p != nil {
+               xadd64(stat, int64(n))
+       }
+       return p
+}
+
+func sysFree(v unsafe.Pointer, n uintptr, stat *uint64) {
+       xadd64(stat, -int64(n))
+       lock(&memlock)
+       // from tiny/mem.c
+       // Push pointer back if this is a free
+       // of the most recent sysAlloc.
+       n += (n + memRound) &^ memRound
+       if bloc == uintptr(v)+n {
+               bloc -= n
+       }
+       unlock(&memlock)
+}
+
+func sysUnused(v unsafe.Pointer, n uintptr) {
+}
+
+func sysUsed(v unsafe.Pointer, n uintptr) {
+}
+
+func sysMap(v unsafe.Pointer, n uintptr, reserved bool, stat *uint64) {
+       // sysReserve has already allocated all heap memory,
+       // but has not adjusted stats.
+       xadd64(stat, int64(n))
+}
+
+func sysFault(v unsafe.Pointer, n uintptr) {
+}
+
+func sysReserve(v unsafe.Pointer, n uintptr, reserved *bool) unsafe.Pointer {
+       *reserved = true
+       return sbrk(n)
+}
similarity index 81%
rename from src/runtime/netpoll_stub.c
rename to src/runtime/netpoll_stub.go
index b7a8f2944c3f78690962a96eefb93cfba0d703b7..6c7e79ea372919614f2ee860b1b2a5d8a217f573 100644 (file)
@@ -4,15 +4,12 @@
 
 // +build plan9
 
-#include "runtime.h"
+package runtime
 
 // Polls for ready network connections.
 // Returns list of goroutines that become runnable.
-G*
-runtime·netpoll(bool block)
-{
+func netpoll(block bool) (gp *g) {
        // Implementation for platforms that do not support
        // integrated network poller.
-       USED(block);
-       return nil;
+       return
 }
diff --git a/src/runtime/os1_plan9.go b/src/runtime/os1_plan9.go
new file mode 100644 (file)
index 0000000..0f8da03
--- /dev/null
@@ -0,0 +1,270 @@
+// 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.
+
+package runtime
+
+import "unsafe"
+
+// Called to initialize a new m (including the bootstrap m).
+// Called on the parent thread (main thread in case of bootstrap), can allocate memory.
+func mpreinit(mp *m) {
+       // Initialize stack and goroutine for note handling.
+       mp.gsignal = malg(32 * 1024)
+       mp.gsignal.m = mp
+       mp.notesig = (*int8)(mallocgc(_ERRMAX, nil, _FlagNoScan))
+       // Initialize stack for handling strings from the
+       // errstr system call, as used in package syscall.
+       mp.errstr = (*byte)(mallocgc(_ERRMAX, nil, _FlagNoScan))
+}
+
+// Called to initialize a new m (including the bootstrap m).
+// Called on the new thread, can not allocate memory.
+func minit() {
+       // Mask all SSE floating-point exceptions
+       // when running on the 64-bit kernel.
+       setfpmasks()
+}
+
+// Called from dropm to undo the effect of an minit.
+func unminit() {
+}
+
+var sysstat = []byte("/dev/sysstat\x00")
+
+func getproccount() int32 {
+       var buf [2048]byte
+       fd := open(&sysstat[0], _OREAD, 0)
+       if fd < 0 {
+               return 1
+       }
+       ncpu := int32(0)
+       for {
+               n := read(fd, unsafe.Pointer(&buf), int32(len(buf)))
+               if n <= 0 {
+                       break
+               }
+               for i := int32(0); i < n; i++ {
+                       if buf[i] == '\n' {
+                               ncpu++
+                       }
+               }
+       }
+       close(fd)
+       if ncpu == 0 {
+               ncpu = 1
+       }
+       return ncpu
+}
+
+var pid = []byte("#c/pid\x00")
+
+func getpid() uint64 {
+       var b [20]byte
+       fd := open(&pid[0], 0, 0)
+       if fd >= 0 {
+               read(fd, unsafe.Pointer(&b), int32(len(b)))
+               close(fd)
+       }
+       c := b[:]
+       for c[0] == ' ' || c[0] == '\t' {
+               c = c[1:]
+       }
+       return uint64(atoi(c))
+}
+
+func osinit() {
+       initBloc()
+       ncpu = getproccount()
+       getg().m.procid = getpid()
+       notify(unsafe.Pointer(funcPC(sigtramp)))
+}
+
+func crash() {
+       notify(nil)
+       *(*int)(nil) = 0
+}
+
+var random_data [_HashRandomBytes]byte
+var random_dev = []byte("/dev/random\x00")
+
+//go:nosplit
+func get_random_data(rnd *unsafe.Pointer, rnd_len *int32) {
+       fd := open(&random_dev[0], 0 /* O_RDONLY */, 0)
+       if read(fd, unsafe.Pointer(&random_data), _HashRandomBytes) == _HashRandomBytes {
+               *rnd = unsafe.Pointer(&random_data[0])
+               *rnd_len = _HashRandomBytes
+       } else {
+               *rnd = nil
+               *rnd_len = 0
+       }
+       close(fd)
+}
+
+func goenvs() {
+}
+
+func initsig() {
+}
+
+//go:nosplit
+func osyield() {
+       sleep(0)
+}
+
+//go:nosplit
+func usleep(µs uint32) {
+       ms := int32(µs / 1000)
+       if ms == 0 {
+               ms = 1
+       }
+       sleep(ms)
+}
+
+//go:nosplit
+func nanotime() int64 {
+       var scratch int64
+       ns := nsec(&scratch)
+       // TODO(aram): remove hack after I fix _nsec in the pc64 kernel.
+       if ns == 0 {
+               return scratch
+       }
+       return ns
+}
+
+//go:nosplit
+func itoa(buf []byte, val uint64) []byte {
+       i := len(buf) - 1
+       for val >= 10 {
+               buf[i] = byte(val%10 + '0')
+               i--
+               val /= 10
+       }
+       buf[i] = byte(val + '0')
+       return buf[i:]
+}
+
+var goexits = []byte("go: exit ")
+
+func goexitsall(status *byte) {
+       var buf [_ERRMAX]byte
+       n := copy(buf[:], goexits)
+       n = copy(buf[n:], gostringnocopy(status))
+       pid := getpid()
+       for mp := (*m)(atomicloadp(unsafe.Pointer(&allm))); mp != nil; mp = mp.alllink {
+               if mp.procid != pid {
+                       postnote(mp.procid, buf[:])
+               }
+       }
+}
+
+var procdir = []byte("/proc/")
+var notefile = []byte("/note\x00")
+
+func postnote(pid uint64, msg []byte) int {
+       var buf [128]byte
+       var tmp [32]byte
+       n := copy(buf[:], procdir)
+       n += copy(buf[n:], itoa(tmp[:], pid))
+       copy(buf[n:], notefile)
+       fd := open(&buf[0], _OWRITE, 0)
+       if fd < 0 {
+               return -1
+       }
+       len := findnull(&msg[0])
+       if write(uintptr(fd), (unsafe.Pointer)(&msg[0]), int32(len)) != int64(len) {
+               close(fd)
+               return -1
+       }
+       close(fd)
+       return 0
+}
+
+//go:nosplit
+func exit(e int) {
+       var status []byte
+       if e == 0 {
+               status = []byte("\x00")
+       } else {
+               // build error string
+               var tmp [32]byte
+               status = []byte(gostringnocopy(&itoa(tmp[:], uint64(e))[0]) + "\x00")
+       }
+       goexitsall(&status[0])
+       exits(&status[0])
+}
+
+func newosproc(mp *m, stk unsafe.Pointer) {
+       if false {
+               print("newosproc mp=", mp, " ostk=", &mp, "\n")
+       }
+       pid := rfork(_RFPROC | _RFMEM | _RFNOWAIT)
+       if pid < 0 {
+               gothrow("newosproc: rfork failed")
+       }
+       if pid == 0 {
+               tstart_plan9(mp)
+       }
+}
+
+//go:nosplit
+func semacreate() uintptr {
+       return 1
+}
+
+//go:nosplit
+func semasleep(ns int64) int {
+       _g_ := getg()
+       if ns >= 0 {
+               ms := timediv(ns, 1000000, nil)
+               if ms == 0 {
+                       ms = 1
+               }
+               ret := plan9_tsemacquire(&_g_.m.waitsemacount, ms)
+               if ret == 1 {
+                       return 0 // success
+               }
+               return -1 // timeout or interrupted
+       }
+       for plan9_semacquire(&_g_.m.waitsemacount, 1) < 0 {
+               // interrupted; try again (c.f. lock_sema.go)
+       }
+       return 0 // success
+}
+
+//go:nosplit
+func semawakeup(mp *m) {
+       plan9_semrelease(&mp.waitsemacount, 1)
+}
+
+//go:nosplit
+func read(fd int32, buf unsafe.Pointer, n int32) int32 {
+       return pread(fd, buf, n, -1)
+}
+
+//go:nosplit
+func write(fd uintptr, buf unsafe.Pointer, n int32) int64 {
+       return int64(pwrite(int32(fd), buf, n, -1))
+}
+
+func memlimit() uint64 {
+       return 0
+}
+
+var _badsignal = []byte("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.
+//go:nosplit
+func badsignal2() {
+       pwrite(2, unsafe.Pointer(&_badsignal[0]), int32(len(_badsignal)), -1)
+       exits(&_badsignal[0])
+}
+
+func atoi(b []byte) int {
+       n := 0
+       for len(b) > 0 && '0' <= b[0] && b[0] <= '9' {
+               n = n*10 + int(b[0]) - '0'
+               b = b[1:]
+       }
+       return n
+}
diff --git a/src/runtime/os2_plan9.go b/src/runtime/os2_plan9.go
new file mode 100644 (file)
index 0000000..f64f4c8
--- /dev/null
@@ -0,0 +1,72 @@
+// 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.
+
+// Plan 9-specific system calls
+
+package runtime
+
+// open
+const (
+       _OREAD   = 0
+       _OWRITE  = 1
+       _ORDWR   = 2
+       _OEXEC   = 3
+       _OTRUNC  = 16
+       _OCEXEC  = 32
+       _ORCLOSE = 64
+       _OEXCL   = 0x1000
+)
+
+// rfork
+const (
+       _RFNAMEG  = 1 << 0
+       _RFENVG   = 1 << 1
+       _RFFDG    = 1 << 2
+       _RFNOTEG  = 1 << 3
+       _RFPROC   = 1 << 4
+       _RFMEM    = 1 << 5
+       _RFNOWAIT = 1 << 6
+       _RFCNAMEG = 1 << 10
+       _RFCENVG  = 1 << 11
+       _RFCFDG   = 1 << 12
+       _RFREND   = 1 << 13
+       _RFNOMNT  = 1 << 14
+)
+
+// notify
+const (
+       _NCONT = 0
+       _NDFLT = 1
+)
+
+type uinptr _Plink
+
+type tos struct {
+       prof struct { // Per process profiling
+               pp    *_Plink // known to be 0(ptr)
+               next  *_Plink // known to be 4(ptr)
+               last  *_Plink
+               first *_Plink
+               pid   uint32
+               what  uint32
+       }
+       cyclefreq uint64 // cycle clock frequency if there is one, 0 otherwise
+       kcycles   int64  // cycles spent in kernel
+       pcycles   int64  // cycles spent in process (kernel + user)
+       pid       uint32 // might as well put the pid here
+       clock     uint32
+       // top of stack is here
+}
+
+const (
+       _NSIG   = 14  // number of signals in sigtable array
+       _ERRMAX = 128 // max length of note string
+
+       // Notes in runtime·sigtab that are handled by runtime·sigpanic.
+       _SIGRFAULT = 2
+       _SIGWFAULT = 3
+       _SIGINTDIV = 4
+       _SIGFLOAT  = 5
+       _SIGTRAP   = 6
+)
diff --git a/src/runtime/os_plan9.c b/src/runtime/os_plan9.c
deleted file mode 100644 (file)
index f8c543f..0000000
+++ /dev/null
@@ -1,362 +0,0 @@
-// 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);
-}
index 20e47bf42e5cd20bf451be7e0c3c1dc61f12949f..2dcdfc009ab140f7130198bfb6c7c7ed72ab56ff 100644 (file)
@@ -6,22 +6,49 @@ package runtime
 
 import "unsafe"
 
+//go:noescape
 func pread(fd int32, buf unsafe.Pointer, nbytes int32, offset int64) int32
+
+//go:noescape
 func pwrite(fd int32, buf unsafe.Pointer, nbytes int32, offset int64) int32
+
 func seek(fd int32, offset int64, whence int32) int64
+
+//go:noescape
 func exits(msg *byte)
+
+//go:noescape
 func brk_(addr unsafe.Pointer) uintptr
+
 func sleep(ms int32) int32
+
 func rfork(flags int32) int32
+
+//go:noescape
 func plan9_semacquire(addr *uint32, block int32) int32
+
+//go:noescape
 func plan9_tsemacquire(addr *uint32, ms int32) int32
+
+//go:noescape
 func plan9_semrelease(addr *uint32, count int32) int32
+
+//go:noescape
 func notify(fn unsafe.Pointer) int32
+
 func noted(mode int32) int32
+
+//go:noescape
 func nsec(*int64) int64
+
+//go:noescape
 func sigtramp(ureg, msg unsafe.Pointer)
+
 func setfpmasks()
+
+//go:noescape
 func tstart_plan9(newm *m)
+
 func errstr() string
 
 type _Plink uintptr
diff --git a/src/runtime/os_plan9.h b/src/runtime/os_plan9.h
deleted file mode 100644 (file)
index 6d18024..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-// 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.
-
-// Plan 9-specific system calls
-int32  runtime·pread(int32 fd, void *buf, int32 nbytes, int64 offset);
-int32  runtime·pwrite(int32 fd, void *buf, int32 nbytes, int64 offset);
-int64  runtime·seek(int32 fd, int64 offset, int32 whence);
-void   runtime·exits(int8* msg);
-intptr runtime·brk_(void*);
-int32  runtime·sleep(int32 ms);
-int32  runtime·rfork(int32 flags);
-int32  runtime·plan9_semacquire(uint32 *addr, int32 block);
-int32  runtime·plan9_tsemacquire(uint32 *addr, int32 ms);
-int32  runtime·plan9_semrelease(uint32 *addr, int32 count);
-int32  runtime·notify(void (*fn)(void*, int8*));
-int32  runtime·noted(int32);
-int64  runtime·nsec(int64*);
-void   runtime·sigtramp(void*, int8*);
-void   runtime·sigpanic(void);
-void   runtime·goexitsall(int8*);
-void   runtime·setfpmasks(void);
-void   runtime·tstart_plan9(M *newm);
-
-/* open */
-enum
-{
-       OREAD   = 0,
-       OWRITE  = 1,
-       ORDWR   = 2,
-       OEXEC   = 3,
-       OTRUNC  = 16,
-       OCEXEC  = 32,
-       ORCLOSE = 64,
-       OEXCL   = 0x1000
-};
-
-/* rfork */
-enum
-{
-       RFNAMEG         = (1<<0),
-       RFENVG          = (1<<1),
-       RFFDG           = (1<<2),
-       RFNOTEG         = (1<<3),
-       RFPROC          = (1<<4),
-       RFMEM           = (1<<5),
-       RFNOWAIT        = (1<<6),
-       RFCNAMEG        = (1<<10),
-       RFCENVG         = (1<<11),
-       RFCFDG          = (1<<12),
-       RFREND          = (1<<13),
-       RFNOMNT         = (1<<14)
-};
-
-/* notify */
-enum
-{
-       NCONT   = 0,
-       NDFLT   = 1
-};
-
-typedef struct Tos Tos;
-typedef intptr _Plink;
-
-struct Tos {
-       struct TosProf                  /* Per process profiling */
-       {
-               _Plink  *pp;    /* known to be 0(ptr) */
-               _Plink  *next;  /* known to be 4(ptr) */
-               _Plink  *last;
-               _Plink  *first;
-               uint32  pid;
-               uint32  what;
-       } prof;
-       uint64  cyclefreq;      /* cycle clock frequency if there is one, 0 otherwise */
-       int64   kcycles;        /* cycles spent in kernel */
-       int64   pcycles;        /* cycles spent in process (kernel + user) */
-       uint32  pid;            /* might as well put the pid here */
-       uint32  clock;
-       /* top of stack is here */
-};
-
-enum {
-       NSIG = 14, /* number of signals in runtime·SigTab array */
-       ERRMAX = 128, /* max length of note string */
-
-       /* Notes in runtime·sigtab that are handled by runtime·sigpanic. */
-       SIGRFAULT = 2,
-       SIGWFAULT = 3,
-       SIGINTDIV = 4,
-       SIGFLOAT = 5,
-       SIGTRAP = 6,
-};
diff --git a/src/runtime/os_plan9_386.c b/src/runtime/os_plan9_386.c
deleted file mode 100644 (file)
index 42c6d16..0000000
+++ /dev/null
@@ -1,150 +0,0 @@
-// 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 "defs_GOOS_GOARCH.h"
-#include "os_GOOS.h"
-#include "signals_GOOS.h"
-
-void
-runtime·dumpregs(Ureg *u)
-{
-       runtime·printf("ax     %x\n", u->ax);
-       runtime·printf("bx     %x\n", u->bx);
-       runtime·printf("cx     %x\n", u->cx);
-       runtime·printf("dx     %x\n", u->dx);
-       runtime·printf("di     %x\n", u->di);
-       runtime·printf("si     %x\n", u->si);
-       runtime·printf("bp     %x\n", u->bp);
-       runtime·printf("sp     %x\n", u->sp);
-       runtime·printf("pc     %x\n", u->pc);
-       runtime·printf("flags  %x\n", u->flags);
-       runtime·printf("cs     %x\n", u->cs);
-       runtime·printf("fs     %x\n", u->fs);
-       runtime·printf("gs     %x\n", u->gs);
-}
-
-int32
-runtime·sighandler(void *v, int8 *note, G *gp)
-{
-       uintptr *sp;
-       SigTab *t;
-       bool crash;
-       Ureg *ureg;
-       intgo len, n;
-       int32 sig, flags;
-
-       ureg = (Ureg*)v;
-
-       // The kernel will never pass us a nil note or ureg so we probably
-       // made a mistake somewhere in runtime·sigtramp.
-       if(ureg == nil || note == nil) {
-               runtime·printf("sighandler: ureg %p note %p\n", ureg, note);
-               goto Throw;
-       }
-
-       // Check that the note is no more than ERRMAX bytes (including
-       // the trailing NUL). We should never receive a longer note.
-       len = runtime·findnull((byte*)note);
-       if(len > ERRMAX-1) {
-               runtime·printf("sighandler: note is longer than ERRMAX\n");
-               goto Throw;
-       }
-
-       // See if the note matches one of the patterns in runtime·sigtab.
-       // Notes that do not match any pattern can be handled at a higher
-       // level by the program but will otherwise be ignored.
-       flags = SigNotify;
-       for(sig = 0; sig < nelem(runtime·sigtab); sig++) {
-               t = &runtime·sigtab[sig];
-               n = runtime·findnull((byte*)t->name);
-               if(len < n)
-                       continue;
-               if(runtime·strncmp((byte*)note, (byte*)t->name, n) == 0) {
-                       flags = t->flags;
-                       break;
-               }
-       }
-
-       if(flags & SigGoExit)
-               runtime·exits(note+9); // Strip "go: exit " prefix.
-
-       if(flags & SigPanic) {
-               // Copy the error string from sigtramp's stack into m->notesig so
-               // we can reliably access it from the panic routines.
-               runtime·memmove(g->m->notesig, note, len+1);
-
-               gp->sig = sig;
-               gp->sigpc = ureg->pc;
-
-               // Only push runtime·sigpanic if PC != 0.
-               //
-               // If PC == 0, probably panicked because of a call to a nil func.
-               // Not pushing that onto SP will make the trace look like a call
-               // to runtime·sigpanic instead. (Otherwise the trace will end at
-               // runtime·sigpanic and we won't get to see who faulted).
-               if(ureg->pc != 0) {
-                       sp = (uintptr*)ureg->sp;
-                       *--sp = ureg->pc;
-                       ureg->sp = (uint32)sp;
-               }
-               ureg->pc = (uintptr)runtime·sigpanic;
-               return NCONT;
-       }
-
-       if(flags & SigNotify) {
-               // TODO(ality): See if os/signal wants it.
-               //if(runtime·sigsend(...))
-               //      return NCONT;
-       }
-       if(flags & SigKill)
-               goto Exit;
-       if(!(flags & SigThrow))
-               return NCONT;
-
-Throw:
-       g->m->throwing = 1;
-       g->m->caughtsig = gp;
-       runtime·startpanic();
-
-       runtime·printf("%s\n", note);
-       runtime·printf("PC=%x\n", ureg->pc);
-       runtime·printf("\n");
-
-       if(runtime·gotraceback(&crash)) {
-               runtime·goroutineheader(gp);
-               runtime·tracebacktrap(ureg->pc, ureg->sp, 0, gp);
-               runtime·tracebackothers(gp);
-               runtime·printf("\n");
-               runtime·dumpregs(ureg);
-       }
-       
-       if(crash)
-               runtime·crash();
-
-Exit:
-       runtime·goexitsall(note);
-       runtime·exits(note);
-       return NDFLT; // not reached
-}
-
-void
-runtime·sigenable(uint32 sig)
-{
-       USED(sig);
-}
-
-void
-runtime·sigdisable(uint32 sig)
-{
-       USED(sig);
-}
-
-void
-runtime·resetcpuprofiler(int32 hz)
-{
-       // TODO: Enable profiling interrupts.
-       
-       g->m->profilehz = hz;
-}
diff --git a/src/runtime/os_plan9_386.go b/src/runtime/os_plan9_386.go
new file mode 100644 (file)
index 0000000..7dda139
--- /dev/null
@@ -0,0 +1,131 @@
+// 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.
+
+package runtime
+
+import "unsafe"
+
+func dumpregs(u *ureg) {
+       print("ax    ", hex(u.ax), "\n")
+       print("bx    ", hex(u.bx), "\n")
+       print("cx    ", hex(u.cx), "\n")
+       print("dx    ", hex(u.dx), "\n")
+       print("di    ", hex(u.di), "\n")
+       print("si    ", hex(u.si), "\n")
+       print("bp    ", hex(u.bp), "\n")
+       print("sp    ", hex(u.sp), "\n")
+       print("pc    ", hex(u.pc), "\n")
+       print("flags ", hex(u.flags), "\n")
+       print("cs    ", hex(u.cs), "\n")
+       print("fs    ", hex(u.fs), "\n")
+       print("gs    ", hex(u.gs), "\n")
+}
+
+func sighandler(_ureg *ureg, note *byte, gp *g) int {
+       _g_ := getg()
+       var t sigTabT
+       var docrash bool
+       var length int
+       var sig int
+       var flags int
+
+       // The kernel will never pass us a nil note or ureg so we probably
+       // made a mistake somewhere in sigtramp.
+       if _ureg == nil || note == nil {
+               print("sighandler: ureg ", _ureg, " note ", note, "\n")
+               goto Throw
+       }
+       // Check that the note is no more than ERRMAX bytes (including
+       // the trailing NUL). We should never receive a longer note.
+       length = findnull(note)
+       if length > _ERRMAX-1 {
+               print("sighandler: note is longer than ERRMAX\n")
+               goto Throw
+       }
+       // See if the note matches one of the patterns in sigtab.
+       // Notes that do not match any pattern can be handled at a higher
+       // level by the program but will otherwise be ignored.
+       flags = _SigNotify
+       for sig, t = range sigtable {
+               n := len(t.name)
+               if length < n {
+                       continue
+               }
+               if strncmp(note, &t.name[0], uintptr(n)) == 0 {
+                       flags = t.flags
+                       break
+               }
+       }
+       if flags&_SigGoExit != 0 {
+               exits((*byte)(add(unsafe.Pointer(note), 9))) // Strip "go: exit " prefix.
+       }
+       if flags&_SigPanic != 0 {
+               // Copy the error string from sigtramp's stack into m->notesig so
+               // we can reliably access it from the panic routines.
+               memmove(unsafe.Pointer(_g_.m.notesig), unsafe.Pointer(note), uintptr(length+1))
+               gp.sig = uint32(sig)
+               gp.sigpc = uintptr(_ureg.pc)
+               // Only push sigpanic if PC != 0.
+               //
+               // If PC == 0, probably panicked because of a call to a nil func.
+               // Not pushing that onto SP will make the trace look like a call
+               // to sigpanic instead. (Otherwise the trace will end at
+               // sigpanic and we won't get to see who faulted).
+               if _ureg.pc != 0 {
+                       sp := _ureg.sp
+                       if regSize > ptrSize {
+                               sp -= ptrSize
+                               *(*uintptr)(unsafe.Pointer(uintptr(sp))) = 0
+                       }
+                       sp -= ptrSize
+                       *(*uintptr)(unsafe.Pointer(uintptr(sp))) = uintptr(_ureg.pc)
+                       _ureg.sp = sp
+               }
+               _ureg.pc = uint32(funcPC(sigpanic))
+               return _NCONT
+       }
+       if flags&_SigNotify != 0 {
+               // TODO(ality): See if os/signal wants it.
+               //if(sigsend(...))
+               //      return _NCONT;
+       }
+       if flags&_SigKill != 0 {
+               goto Exit
+       }
+       if flags&_SigThrow == 0 {
+               return _NCONT
+       }
+Throw:
+       _g_.m.throwing = 1
+       _g_.m.caughtsig = gp
+       startpanic()
+       print(gostringnocopy(note), "\n")
+       print("PC=", hex(_ureg.pc), "\n")
+       print("\n")
+       if gotraceback(&docrash) > 0 {
+               goroutineheader(gp)
+               tracebacktrap(uintptr(_ureg.pc), uintptr(_ureg.sp), 0, gp)
+               tracebackothers(gp)
+               print("\n")
+               dumpregs(_ureg)
+       }
+       if docrash {
+               crash()
+       }
+Exit:
+       goexitsall(note)
+       exits(note)
+       return _NDFLT // not reached
+}
+
+func sigenable(sig uint32) {
+}
+
+func sigdisable(sig uint32) {
+}
+
+func resetcpuprofiler(hz int32) {
+       // TODO: Enable profiling interrupts.
+       getg().m.profilehz = hz
+}
diff --git a/src/runtime/os_plan9_amd64.c b/src/runtime/os_plan9_amd64.c
deleted file mode 100644 (file)
index a9dc0eb..0000000
+++ /dev/null
@@ -1,158 +0,0 @@
-// 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 "defs_GOOS_GOARCH.h"
-#include "os_GOOS.h"
-#include "signals_GOOS.h"
-
-void
-runtime·dumpregs(Ureg *u)
-{
-       runtime·printf("ax     %X\n", u->ax);
-       runtime·printf("bx     %X\n", u->bx);
-       runtime·printf("cx     %X\n", u->cx);
-       runtime·printf("dx     %X\n", u->dx);
-       runtime·printf("di     %X\n", u->di);
-       runtime·printf("si     %X\n", u->si);
-       runtime·printf("bp     %X\n", u->bp);
-       runtime·printf("sp     %X\n", u->sp);
-       runtime·printf("r8     %X\n", u->r8);
-       runtime·printf("r9     %X\n", u->r9);
-       runtime·printf("r10    %X\n", u->r10);
-       runtime·printf("r11    %X\n", u->r11);
-       runtime·printf("r12    %X\n", u->r12);
-       runtime·printf("r13    %X\n", u->r13);
-       runtime·printf("r14    %X\n", u->r14);
-       runtime·printf("r15    %X\n", u->r15);
-       runtime·printf("ip     %X\n", u->ip);
-       runtime·printf("flags  %X\n", u->flags);
-       runtime·printf("cs     %X\n", (uint64)u->cs);
-       runtime·printf("fs     %X\n", (uint64)u->fs);
-       runtime·printf("gs     %X\n", (uint64)u->gs);
-}
-
-int32
-runtime·sighandler(void *v, int8 *note, G *gp)
-{
-       uintptr *sp;
-       SigTab *t;
-       bool crash;
-       Ureg *ureg;
-       intgo len, n;
-       int32 sig, flags;
-
-       ureg = (Ureg*)v;
-
-       // The kernel will never pass us a nil note or ureg so we probably
-       // made a mistake somewhere in runtime·sigtramp.
-       if(ureg == nil || note == nil) {
-               runtime·printf("sighandler: ureg %p note %p\n", ureg, note);
-               goto Throw;
-       }
-
-       // Check that the note is no more than ERRMAX bytes (including
-       // the trailing NUL). We should never receive a longer note.
-       len = runtime·findnull((byte*)note);
-       if(len > ERRMAX-1) {
-               runtime·printf("sighandler: note is longer than ERRMAX\n");
-               goto Throw;
-       }
-
-       // See if the note matches one of the patterns in runtime·sigtab.
-       // Notes that do not match any pattern can be handled at a higher
-       // level by the program but will otherwise be ignored.
-       flags = SigNotify;
-       for(sig = 0; sig < nelem(runtime·sigtab); sig++) {
-               t = &runtime·sigtab[sig];
-               n = runtime·findnull((byte*)t->name);
-               if(len < n)
-                       continue;
-               if(runtime·strncmp((byte*)note, (byte*)t->name, n) == 0) {
-                       flags = t->flags;
-                       break;
-               }
-       }
-
-       if(flags & SigGoExit)
-               runtime·exits(note+9); // Strip "go: exit " prefix.
-
-       if(flags & SigPanic) {
-               // Copy the error string from sigtramp's stack into m->notesig so
-               // we can reliably access it from the panic routines.
-               runtime·memmove(g->m->notesig, note, len+1);
-
-               gp->sig = sig;
-               gp->sigpc = ureg->ip;
-
-               // Only push runtime·sigpanic if PC != 0.
-               //
-               // If PC == 0, probably panicked because of a call to a nil func.
-               // Not pushing that onto SP will make the trace look like a call
-               // to runtime·sigpanic instead. (Otherwise the trace will end at
-               // runtime·sigpanic and we won't get to see who faulted).
-               if(ureg->ip != 0) {
-                       sp = (uintptr*)ureg->sp;
-                       *--sp = ureg->ip;
-                       ureg->sp = (uint64)sp;
-               }
-               ureg->ip = (uintptr)runtime·sigpanic;
-               return NCONT;
-       }
-
-       if(flags & SigNotify) {
-               // TODO(ality): See if os/signal wants it.
-               //if(runtime·sigsend(...))
-               //      return NCONT;
-       }
-       if(flags & SigKill)
-               goto Exit;
-       if(!(flags & SigThrow))
-               return NCONT;
-
-Throw:
-       g->m->throwing = 1;
-       g->m->caughtsig = gp;
-       runtime·startpanic();
-
-       runtime·printf("%s\n", note);
-       runtime·printf("PC=%X\n", ureg->ip);
-       runtime·printf("\n");
-
-       if(runtime·gotraceback(&crash)) {
-               runtime·goroutineheader(gp);
-               runtime·tracebacktrap(ureg->ip, ureg->sp, 0, gp);
-               runtime·tracebackothers(gp);
-               runtime·printf("\n");
-               runtime·dumpregs(ureg);
-       }
-       
-       if(crash)
-               runtime·crash();
-
-Exit:
-       runtime·goexitsall(note);
-       runtime·exits(note);
-       return NDFLT; // not reached
-}
-
-void
-runtime·sigenable(uint32 sig)
-{
-       USED(sig);
-}
-
-void
-runtime·sigdisable(uint32 sig)
-{
-       USED(sig);
-}
-
-void
-runtime·resetcpuprofiler(int32 hz)
-{
-       // TODO: Enable profiling interrupts.
-       
-       g->m->profilehz = hz;
-}
diff --git a/src/runtime/os_plan9_amd64.go b/src/runtime/os_plan9_amd64.go
new file mode 100644 (file)
index 0000000..8727dcc
--- /dev/null
@@ -0,0 +1,139 @@
+// 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.
+
+package runtime
+
+import "unsafe"
+
+func dumpregs(u *ureg) {
+       print("ax    ", hex(u.ax), "\n")
+       print("bx    ", hex(u.bx), "\n")
+       print("cx    ", hex(u.cx), "\n")
+       print("dx    ", hex(u.dx), "\n")
+       print("di    ", hex(u.di), "\n")
+       print("si    ", hex(u.si), "\n")
+       print("bp    ", hex(u.bp), "\n")
+       print("sp    ", hex(u.sp), "\n")
+       print("r8    ", hex(u.r8), "\n")
+       print("r9    ", hex(u.r9), "\n")
+       print("r10   ", hex(u.r10), "\n")
+       print("r11   ", hex(u.r11), "\n")
+       print("r12   ", hex(u.r12), "\n")
+       print("r13   ", hex(u.r13), "\n")
+       print("r14   ", hex(u.r14), "\n")
+       print("r15   ", hex(u.r15), "\n")
+       print("ip    ", hex(u.ip), "\n")
+       print("flags ", hex(u.flags), "\n")
+       print("cs    ", hex(uint64(u.cs)), "\n")
+       print("fs    ", hex(uint64(u.fs)), "\n")
+       print("gs    ", hex(uint64(u.gs)), "\n")
+}
+
+func sighandler(_ureg *ureg, note *byte, gp *g) int {
+       _g_ := getg()
+       var t sigTabT
+       var docrash bool
+       var length int
+       var sig int
+       var flags int
+
+       // The kernel will never pass us a nil note or ureg so we probably
+       // made a mistake somewhere in sigtramp.
+       if _ureg == nil || note == nil {
+               print("sighandler: ureg ", _ureg, " note ", note, "\n")
+               goto Throw
+       }
+       // Check that the note is no more than ERRMAX bytes (including
+       // the trailing NUL). We should never receive a longer note.
+       length = findnull(note)
+       if length > _ERRMAX-1 {
+               print("sighandler: note is longer than ERRMAX\n")
+               goto Throw
+       }
+       // See if the note matches one of the patterns in sigtab.
+       // Notes that do not match any pattern can be handled at a higher
+       // level by the program but will otherwise be ignored.
+       flags = _SigNotify
+       for sig, t = range sigtable {
+               n := len(t.name)
+               if length < n {
+                       continue
+               }
+               if strncmp(note, &t.name[0], uintptr(n)) == 0 {
+                       flags = t.flags
+                       break
+               }
+       }
+       if flags&_SigGoExit != 0 {
+               exits((*byte)(add(unsafe.Pointer(note), 9))) // Strip "go: exit " prefix.
+       }
+       if flags&_SigPanic != 0 {
+               // Copy the error string from sigtramp's stack into m->notesig so
+               // we can reliably access it from the panic routines.
+               memmove(unsafe.Pointer(_g_.m.notesig), unsafe.Pointer(note), uintptr(length+1))
+               gp.sig = uint32(sig)
+               gp.sigpc = uintptr(_ureg.ip)
+               // Only push sigpanic if PC != 0.
+               //
+               // If PC == 0, probably panicked because of a call to a nil func.
+               // Not pushing that onto SP will make the trace look like a call
+               // to sigpanic instead. (Otherwise the trace will end at
+               // sigpanic and we won't get to see who faulted).
+               if _ureg.ip != 0 {
+                       sp := _ureg.sp
+                       if regSize > ptrSize {
+                               sp -= ptrSize
+                               *(*uintptr)(unsafe.Pointer(uintptr(sp))) = 0
+                       }
+                       sp -= ptrSize
+                       *(*uintptr)(unsafe.Pointer(uintptr(sp))) = uintptr(_ureg.ip)
+                       _ureg.sp = sp
+               }
+               _ureg.ip = uint64(funcPC(sigpanic))
+               return _NCONT
+       }
+       if flags&_SigNotify != 0 {
+               // TODO(ality): See if os/signal wants it.
+               //if(sigsend(...))
+               //      return _NCONT;
+       }
+       if flags&_SigKill != 0 {
+               goto Exit
+       }
+       if flags&_SigThrow == 0 {
+               return _NCONT
+       }
+Throw:
+       _g_.m.throwing = 1
+       _g_.m.caughtsig = gp
+       startpanic()
+       print(gostringnocopy(note), "\n")
+       print("PC=", hex(_ureg.ip), "\n")
+       print("\n")
+       if gotraceback(&docrash) > 0 {
+               goroutineheader(gp)
+               tracebacktrap(uintptr(_ureg.ip), uintptr(_ureg.sp), 0, gp)
+               tracebackothers(gp)
+               print("\n")
+               dumpregs(_ureg)
+       }
+       if docrash {
+               crash()
+       }
+Exit:
+       goexitsall(note)
+       exits(note)
+       return _NDFLT // not reached
+}
+
+func sigenable(sig uint32) {
+}
+
+func sigdisable(sig uint32) {
+}
+
+func resetcpuprofiler(hz int32) {
+       // TODO: Enable profiling interrupts.
+       getg().m.profilehz = hz
+}
similarity index 54%
rename from src/runtime/signals_plan9.h
rename to src/runtime/signal_plan9.go
index 4ee8e542c901fc511bbda89a2e4a8a1ff05ac1d2..37d24359bfdf3578666956a062149d6e1c92db2f 100644 (file)
@@ -2,62 +2,53 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-#include "textflag.h"
+package runtime
 
-#define N SigNotify
-#define K SigKill
-#define T SigThrow
-#define P SigPanic
-#define E SigGoExit
+type sigTabT struct {
+       flags int
+       name  []byte
+}
 
 // Incoming notes are compared against this table using strncmp, so the
 // order matters: longer patterns must appear before their prefixes.
-// There are #defined SIG constants in os_plan9.h for the table index of
-// some of these.
+// There are _SIG constants in os2_plan9.go for the table index of some
+// of these.
 //
 // If you add entries to this table, you must respect the prefix ordering
-// and also update the constant values is os_plan9.h.
-
-#pragma dataflag NOPTR
-SigTab runtime·sigtab[] = {
+// and also update the constant values is os2_plan9.go.
+var sigtable = [...]sigTabT{
        // Traps that we cannot be recovered.
-       T,      "sys: trap: debug exception",
-       T,      "sys: trap: invalid opcode",
+       {_SigThrow, []byte("sys: trap: debug exception")},
+       {_SigThrow, []byte("sys: trap: invalid opcode")},
 
        // We can recover from some memory errors in runtime·sigpanic.
-       P,      "sys: trap: fault read addr",   // SIGRFAULT
-       P,      "sys: trap: fault write addr",  // SIGWFAULT
+       {_SigPanic, []byte("sys: trap: fault read addr")},  // SIGRFAULT
+       {_SigPanic, []byte("sys: trap: fault write addr")}, // SIGWFAULT
 
        // We can also recover from math errors.
-       P,      "sys: trap: divide error",      // SIGINTDIV
-       P,      "sys: fp:",     // SIGFLOAT
+       {_SigPanic, []byte("sys: trap: divide error")}, // SIGINTDIV
+       {_SigPanic, []byte("sys: fp:")},                // SIGFLOAT
 
        // All other traps are normally handled as if they were marked SigThrow.
        // We mark them SigPanic here so that debug.SetPanicOnFault will work.
-       P,      "sys: trap:",   // SIGTRAP
+       {_SigPanic, []byte("sys: trap:")}, // SIGTRAP
 
        // Writes to a closed pipe can be handled if desired, otherwise they're ignored.
-       N,      "sys: write on closed pipe",
+       {_SigNotify, []byte("sys: write on closed pipe")},
 
        // Other system notes are more serious and cannot be recovered.
-       T,      "sys:",
+       {_SigThrow, []byte("sys:")},
 
        // Issued to all other procs when calling runtime·exit.
-       E,      "go: exit ",
+       {_SigGoExit, []byte("go: exit ")},
 
        // Kill is sent by external programs to cause an exit.
-       K,      "kill",
+       {_SigKill, []byte("kill")},
 
        // Interrupts can be handled if desired, otherwise they cause an exit.
-       N+K,    "interrupt",
-       N+K,    "hangup",
+       {_SigNotify + _SigKill, []byte("interrupt")},
+       {_SigNotify + _SigKill, []byte("hangup")},
 
        // Alarms can be handled if desired, otherwise they're ignored.
-       N,      "alarm",
-};
-
-#undef N
-#undef K
-#undef T
-#undef P
-#undef E
+       {_SigNotify, []byte("alarm")},
+}
index 74cc5c6a7c49e1355ddfb47758d00aa19bc9168b..60751dd343dc76fbff9c3045e3c2b65fb7b0a35e 100644 (file)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build !plan9
 // +build !solaris
 // +build !windows
 // +build !nacl
diff --git a/src/runtime/stubs3.go b/src/runtime/stubs3.go
new file mode 100644 (file)
index 0000000..ffaa287
--- /dev/null
@@ -0,0 +1,12 @@
+// Copyright 2014 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.
+
+// +build plan9
+
+package runtime
+
+func close(fd int32) int32
+
+//go:noescape
+func open(name *byte, mode, perm int32) int32