github.com/reiver/go@v0.0.0-20150109200633-1d0c7792f172/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 close(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 close(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 var random_dev = []byte("/dev/random\x00") 89 90 //go:nosplit 91 func getRandomData(r []byte) { 92 fd := open(&random_dev[0], 0 /* O_RDONLY */, 0) 93 n := read(fd, unsafe.Pointer(&r[0]), int32(len(r))) 94 close(fd) 95 extendRandom(r, int(n)) 96 } 97 98 func goenvs() { 99 } 100 101 func initsig() { 102 } 103 104 //go:nosplit 105 func osyield() { 106 sleep(0) 107 } 108 109 //go:nosplit 110 func usleep(µs uint32) { 111 ms := int32(µs / 1000) 112 if ms == 0 { 113 ms = 1 114 } 115 sleep(ms) 116 } 117 118 //go:nosplit 119 func nanotime() int64 { 120 var scratch int64 121 ns := nsec(&scratch) 122 // TODO(aram): remove hack after I fix _nsec in the pc64 kernel. 123 if ns == 0 { 124 return scratch 125 } 126 return ns 127 } 128 129 //go:nosplit 130 func itoa(buf []byte, val uint64) []byte { 131 i := len(buf) - 1 132 for val >= 10 { 133 buf[i] = byte(val%10 + '0') 134 i-- 135 val /= 10 136 } 137 buf[i] = byte(val + '0') 138 return buf[i:] 139 } 140 141 var goexits = []byte("go: exit ") 142 143 func goexitsall(status *byte) { 144 var buf [_ERRMAX]byte 145 n := copy(buf[:], goexits) 146 n = copy(buf[n:], gostringnocopy(status)) 147 pid := getpid() 148 for mp := (*m)(atomicloadp(unsafe.Pointer(&allm))); mp != nil; mp = mp.alllink { 149 if mp.procid != pid { 150 postnote(mp.procid, buf[:]) 151 } 152 } 153 } 154 155 var procdir = []byte("/proc/") 156 var notefile = []byte("/note\x00") 157 158 func postnote(pid uint64, msg []byte) int { 159 var buf [128]byte 160 var tmp [32]byte 161 n := copy(buf[:], procdir) 162 n += copy(buf[n:], itoa(tmp[:], pid)) 163 copy(buf[n:], notefile) 164 fd := open(&buf[0], _OWRITE, 0) 165 if fd < 0 { 166 return -1 167 } 168 len := findnull(&msg[0]) 169 if write(uintptr(fd), (unsafe.Pointer)(&msg[0]), int32(len)) != int64(len) { 170 close(fd) 171 return -1 172 } 173 close(fd) 174 return 0 175 } 176 177 //go:nosplit 178 func exit(e int) { 179 var status []byte 180 if e == 0 { 181 status = []byte("\x00") 182 } else { 183 // build error string 184 var tmp [32]byte 185 status = []byte(gostringnocopy(&itoa(tmp[:len(tmp)-1], uint64(e))[0])) 186 } 187 goexitsall(&status[0]) 188 exits(&status[0]) 189 } 190 191 func newosproc(mp *m, stk unsafe.Pointer) { 192 if false { 193 print("newosproc mp=", mp, " ostk=", &mp, "\n") 194 } 195 pid := rfork(_RFPROC | _RFMEM | _RFNOWAIT) 196 if pid < 0 { 197 throw("newosproc: rfork failed") 198 } 199 if pid == 0 { 200 tstart_plan9(mp) 201 } 202 } 203 204 //go:nosplit 205 func semacreate() uintptr { 206 return 1 207 } 208 209 //go:nosplit 210 func semasleep(ns int64) int { 211 _g_ := getg() 212 if ns >= 0 { 213 ms := timediv(ns, 1000000, nil) 214 if ms == 0 { 215 ms = 1 216 } 217 ret := plan9_tsemacquire(&_g_.m.waitsemacount, ms) 218 if ret == 1 { 219 return 0 // success 220 } 221 return -1 // timeout or interrupted 222 } 223 for plan9_semacquire(&_g_.m.waitsemacount, 1) < 0 { 224 // interrupted; try again (c.f. lock_sema.go) 225 } 226 return 0 // success 227 } 228 229 //go:nosplit 230 func semawakeup(mp *m) { 231 plan9_semrelease(&mp.waitsemacount, 1) 232 } 233 234 //go:nosplit 235 func read(fd int32, buf unsafe.Pointer, n int32) int32 { 236 return pread(fd, buf, n, -1) 237 } 238 239 //go:nosplit 240 func write(fd uintptr, buf unsafe.Pointer, n int32) int64 { 241 return int64(pwrite(int32(fd), buf, n, -1)) 242 } 243 244 func memlimit() uint64 { 245 return 0 246 } 247 248 var _badsignal = []byte("runtime: signal received on thread not created by Go.\n") 249 250 // This runs on a foreign stack, without an m or a g. No stack split. 251 //go:nosplit 252 func badsignal2() { 253 pwrite(2, unsafe.Pointer(&_badsignal[0]), int32(len(_badsignal)), -1) 254 exits(&_badsignal[0]) 255 } 256 257 func _atoi(b []byte) int { 258 n := 0 259 for len(b) > 0 && '0' <= b[0] && b[0] <= '9' { 260 n = n*10 + int(b[0]) - '0' 261 b = b[1:] 262 } 263 return n 264 }