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