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