mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
[dev.cc] runtime: convert Plan 9 port to Go
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
This commit is contained in:
parent
ad8179281d
commit
e9c57d8a2d
18 changed files with 756 additions and 923 deletions
|
|
@ -1,5 +1,7 @@
|
||||||
package runtime
|
package runtime
|
||||||
|
|
||||||
|
const _PAGESIZE = 0x1000
|
||||||
|
|
||||||
type ureg struct {
|
type ureg struct {
|
||||||
di uint32 /* general registers */
|
di uint32 /* general registers */
|
||||||
si uint32 /* ... */
|
si uint32 /* ... */
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
package runtime
|
package runtime
|
||||||
|
|
||||||
|
const _PAGESIZE = 0x1000
|
||||||
|
|
||||||
type ureg struct {
|
type ureg struct {
|
||||||
ax uint64
|
ax uint64
|
||||||
bx uint64
|
bx uint64
|
||||||
|
|
|
||||||
|
|
@ -54,3 +54,6 @@ func gogetenv(key string) string {
|
||||||
sp.len = int(r)
|
sp.len = int(r)
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _cgo_setenv unsafe.Pointer // pointer to C function
|
||||||
|
var _cgo_unsetenv unsafe.Pointer // pointer to C function
|
||||||
|
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
70
src/runtime/mem_plan9.go
Normal file
70
src/runtime/mem_plan9.go
Normal file
|
|
@ -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)
|
||||||
|
}
|
||||||
|
|
@ -4,15 +4,12 @@
|
||||||
|
|
||||||
// +build plan9
|
// +build plan9
|
||||||
|
|
||||||
#include "runtime.h"
|
package runtime
|
||||||
|
|
||||||
// Polls for ready network connections.
|
// Polls for ready network connections.
|
||||||
// Returns list of goroutines that become runnable.
|
// Returns list of goroutines that become runnable.
|
||||||
G*
|
func netpoll(block bool) (gp *g) {
|
||||||
runtime·netpoll(bool block)
|
|
||||||
{
|
|
||||||
// Implementation for platforms that do not support
|
// Implementation for platforms that do not support
|
||||||
// integrated network poller.
|
// integrated network poller.
|
||||||
USED(block);
|
return
|
||||||
return nil;
|
|
||||||
}
|
}
|
||||||
270
src/runtime/os1_plan9.go
Normal file
270
src/runtime/os1_plan9.go
Normal file
|
|
@ -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
|
||||||
|
}
|
||||||
72
src/runtime/os2_plan9.go
Normal file
72
src/runtime/os2_plan9.go
Normal file
|
|
@ -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
|
||||||
|
)
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
|
|
@ -6,22 +6,49 @@ package runtime
|
||||||
|
|
||||||
import "unsafe"
|
import "unsafe"
|
||||||
|
|
||||||
|
//go:noescape
|
||||||
func pread(fd int32, buf unsafe.Pointer, nbytes int32, offset int64) int32
|
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 pwrite(fd int32, buf unsafe.Pointer, nbytes int32, offset int64) int32
|
||||||
|
|
||||||
func seek(fd int32, offset int64, whence int32) int64
|
func seek(fd int32, offset int64, whence int32) int64
|
||||||
|
|
||||||
|
//go:noescape
|
||||||
func exits(msg *byte)
|
func exits(msg *byte)
|
||||||
|
|
||||||
|
//go:noescape
|
||||||
func brk_(addr unsafe.Pointer) uintptr
|
func brk_(addr unsafe.Pointer) uintptr
|
||||||
|
|
||||||
func sleep(ms int32) int32
|
func sleep(ms int32) int32
|
||||||
|
|
||||||
func rfork(flags int32) int32
|
func rfork(flags int32) int32
|
||||||
|
|
||||||
|
//go:noescape
|
||||||
func plan9_semacquire(addr *uint32, block int32) int32
|
func plan9_semacquire(addr *uint32, block int32) int32
|
||||||
|
|
||||||
|
//go:noescape
|
||||||
func plan9_tsemacquire(addr *uint32, ms int32) int32
|
func plan9_tsemacquire(addr *uint32, ms int32) int32
|
||||||
|
|
||||||
|
//go:noescape
|
||||||
func plan9_semrelease(addr *uint32, count int32) int32
|
func plan9_semrelease(addr *uint32, count int32) int32
|
||||||
|
|
||||||
|
//go:noescape
|
||||||
func notify(fn unsafe.Pointer) int32
|
func notify(fn unsafe.Pointer) int32
|
||||||
|
|
||||||
func noted(mode int32) int32
|
func noted(mode int32) int32
|
||||||
|
|
||||||
|
//go:noescape
|
||||||
func nsec(*int64) int64
|
func nsec(*int64) int64
|
||||||
|
|
||||||
|
//go:noescape
|
||||||
func sigtramp(ureg, msg unsafe.Pointer)
|
func sigtramp(ureg, msg unsafe.Pointer)
|
||||||
|
|
||||||
func setfpmasks()
|
func setfpmasks()
|
||||||
|
|
||||||
|
//go:noescape
|
||||||
func tstart_plan9(newm *m)
|
func tstart_plan9(newm *m)
|
||||||
|
|
||||||
func errstr() string
|
func errstr() string
|
||||||
|
|
||||||
type _Plink uintptr
|
type _Plink uintptr
|
||||||
|
|
|
||||||
|
|
@ -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,
|
|
||||||
};
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
131
src/runtime/os_plan9_386.go
Normal file
131
src/runtime/os_plan9_386.go
Normal file
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
139
src/runtime/os_plan9_amd64.go
Normal file
139
src/runtime/os_plan9_amd64.go
Normal file
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
@ -2,62 +2,53 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
#include "textflag.h"
|
package runtime
|
||||||
|
|
||||||
#define N SigNotify
|
type sigTabT struct {
|
||||||
#define K SigKill
|
flags int
|
||||||
#define T SigThrow
|
name []byte
|
||||||
#define P SigPanic
|
}
|
||||||
#define E SigGoExit
|
|
||||||
|
|
||||||
// Incoming notes are compared against this table using strncmp, so the
|
// Incoming notes are compared against this table using strncmp, so the
|
||||||
// order matters: longer patterns must appear before their prefixes.
|
// order matters: longer patterns must appear before their prefixes.
|
||||||
// There are #defined SIG constants in os_plan9.h for the table index of
|
// There are _SIG constants in os2_plan9.go for the table index of some
|
||||||
// some of these.
|
// of these.
|
||||||
//
|
//
|
||||||
// If you add entries to this table, you must respect the prefix ordering
|
// If you add entries to this table, you must respect the prefix ordering
|
||||||
// and also update the constant values is os_plan9.h.
|
// and also update the constant values is os2_plan9.go.
|
||||||
|
var sigtable = [...]sigTabT{
|
||||||
#pragma dataflag NOPTR
|
|
||||||
SigTab runtime·sigtab[] = {
|
|
||||||
// Traps that we cannot be recovered.
|
// Traps that we cannot be recovered.
|
||||||
T, "sys: trap: debug exception",
|
{_SigThrow, []byte("sys: trap: debug exception")},
|
||||||
T, "sys: trap: invalid opcode",
|
{_SigThrow, []byte("sys: trap: invalid opcode")},
|
||||||
|
|
||||||
// We can recover from some memory errors in runtime·sigpanic.
|
// We can recover from some memory errors in runtime·sigpanic.
|
||||||
P, "sys: trap: fault read addr", // SIGRFAULT
|
{_SigPanic, []byte("sys: trap: fault read addr")}, // SIGRFAULT
|
||||||
P, "sys: trap: fault write addr", // SIGWFAULT
|
{_SigPanic, []byte("sys: trap: fault write addr")}, // SIGWFAULT
|
||||||
|
|
||||||
// We can also recover from math errors.
|
// We can also recover from math errors.
|
||||||
P, "sys: trap: divide error", // SIGINTDIV
|
{_SigPanic, []byte("sys: trap: divide error")}, // SIGINTDIV
|
||||||
P, "sys: fp:", // SIGFLOAT
|
{_SigPanic, []byte("sys: fp:")}, // SIGFLOAT
|
||||||
|
|
||||||
// All other traps are normally handled as if they were marked SigThrow.
|
// All other traps are normally handled as if they were marked SigThrow.
|
||||||
// We mark them SigPanic here so that debug.SetPanicOnFault will work.
|
// 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.
|
// 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.
|
// Other system notes are more serious and cannot be recovered.
|
||||||
T, "sys:",
|
{_SigThrow, []byte("sys:")},
|
||||||
|
|
||||||
// Issued to all other procs when calling runtime·exit.
|
// 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.
|
// 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.
|
// Interrupts can be handled if desired, otherwise they cause an exit.
|
||||||
N+K, "interrupt",
|
{_SigNotify + _SigKill, []byte("interrupt")},
|
||||||
N+K, "hangup",
|
{_SigNotify + _SigKill, []byte("hangup")},
|
||||||
|
|
||||||
// Alarms can be handled if desired, otherwise they're ignored.
|
// Alarms can be handled if desired, otherwise they're ignored.
|
||||||
N, "alarm",
|
{_SigNotify, []byte("alarm")},
|
||||||
};
|
}
|
||||||
|
|
||||||
#undef N
|
|
||||||
#undef K
|
|
||||||
#undef T
|
|
||||||
#undef P
|
|
||||||
#undef E
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build !plan9
|
||||||
// +build !solaris
|
// +build !solaris
|
||||||
// +build !windows
|
// +build !windows
|
||||||
// +build !nacl
|
// +build !nacl
|
||||||
|
|
|
||||||
12
src/runtime/stubs3.go
Normal file
12
src/runtime/stubs3.go
Normal file
|
|
@ -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
|
||||||
Loading…
Add table
Add a link
Reference in a new issue