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