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