aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/os_plan9.go
diff options
context:
space:
mode:
authorBrad Fitzpatrick <bradfitz@golang.org>2016-05-06 16:07:11 +0000
committerBrad Fitzpatrick <bradfitz@golang.org>2016-05-06 17:47:44 +0000
commit131231b8db26b38c9c2fdc52fb788241f5c2de51 (patch)
treefe1caec40ca0ffa74866d2a7ea612053695b0940 /src/runtime/os_plan9.go
parent1ff57143af65014c80e39cc0f19cd97a455f5b49 (diff)
downloadgo-131231b8db26b38c9c2fdc52fb788241f5c2de51.tar.gz
go-131231b8db26b38c9c2fdc52fb788241f5c2de51.zip
os: rename remaining four os1_*.go files to os_*.go
Change-Id: Ice9c234960adc7857c8370b777a0b18e29d59281 Reviewed-on: https://go-review.googlesource.com/22853 Reviewed-by: Ian Lance Taylor <iant@golang.org> Run-TryBot: Ian Lance Taylor <iant@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org>
Diffstat (limited to 'src/runtime/os_plan9.go')
-rw-r--r--src/runtime/os_plan9.go438
1 files changed, 438 insertions, 0 deletions
diff --git a/src/runtime/os_plan9.go b/src/runtime/os_plan9.go
new file mode 100644
index 0000000000..2f3a0d1a19
--- /dev/null
+++ b/src/runtime/os_plan9.go
@@ -0,0 +1,438 @@
+// 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 (
+ "runtime/internal/atomic"
+ "unsafe"
+)
+
+type mOS struct {
+ waitsemacount uint32
+ notesig *int8
+ errstr *byte
+}
+
+func closefd(fd int32) int32
+
+//go:noescape
+func open(name *byte, mode, perm int32) int32
+
+//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) int32
+
+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
+
+//go:linkname os_sigpipe os.sigpipe
+func os_sigpipe() {
+ throw("too many writes on closed pipe")
+}
+
+func sigpanic() {
+ g := getg()
+ if !canpanic(g) {
+ throw("unexpected signal during runtime execution")
+ }
+
+ note := gostringnocopy((*byte)(unsafe.Pointer(g.m.notesig)))
+ switch g.sig {
+ case _SIGRFAULT, _SIGWFAULT:
+ i := index(note, "addr=")
+ if i >= 0 {
+ i += 5
+ } else if i = index(note, "va="); i >= 0 {
+ i += 3
+ } else {
+ panicmem()
+ }
+ addr := note[i:]
+ g.sigcode1 = uintptr(atolwhex(addr))
+ if g.sigcode1 < 0x1000 || g.paniconfault {
+ panicmem()
+ }
+ print("unexpected fault address ", hex(g.sigcode1), "\n")
+ throw("fault")
+ case _SIGTRAP:
+ if g.paniconfault {
+ panicmem()
+ }
+ throw(note)
+ case _SIGINTDIV:
+ panicdivide()
+ case _SIGFLOAT:
+ panicfloat()
+ default:
+ panic(errorString(note))
+ }
+}
+
+func atolwhex(p string) int64 {
+ for hasprefix(p, " ") || hasprefix(p, "\t") {
+ p = p[1:]
+ }
+ neg := false
+ if hasprefix(p, "-") || hasprefix(p, "+") {
+ neg = p[0] == '-'
+ p = p[1:]
+ for hasprefix(p, " ") || hasprefix(p, "\t") {
+ p = p[1:]
+ }
+ }
+ var n int64
+ switch {
+ case hasprefix(p, "0x"), hasprefix(p, "0X"):
+ p = p[2:]
+ for ; len(p) > 0; p = p[1:] {
+ if '0' <= p[0] && p[0] <= '9' {
+ n = n*16 + int64(p[0]-'0')
+ } else if 'a' <= p[0] && p[0] <= 'f' {
+ n = n*16 + int64(p[0]-'a'+10)
+ } else if 'A' <= p[0] && p[0] <= 'F' {
+ n = n*16 + int64(p[0]-'A'+10)
+ } else {
+ break
+ }
+ }
+ case hasprefix(p, "0"):
+ for ; len(p) > 0 && '0' <= p[0] && p[0] <= '7'; p = p[1:] {
+ n = n*8 + int64(p[0]-'0')
+ }
+ default:
+ for ; len(p) > 0 && '0' <= p[0] && p[0] <= '9'; p = p[1:] {
+ n = n*10 + int64(p[0]-'0')
+ }
+ }
+ if neg {
+ n = -n
+ }
+ return n
+}
+
+type sigset struct{}
+
+// 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, true))
+ // Initialize stack for handling strings from the
+ // errstr system call, as used in package syscall.
+ mp.errstr = (*byte)(mallocgc(_ERRMAX, nil, true))
+}
+
+func msigsave(mp *m) {
+}
+
+func msigrestore(sigmask sigset) {
+}
+
+func sigblock() {
+}
+
+// Called to initialize a new m (including the bootstrap m).
+// Called on the new thread, cannot allocate memory.
+func minit() {
+ if atomic.Load(&exiting) != 0 {
+ exits(&emptystatus[0])
+ }
+ // 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++
+ }
+ }
+ }
+ closefd(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)))
+ closefd(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
+}
+
+//go:nosplit
+func getRandomData(r []byte) {
+ extendRandom(r, 0)
+}
+
+func goenvs() {
+}
+
+func initsig(preinit bool) {
+}
+
+//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 ")
+var emptystatus = []byte("\x00")
+var exiting uint32
+
+func goexitsall(status *byte) {
+ var buf [_ERRMAX]byte
+ if !atomic.Cas(&exiting, 0, 1) {
+ return
+ }
+ getg().m.locks++
+ n := copy(buf[:], goexits)
+ n = copy(buf[n:], gostringnocopy(status))
+ pid := getpid()
+ for mp := (*m)(atomic.Loadp(unsafe.Pointer(&allm))); mp != nil; mp = mp.alllink {
+ if mp.procid != 0 && mp.procid != pid {
+ postnote(mp.procid, buf[:])
+ }
+ }
+ getg().m.locks--
+}
+
+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) {
+ closefd(fd)
+ return -1
+ }
+ closefd(fd)
+ return 0
+}
+
+//go:nosplit
+func exit(e int) {
+ var status []byte
+ if e == 0 {
+ status = emptystatus
+ } else {
+ // build error string
+ var tmp [32]byte
+ status = append(itoa(tmp[:len(tmp)-1], uint64(e)), 0)
+ }
+ goexitsall(&status[0])
+ exits(&status[0])
+}
+
+// May run with m.p==nil, so write barriers are not allowed.
+//go:nowritebarrier
+func newosproc(mp *m, stk unsafe.Pointer) {
+ if false {
+ print("newosproc mp=", mp, " ostk=", &mp, "\n")
+ }
+ pid := rfork(_RFPROC | _RFMEM | _RFNOWAIT)
+ if pid < 0 {
+ throw("newosproc: rfork failed")
+ }
+ if pid == 0 {
+ tstart_plan9(mp)
+ }
+}
+
+//go:nosplit
+func semacreate(mp *m) {
+}
+
+//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 raisebadsignal(sig int32) {
+ badsignal2()
+}
+
+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
+}
+
+func signame(sig uint32) string {
+ if sig >= uint32(len(sigtable)) {
+ return ""
+ }
+ return sigtable[sig].name
+}