rsc.io/go@v0.0.0-20150416155037-e040fd465409/src/runtime/os1_plan9.go (about) 1 // Copyright 2010 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package runtime 6 7 import "unsafe" 8 9 // Called to initialize a new m (including the bootstrap m). 10 // Called on the parent thread (main thread in case of bootstrap), can allocate memory. 11 func mpreinit(mp *m) { 12 // Initialize stack and goroutine for note handling. 13 mp.gsignal = malg(32 * 1024) 14 mp.gsignal.m = mp 15 mp.notesig = (*int8)(mallocgc(_ERRMAX, nil, _FlagNoScan)) 16 // Initialize stack for handling strings from the 17 // errstr system call, as used in package syscall. 18 mp.errstr = (*byte)(mallocgc(_ERRMAX, nil, _FlagNoScan)) 19 } 20 21 // Called to initialize a new m (including the bootstrap m). 22 // Called on the new thread, can not allocate memory. 23 func minit() { 24 // Mask all SSE floating-point exceptions 25 // when running on the 64-bit kernel. 26 setfpmasks() 27 } 28 29 // Called from dropm to undo the effect of an minit. 30 func unminit() { 31 } 32 33 var sysstat = []byte("/dev/sysstat\x00") 34 35 func getproccount() int32 { 36 var buf [2048]byte 37 fd := open(&sysstat[0], _OREAD, 0) 38 if fd < 0 { 39 return 1 40 } 41 ncpu := int32(0) 42 for { 43 n := read(fd, unsafe.Pointer(&buf), int32(len(buf))) 44 if n <= 0 { 45 break 46 } 47 for i := int32(0); i < n; i++ { 48 if buf[i] == '\n' { 49 ncpu++ 50 } 51 } 52 } 53 closefd(fd) 54 if ncpu == 0 { 55 ncpu = 1 56 } 57 return ncpu 58 } 59 60 var pid = []byte("#c/pid\x00") 61 62 func getpid() uint64 { 63 var b [20]byte 64 fd := open(&pid[0], 0, 0) 65 if fd >= 0 { 66 read(fd, unsafe.Pointer(&b), int32(len(b))) 67 closefd(fd) 68 } 69 c := b[:] 70 for c[0] == ' ' || c[0] == '\t' { 71 c = c[1:] 72 } 73 return uint64(_atoi(c)) 74 } 75 76 func osinit() { 77 initBloc() 78 ncpu = getproccount() 79 getg().m.procid = getpid() 80 notify(unsafe.Pointer(funcPC(sigtramp))) 81 } 82 83 func crash() { 84 notify(nil) 85 *(*int)(nil) = 0 86 } 87 88 //go:nosplit 89 func getRandomData(r []byte) { 90 extendRandom(r, 0) 91 } 92 93 func goenvs() { 94 } 95 96 func initsig() { 97 } 98 99 //go:nosplit 100 func osyield() { 101 sleep(0) 102 } 103 104 //go:nosplit 105 func usleep(µs uint32) { 106 ms := int32(µs / 1000) 107 if ms == 0 { 108 ms = 1 109 } 110 sleep(ms) 111 } 112 113 //go:nosplit 114 func nanotime() int64 { 115 var scratch int64 116 ns := nsec(&scratch) 117 // TODO(aram): remove hack after I fix _nsec in the pc64 kernel. 118 if ns == 0 { 119 return scratch 120 } 121 return ns 122 } 123 124 //go:nosplit 125 func itoa(buf []byte, val uint64) []byte { 126 i := len(buf) - 1 127 for val >= 10 { 128 buf[i] = byte(val%10 + '0') 129 i-- 130 val /= 10 131 } 132 buf[i] = byte(val + '0') 133 return buf[i:] 134 } 135 136 var goexits = []byte("go: exit ") 137 138 func goexitsall(status *byte) { 139 var buf [_ERRMAX]byte 140 n := copy(buf[:], goexits) 141 n = copy(buf[n:], gostringnocopy(status)) 142 pid := getpid() 143 for mp := (*m)(atomicloadp(unsafe.Pointer(&allm))); mp != nil; mp = mp.alllink { 144 if mp.procid != pid { 145 postnote(mp.procid, buf[:]) 146 } 147 } 148 } 149 150 var procdir = []byte("/proc/") 151 var notefile = []byte("/note\x00") 152 153 func postnote(pid uint64, msg []byte) int { 154 var buf [128]byte 155 var tmp [32]byte 156 n := copy(buf[:], procdir) 157 n += copy(buf[n:], itoa(tmp[:], pid)) 158 copy(buf[n:], notefile) 159 fd := open(&buf[0], _OWRITE, 0) 160 if fd < 0 { 161 return -1 162 } 163 len := findnull(&msg[0]) 164 if write(uintptr(fd), (unsafe.Pointer)(&msg[0]), int32(len)) != int64(len) { 165 closefd(fd) 166 return -1 167 } 168 closefd(fd) 169 return 0 170 } 171 172 //go:nosplit 173 func exit(e int) { 174 var status []byte 175 if e == 0 { 176 status = []byte("\x00") 177 } else { 178 // build error string 179 var tmp [32]byte 180 status = []byte(gostringnocopy(&itoa(tmp[:len(tmp)-1], uint64(e))[0])) 181 } 182 goexitsall(&status[0]) 183 exits(&status[0]) 184 } 185 186 // May run with m.p==nil, so write barriers are not allowed. 187 //go:nowritebarrier 188 func newosproc(mp *m, stk unsafe.Pointer) { 189 if false { 190 print("newosproc mp=", mp, " ostk=", &mp, "\n") 191 } 192 pid := rfork(_RFPROC | _RFMEM | _RFNOWAIT) 193 if pid < 0 { 194 throw("newosproc: rfork failed") 195 } 196 if pid == 0 { 197 tstart_plan9(mp) 198 } 199 } 200 201 //go:nosplit 202 func semacreate() uintptr { 203 return 1 204 } 205 206 //go:nosplit 207 func semasleep(ns int64) int { 208 _g_ := getg() 209 if ns >= 0 { 210 ms := timediv(ns, 1000000, nil) 211 if ms == 0 { 212 ms = 1 213 } 214 ret := plan9_tsemacquire(&_g_.m.waitsemacount, ms) 215 if ret == 1 { 216 return 0 // success 217 } 218 return -1 // timeout or interrupted 219 } 220 for plan9_semacquire(&_g_.m.waitsemacount, 1) < 0 { 221 // interrupted; try again (c.f. lock_sema.go) 222 } 223 return 0 // success 224 } 225 226 //go:nosplit 227 func semawakeup(mp *m) { 228 plan9_semrelease(&mp.waitsemacount, 1) 229 } 230 231 //go:nosplit 232 func read(fd int32, buf unsafe.Pointer, n int32) int32 { 233 return pread(fd, buf, n, -1) 234 } 235 236 //go:nosplit 237 func write(fd uintptr, buf unsafe.Pointer, n int32) int64 { 238 return int64(pwrite(int32(fd), buf, n, -1)) 239 } 240 241 func memlimit() uint64 { 242 return 0 243 } 244 245 var _badsignal = []byte("runtime: signal received on thread not created by Go.\n") 246 247 // This runs on a foreign stack, without an m or a g. No stack split. 248 //go:nosplit 249 func badsignal2() { 250 pwrite(2, unsafe.Pointer(&_badsignal[0]), int32(len(_badsignal)), -1) 251 exits(&_badsignal[0]) 252 } 253 254 func _atoi(b []byte) int { 255 n := 0 256 for len(b) > 0 && '0' <= b[0] && b[0] <= '9' { 257 n = n*10 + int(b[0]) - '0' 258 b = b[1:] 259 } 260 return n 261 }