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 func msigsave(mp *m) { 22 } 23 24 // Called to initialize a new m (including the bootstrap m). 25 // Called on the new thread, can not allocate memory. 26 func minit() { 27 // Mask all SSE floating-point exceptions 28 // when running on the 64-bit kernel. 29 setfpmasks() 30 } 31 32 // Called from dropm to undo the effect of an minit. 33 func unminit() { 34 } 35 36 var sysstat = []byte("/dev/sysstat\x00") 37 38 func getproccount() int32 { 39 var buf [2048]byte 40 fd := open(&sysstat[0], _OREAD, 0) 41 if fd < 0 { 42 return 1 43 } 44 ncpu := int32(0) 45 for { 46 n := read(fd, unsafe.Pointer(&buf), int32(len(buf))) 47 if n <= 0 { 48 break 49 } 50 for i := int32(0); i < n; i++ { 51 if buf[i] == '\n' { 52 ncpu++ 53 } 54 } 55 } 56 closefd(fd) 57 if ncpu == 0 { 58 ncpu = 1 59 } 60 return ncpu 61 } 62 63 var pid = []byte("#c/pid\x00") 64 65 func getpid() uint64 { 66 var b [20]byte 67 fd := open(&pid[0], 0, 0) 68 if fd >= 0 { 69 read(fd, unsafe.Pointer(&b), int32(len(b))) 70 closefd(fd) 71 } 72 c := b[:] 73 for c[0] == ' ' || c[0] == '\t' { 74 c = c[1:] 75 } 76 return uint64(_atoi(c)) 77 } 78 79 func osinit() { 80 initBloc() 81 ncpu = getproccount() 82 getg().m.procid = getpid() 83 notify(unsafe.Pointer(funcPC(sigtramp))) 84 } 85 86 func crash() { 87 notify(nil) 88 *(*int)(nil) = 0 89 } 90 91 //go:nosplit 92 func getRandomData(r []byte) { 93 extendRandom(r, 0) 94 } 95 96 func goenvs() { 97 } 98 99 func initsig() { 100 } 101 102 //go:nosplit 103 func osyield() { 104 sleep(0) 105 } 106 107 //go:nosplit 108 func usleep(s uint32) { 109 ms := int32(s / 1000) 110 if ms == 0 { 111 ms = 1 112 } 113 sleep(ms) 114 } 115 116 //go:nosplit 117 func nanotime() int64 { 118 var scratch int64 119 ns := nsec(&scratch) 120 // TODO(aram): remove hack after I fix _nsec in the pc64 kernel. 121 if ns == 0 { 122 return scratch 123 } 124 return ns 125 } 126 127 //go:nosplit 128 func itoa(buf []byte, val uint64) []byte { 129 i := len(buf) - 1 130 for val >= 10 { 131 buf[i] = byte(val%10 + '0') 132 i-- 133 val /= 10 134 } 135 buf[i] = byte(val + '0') 136 return buf[i:] 137 } 138 139 var goexits = []byte("go: exit ") 140 141 func goexitsall(status *byte) { 142 var buf [_ERRMAX]byte 143 n := copy(buf[:], goexits) 144 n = copy(buf[n:], gostringnocopy(status)) 145 pid := getpid() 146 for mp := (*m)(atomicloadp(unsafe.Pointer(&allm))); mp != nil; mp = mp.alllink { 147 if mp.procid != pid { 148 postnote(mp.procid, buf[:]) 149 } 150 } 151 } 152 153 var procdir = []byte("/proc/") 154 var notefile = []byte("/note\x00") 155 156 func postnote(pid uint64, msg []byte) int { 157 var buf [128]byte 158 var tmp [32]byte 159 n := copy(buf[:], procdir) 160 n += copy(buf[n:], itoa(tmp[:], pid)) 161 copy(buf[n:], notefile) 162 fd := open(&buf[0], _OWRITE, 0) 163 if fd < 0 { 164 return -1 165 } 166 len := findnull(&msg[0]) 167 if write(uintptr(fd), (unsafe.Pointer)(&msg[0]), int32(len)) != int64(len) { 168 closefd(fd) 169 return -1 170 } 171 closefd(fd) 172 return 0 173 } 174 175 //go:nosplit 176 func exit(e int) { 177 var status []byte 178 if e == 0 { 179 status = []byte("\x00") 180 } else { 181 // build error string 182 var tmp [32]byte 183 status = append(itoa(tmp[:len(tmp)-1], uint64(e)), 0) 184 } 185 goexitsall(&status[0]) 186 exits(&status[0]) 187 } 188 189 // May run with m.p==nil, so write barriers are not allowed. 190 //go:nowritebarrier 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 raisebadsignal(sig int32) { 258 badsignal2() 259 } 260 261 func _atoi(b []byte) int { 262 n := 0 263 for len(b) > 0 && '0' <= b[0] && b[0] <= '9' { 264 n = n*10 + int(b[0]) - '0' 265 b = b[1:] 266 } 267 return n 268 } 269