github.com/brownsys/tracing-framework-go@v0.0.0-20161210174012-0542a62412fe/go/darwin_amd64/src/runtime/os_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 ( 8 "runtime/internal/atomic" 9 "unsafe" 10 ) 11 12 type mOS struct { 13 waitsemacount uint32 14 notesig *int8 15 errstr *byte 16 } 17 18 func closefd(fd int32) int32 19 20 //go:noescape 21 func open(name *byte, mode, perm int32) int32 22 23 //go:noescape 24 func pread(fd int32, buf unsafe.Pointer, nbytes int32, offset int64) int32 25 26 //go:noescape 27 func pwrite(fd int32, buf unsafe.Pointer, nbytes int32, offset int64) int32 28 29 func seek(fd int32, offset int64, whence int32) int64 30 31 //go:noescape 32 func exits(msg *byte) 33 34 //go:noescape 35 func brk_(addr unsafe.Pointer) int32 36 37 func sleep(ms int32) int32 38 39 func rfork(flags int32) int32 40 41 //go:noescape 42 func plan9_semacquire(addr *uint32, block int32) int32 43 44 //go:noescape 45 func plan9_tsemacquire(addr *uint32, ms int32) int32 46 47 //go:noescape 48 func plan9_semrelease(addr *uint32, count int32) int32 49 50 //go:noescape 51 func notify(fn unsafe.Pointer) int32 52 53 func noted(mode int32) int32 54 55 //go:noescape 56 func nsec(*int64) int64 57 58 //go:noescape 59 func sigtramp(ureg, msg unsafe.Pointer) 60 61 func setfpmasks() 62 63 //go:noescape 64 func tstart_plan9(newm *m) 65 66 func errstr() string 67 68 type _Plink uintptr 69 70 //go:linkname os_sigpipe os.sigpipe 71 func os_sigpipe() { 72 throw("too many writes on closed pipe") 73 } 74 75 func sigpanic() { 76 g := getg() 77 if !canpanic(g) { 78 throw("unexpected signal during runtime execution") 79 } 80 81 note := gostringnocopy((*byte)(unsafe.Pointer(g.m.notesig))) 82 switch g.sig { 83 case _SIGRFAULT, _SIGWFAULT: 84 i := index(note, "addr=") 85 if i >= 0 { 86 i += 5 87 } else if i = index(note, "va="); i >= 0 { 88 i += 3 89 } else { 90 panicmem() 91 } 92 addr := note[i:] 93 g.sigcode1 = uintptr(atolwhex(addr)) 94 if g.sigcode1 < 0x1000 || g.paniconfault { 95 panicmem() 96 } 97 print("unexpected fault address ", hex(g.sigcode1), "\n") 98 throw("fault") 99 case _SIGTRAP: 100 if g.paniconfault { 101 panicmem() 102 } 103 throw(note) 104 case _SIGINTDIV: 105 panicdivide() 106 case _SIGFLOAT: 107 panicfloat() 108 default: 109 panic(errorString(note)) 110 } 111 } 112 113 func atolwhex(p string) int64 { 114 for hasprefix(p, " ") || hasprefix(p, "\t") { 115 p = p[1:] 116 } 117 neg := false 118 if hasprefix(p, "-") || hasprefix(p, "+") { 119 neg = p[0] == '-' 120 p = p[1:] 121 for hasprefix(p, " ") || hasprefix(p, "\t") { 122 p = p[1:] 123 } 124 } 125 var n int64 126 switch { 127 case hasprefix(p, "0x"), hasprefix(p, "0X"): 128 p = p[2:] 129 for ; len(p) > 0; p = p[1:] { 130 if '0' <= p[0] && p[0] <= '9' { 131 n = n*16 + int64(p[0]-'0') 132 } else if 'a' <= p[0] && p[0] <= 'f' { 133 n = n*16 + int64(p[0]-'a'+10) 134 } else if 'A' <= p[0] && p[0] <= 'F' { 135 n = n*16 + int64(p[0]-'A'+10) 136 } else { 137 break 138 } 139 } 140 case hasprefix(p, "0"): 141 for ; len(p) > 0 && '0' <= p[0] && p[0] <= '7'; p = p[1:] { 142 n = n*8 + int64(p[0]-'0') 143 } 144 default: 145 for ; len(p) > 0 && '0' <= p[0] && p[0] <= '9'; p = p[1:] { 146 n = n*10 + int64(p[0]-'0') 147 } 148 } 149 if neg { 150 n = -n 151 } 152 return n 153 } 154 155 type sigset struct{} 156 157 // Called to initialize a new m (including the bootstrap m). 158 // Called on the parent thread (main thread in case of bootstrap), can allocate memory. 159 func mpreinit(mp *m) { 160 // Initialize stack and goroutine for note handling. 161 mp.gsignal = malg(32 * 1024) 162 mp.gsignal.m = mp 163 mp.notesig = (*int8)(mallocgc(_ERRMAX, nil, true)) 164 // Initialize stack for handling strings from the 165 // errstr system call, as used in package syscall. 166 mp.errstr = (*byte)(mallocgc(_ERRMAX, nil, true)) 167 } 168 169 func msigsave(mp *m) { 170 } 171 172 func msigrestore(sigmask sigset) { 173 } 174 175 func sigblock() { 176 } 177 178 // Called to initialize a new m (including the bootstrap m). 179 // Called on the new thread, cannot allocate memory. 180 func minit() { 181 if atomic.Load(&exiting) != 0 { 182 exits(&emptystatus[0]) 183 } 184 // Mask all SSE floating-point exceptions 185 // when running on the 64-bit kernel. 186 setfpmasks() 187 } 188 189 // Called from dropm to undo the effect of an minit. 190 func unminit() { 191 } 192 193 var sysstat = []byte("/dev/sysstat\x00") 194 195 func getproccount() int32 { 196 var buf [2048]byte 197 fd := open(&sysstat[0], _OREAD, 0) 198 if fd < 0 { 199 return 1 200 } 201 ncpu := int32(0) 202 for { 203 n := read(fd, unsafe.Pointer(&buf), int32(len(buf))) 204 if n <= 0 { 205 break 206 } 207 for i := int32(0); i < n; i++ { 208 if buf[i] == '\n' { 209 ncpu++ 210 } 211 } 212 } 213 closefd(fd) 214 if ncpu == 0 { 215 ncpu = 1 216 } 217 return ncpu 218 } 219 220 var pid = []byte("#c/pid\x00") 221 222 func getpid() uint64 { 223 var b [20]byte 224 fd := open(&pid[0], 0, 0) 225 if fd >= 0 { 226 read(fd, unsafe.Pointer(&b), int32(len(b))) 227 closefd(fd) 228 } 229 c := b[:] 230 for c[0] == ' ' || c[0] == '\t' { 231 c = c[1:] 232 } 233 return uint64(_atoi(c)) 234 } 235 236 func osinit() { 237 initBloc() 238 ncpu = getproccount() 239 getg().m.procid = getpid() 240 notify(unsafe.Pointer(funcPC(sigtramp))) 241 } 242 243 func crash() { 244 notify(nil) 245 *(*int)(nil) = 0 246 } 247 248 //go:nosplit 249 func getRandomData(r []byte) { 250 extendRandom(r, 0) 251 } 252 253 func goenvs() { 254 } 255 256 func initsig(preinit bool) { 257 } 258 259 //go:nosplit 260 func osyield() { 261 sleep(0) 262 } 263 264 //go:nosplit 265 func usleep(µs uint32) { 266 ms := int32(µs / 1000) 267 if ms == 0 { 268 ms = 1 269 } 270 sleep(ms) 271 } 272 273 //go:nosplit 274 func nanotime() int64 { 275 var scratch int64 276 ns := nsec(&scratch) 277 // TODO(aram): remove hack after I fix _nsec in the pc64 kernel. 278 if ns == 0 { 279 return scratch 280 } 281 return ns 282 } 283 284 //go:nosplit 285 func itoa(buf []byte, val uint64) []byte { 286 i := len(buf) - 1 287 for val >= 10 { 288 buf[i] = byte(val%10 + '0') 289 i-- 290 val /= 10 291 } 292 buf[i] = byte(val + '0') 293 return buf[i:] 294 } 295 296 var goexits = []byte("go: exit ") 297 var emptystatus = []byte("\x00") 298 var exiting uint32 299 300 func goexitsall(status *byte) { 301 var buf [_ERRMAX]byte 302 if !atomic.Cas(&exiting, 0, 1) { 303 return 304 } 305 getg().m.locks++ 306 n := copy(buf[:], goexits) 307 n = copy(buf[n:], gostringnocopy(status)) 308 pid := getpid() 309 for mp := (*m)(atomic.Loadp(unsafe.Pointer(&allm))); mp != nil; mp = mp.alllink { 310 if mp.procid != 0 && mp.procid != pid { 311 postnote(mp.procid, buf[:]) 312 } 313 } 314 getg().m.locks-- 315 } 316 317 var procdir = []byte("/proc/") 318 var notefile = []byte("/note\x00") 319 320 func postnote(pid uint64, msg []byte) int { 321 var buf [128]byte 322 var tmp [32]byte 323 n := copy(buf[:], procdir) 324 n += copy(buf[n:], itoa(tmp[:], pid)) 325 copy(buf[n:], notefile) 326 fd := open(&buf[0], _OWRITE, 0) 327 if fd < 0 { 328 return -1 329 } 330 len := findnull(&msg[0]) 331 if write(uintptr(fd), unsafe.Pointer(&msg[0]), int32(len)) != int64(len) { 332 closefd(fd) 333 return -1 334 } 335 closefd(fd) 336 return 0 337 } 338 339 //go:nosplit 340 func exit(e int) { 341 var status []byte 342 if e == 0 { 343 status = emptystatus 344 } else { 345 // build error string 346 var tmp [32]byte 347 status = append(itoa(tmp[:len(tmp)-1], uint64(e)), 0) 348 } 349 goexitsall(&status[0]) 350 exits(&status[0]) 351 } 352 353 // May run with m.p==nil, so write barriers are not allowed. 354 //go:nowritebarrier 355 func newosproc(mp *m, stk unsafe.Pointer) { 356 if false { 357 print("newosproc mp=", mp, " ostk=", &mp, "\n") 358 } 359 pid := rfork(_RFPROC | _RFMEM | _RFNOWAIT) 360 if pid < 0 { 361 throw("newosproc: rfork failed") 362 } 363 if pid == 0 { 364 tstart_plan9(mp) 365 } 366 } 367 368 //go:nosplit 369 func semacreate(mp *m) { 370 } 371 372 //go:nosplit 373 func semasleep(ns int64) int { 374 _g_ := getg() 375 if ns >= 0 { 376 ms := timediv(ns, 1000000, nil) 377 if ms == 0 { 378 ms = 1 379 } 380 ret := plan9_tsemacquire(&_g_.m.waitsemacount, ms) 381 if ret == 1 { 382 return 0 // success 383 } 384 return -1 // timeout or interrupted 385 } 386 for plan9_semacquire(&_g_.m.waitsemacount, 1) < 0 { 387 // interrupted; try again (c.f. lock_sema.go) 388 } 389 return 0 // success 390 } 391 392 //go:nosplit 393 func semawakeup(mp *m) { 394 plan9_semrelease(&mp.waitsemacount, 1) 395 } 396 397 //go:nosplit 398 func read(fd int32, buf unsafe.Pointer, n int32) int32 { 399 return pread(fd, buf, n, -1) 400 } 401 402 //go:nosplit 403 func write(fd uintptr, buf unsafe.Pointer, n int32) int64 { 404 return int64(pwrite(int32(fd), buf, n, -1)) 405 } 406 407 func memlimit() uint64 { 408 return 0 409 } 410 411 var _badsignal = []byte("runtime: signal received on thread not created by Go.\n") 412 413 // This runs on a foreign stack, without an m or a g. No stack split. 414 //go:nosplit 415 func badsignal2() { 416 pwrite(2, unsafe.Pointer(&_badsignal[0]), int32(len(_badsignal)), -1) 417 exits(&_badsignal[0]) 418 } 419 420 func raisebadsignal(sig int32) { 421 badsignal2() 422 } 423 424 func _atoi(b []byte) int { 425 n := 0 426 for len(b) > 0 && '0' <= b[0] && b[0] <= '9' { 427 n = n*10 + int(b[0]) - '0' 428 b = b[1:] 429 } 430 return n 431 } 432 433 func signame(sig uint32) string { 434 if sig >= uint32(len(sigtable)) { 435 return "" 436 } 437 return sigtable[sig].name 438 }