Source file
src/runtime/os_plan9.go
Documentation: runtime
1
2
3
4
5 package runtime
6
7 import (
8 "internal/abi"
9 "runtime/internal/atomic"
10 "unsafe"
11 )
12
13 type mOS struct {
14 waitsemacount uint32
15 notesig *int8
16 errstr *byte
17 ignoreHangup bool
18 }
19
20 func closefd(fd int32) int32
21
22
23 func open(name *byte, mode, perm int32) int32
24
25
26 func pread(fd int32, buf unsafe.Pointer, nbytes int32, offset int64) int32
27
28
29 func pwrite(fd int32, buf unsafe.Pointer, nbytes int32, offset int64) int32
30
31 func seek(fd int32, offset int64, whence int32) int64
32
33
34 func exits(msg *byte)
35
36
37 func brk_(addr unsafe.Pointer) int32
38
39 func sleep(ms int32) int32
40
41 func rfork(flags int32) int32
42
43
44 func plan9_semacquire(addr *uint32, block int32) int32
45
46
47 func plan9_tsemacquire(addr *uint32, ms int32) int32
48
49
50 func plan9_semrelease(addr *uint32, count int32) int32
51
52
53 func notify(fn unsafe.Pointer) int32
54
55 func noted(mode int32) int32
56
57
58 func nsec(*int64) int64
59
60
61 func sigtramp(ureg, note unsafe.Pointer)
62
63 func setfpmasks()
64
65
66 func tstart_plan9(newm *m)
67
68 func errstr() string
69
70 type _Plink uintptr
71
72 func sigpanic() {
73 gp := getg()
74 if !canpanic() {
75 throw("unexpected signal during runtime execution")
76 }
77
78 note := gostringnocopy((*byte)(unsafe.Pointer(gp.m.notesig)))
79 switch gp.sig {
80 case _SIGRFAULT, _SIGWFAULT:
81 i := indexNoFloat(note, "addr=")
82 if i >= 0 {
83 i += 5
84 } else if i = indexNoFloat(note, "va="); i >= 0 {
85 i += 3
86 } else {
87 panicmem()
88 }
89 addr := note[i:]
90 gp.sigcode1 = uintptr(atolwhex(addr))
91 if gp.sigcode1 < 0x1000 {
92 panicmem()
93 }
94 if gp.paniconfault {
95 panicmemAddr(gp.sigcode1)
96 }
97 if inUserArenaChunk(gp.sigcode1) {
98
99
100
101 print("accessed data from freed user arena ", hex(gp.sigcode1), "\n")
102 } else {
103 print("unexpected fault address ", hex(gp.sigcode1), "\n")
104 }
105 throw("fault")
106 case _SIGTRAP:
107 if gp.paniconfault {
108 panicmem()
109 }
110 throw(note)
111 case _SIGINTDIV:
112 panicdivide()
113 case _SIGFLOAT:
114 panicfloat()
115 default:
116 panic(errorString(note))
117 }
118 }
119
120
121
122 func indexNoFloat(s, t string) int {
123 if len(t) == 0 {
124 return 0
125 }
126 for i := 0; i < len(s); i++ {
127 if s[i] == t[0] && hasPrefix(s[i:], t) {
128 return i
129 }
130 }
131 return -1
132 }
133
134 func atolwhex(p string) int64 {
135 for hasPrefix(p, " ") || hasPrefix(p, "\t") {
136 p = p[1:]
137 }
138 neg := false
139 if hasPrefix(p, "-") || hasPrefix(p, "+") {
140 neg = p[0] == '-'
141 p = p[1:]
142 for hasPrefix(p, " ") || hasPrefix(p, "\t") {
143 p = p[1:]
144 }
145 }
146 var n int64
147 switch {
148 case hasPrefix(p, "0x"), hasPrefix(p, "0X"):
149 p = p[2:]
150 for ; len(p) > 0; p = p[1:] {
151 if '0' <= p[0] && p[0] <= '9' {
152 n = n*16 + int64(p[0]-'0')
153 } else if 'a' <= p[0] && p[0] <= 'f' {
154 n = n*16 + int64(p[0]-'a'+10)
155 } else if 'A' <= p[0] && p[0] <= 'F' {
156 n = n*16 + int64(p[0]-'A'+10)
157 } else {
158 break
159 }
160 }
161 case hasPrefix(p, "0"):
162 for ; len(p) > 0 && '0' <= p[0] && p[0] <= '7'; p = p[1:] {
163 n = n*8 + int64(p[0]-'0')
164 }
165 default:
166 for ; len(p) > 0 && '0' <= p[0] && p[0] <= '9'; p = p[1:] {
167 n = n*10 + int64(p[0]-'0')
168 }
169 }
170 if neg {
171 n = -n
172 }
173 return n
174 }
175
176 type sigset struct{}
177
178
179
180 func mpreinit(mp *m) {
181
182 mp.gsignal = malg(32 * 1024)
183 mp.gsignal.m = mp
184 mp.notesig = (*int8)(mallocgc(_ERRMAX, nil, true))
185
186
187 mp.errstr = (*byte)(mallocgc(_ERRMAX, nil, true))
188 }
189
190 func sigsave(p *sigset) {
191 }
192
193 func msigrestore(sigmask sigset) {
194 }
195
196
197
198 func clearSignalHandlers() {
199 }
200
201 func sigblock(exiting bool) {
202 }
203
204
205
206 func minit() {
207 if atomic.Load(&exiting) != 0 {
208 exits(&emptystatus[0])
209 }
210
211
212 setfpmasks()
213 }
214
215
216 func unminit() {
217 }
218
219
220
221 func mdestroy(mp *m) {
222 }
223
224 var sysstat = []byte("/dev/sysstat\x00")
225
226 func getproccount() int32 {
227 var buf [2048]byte
228 fd := open(&sysstat[0], _OREAD, 0)
229 if fd < 0 {
230 return 1
231 }
232 ncpu := int32(0)
233 for {
234 n := read(fd, unsafe.Pointer(&buf), int32(len(buf)))
235 if n <= 0 {
236 break
237 }
238 for i := int32(0); i < n; i++ {
239 if buf[i] == '\n' {
240 ncpu++
241 }
242 }
243 }
244 closefd(fd)
245 if ncpu == 0 {
246 ncpu = 1
247 }
248 return ncpu
249 }
250
251 var devswap = []byte("/dev/swap\x00")
252 var pagesize = []byte(" pagesize\n")
253
254 func getPageSize() uintptr {
255 var buf [2048]byte
256 var pos int
257 fd := open(&devswap[0], _OREAD, 0)
258 if fd < 0 {
259
260
261
262 return minPhysPageSize
263 }
264 for pos < len(buf) {
265 n := read(fd, unsafe.Pointer(&buf[pos]), int32(len(buf)-pos))
266 if n <= 0 {
267 break
268 }
269 pos += int(n)
270 }
271 closefd(fd)
272 text := buf[:pos]
273
274 bol := 0
275 for i, c := range text {
276 if c == '\n' {
277 bol = i + 1
278 }
279 if bytesHasPrefix(text[i:], pagesize) {
280
281 return uintptr(_atoi(text[bol:]))
282 }
283 }
284
285 return minPhysPageSize
286 }
287
288 func bytesHasPrefix(s, prefix []byte) bool {
289 if len(s) < len(prefix) {
290 return false
291 }
292 for i, p := range prefix {
293 if s[i] != p {
294 return false
295 }
296 }
297 return true
298 }
299
300 var pid = []byte("#c/pid\x00")
301
302 func getpid() uint64 {
303 var b [20]byte
304 fd := open(&pid[0], 0, 0)
305 if fd >= 0 {
306 read(fd, unsafe.Pointer(&b), int32(len(b)))
307 closefd(fd)
308 }
309 c := b[:]
310 for c[0] == ' ' || c[0] == '\t' {
311 c = c[1:]
312 }
313 return uint64(_atoi(c))
314 }
315
316 func osinit() {
317 physPageSize = getPageSize()
318 initBloc()
319 ncpu = getproccount()
320 getg().m.procid = getpid()
321 }
322
323
324 func crash() {
325 notify(nil)
326 *(*int)(nil) = 0
327 }
328
329
330 func readRandom(r []byte) int {
331 return 0
332 }
333
334 func initsig(preinit bool) {
335 if !preinit {
336 notify(unsafe.Pointer(abi.FuncPCABI0(sigtramp)))
337 }
338 }
339
340
341 func osyield() {
342 sleep(0)
343 }
344
345
346 func osyield_no_g() {
347 osyield()
348 }
349
350
351 func usleep(µs uint32) {
352 ms := int32(µs / 1000)
353 if ms == 0 {
354 ms = 1
355 }
356 sleep(ms)
357 }
358
359
360 func usleep_no_g(usec uint32) {
361 usleep(usec)
362 }
363
364
365 func nanotime1() int64 {
366 var scratch int64
367 ns := nsec(&scratch)
368
369 if ns == 0 {
370 return scratch
371 }
372 return ns
373 }
374
375 var goexits = []byte("go: exit ")
376 var emptystatus = []byte("\x00")
377 var exiting uint32
378
379 func goexitsall(status *byte) {
380 var buf [_ERRMAX]byte
381 if !atomic.Cas(&exiting, 0, 1) {
382 return
383 }
384 getg().m.locks++
385 n := copy(buf[:], goexits)
386 n = copy(buf[n:], gostringnocopy(status))
387 pid := getpid()
388 for mp := (*m)(atomic.Loadp(unsafe.Pointer(&allm))); mp != nil; mp = mp.alllink {
389 if mp.procid != 0 && mp.procid != pid {
390 postnote(mp.procid, buf[:])
391 }
392 }
393 getg().m.locks--
394 }
395
396 var procdir = []byte("/proc/")
397 var notefile = []byte("/note\x00")
398
399 func postnote(pid uint64, msg []byte) int {
400 var buf [128]byte
401 var tmp [32]byte
402 n := copy(buf[:], procdir)
403 n += copy(buf[n:], itoa(tmp[:], pid))
404 copy(buf[n:], notefile)
405 fd := open(&buf[0], _OWRITE, 0)
406 if fd < 0 {
407 return -1
408 }
409 len := findnull(&msg[0])
410 if write1(uintptr(fd), unsafe.Pointer(&msg[0]), int32(len)) != int32(len) {
411 closefd(fd)
412 return -1
413 }
414 closefd(fd)
415 return 0
416 }
417
418
419 func exit(e int32) {
420 var status []byte
421 if e == 0 {
422 status = emptystatus
423 } else {
424
425 var tmp [32]byte
426 sl := itoa(tmp[:len(tmp)-1], uint64(e))
427
428 status = sl[:len(sl)+1]
429 }
430 goexitsall(&status[0])
431 exits(&status[0])
432 }
433
434
435
436
437 func newosproc(mp *m) {
438 if false {
439 print("newosproc mp=", mp, " ostk=", &mp, "\n")
440 }
441 pid := rfork(_RFPROC | _RFMEM | _RFNOWAIT)
442 if pid < 0 {
443 throw("newosproc: rfork failed")
444 }
445 if pid == 0 {
446 tstart_plan9(mp)
447 }
448 }
449
450 func exitThread(wait *atomic.Uint32) {
451
452
453 throw("exitThread")
454 }
455
456
457 func semacreate(mp *m) {
458 }
459
460
461 func semasleep(ns int64) int {
462 gp := getg()
463 if ns >= 0 {
464 ms := timediv(ns, 1000000, nil)
465 if ms == 0 {
466 ms = 1
467 }
468 ret := plan9_tsemacquire(&gp.m.waitsemacount, ms)
469 if ret == 1 {
470 return 0
471 }
472 return -1
473 }
474 for plan9_semacquire(&gp.m.waitsemacount, 1) < 0 {
475
476 }
477 return 0
478 }
479
480
481 func semawakeup(mp *m) {
482 plan9_semrelease(&mp.waitsemacount, 1)
483 }
484
485
486 func read(fd int32, buf unsafe.Pointer, n int32) int32 {
487 return pread(fd, buf, n, -1)
488 }
489
490
491 func write1(fd uintptr, buf unsafe.Pointer, n int32) int32 {
492 return pwrite(int32(fd), buf, n, -1)
493 }
494
495 var _badsignal = []byte("runtime: signal received on thread not created by Go.\n")
496
497
498
499
500 func badsignal2() {
501 pwrite(2, unsafe.Pointer(&_badsignal[0]), int32(len(_badsignal)), -1)
502 exits(&_badsignal[0])
503 }
504
505 func raisebadsignal(sig uint32) {
506 badsignal2()
507 }
508
509 func _atoi(b []byte) int {
510 n := 0
511 for len(b) > 0 && '0' <= b[0] && b[0] <= '9' {
512 n = n*10 + int(b[0]) - '0'
513 b = b[1:]
514 }
515 return n
516 }
517
518 func signame(sig uint32) string {
519 if sig >= uint32(len(sigtable)) {
520 return ""
521 }
522 return sigtable[sig].name
523 }
524
525 const preemptMSupported = false
526
527 func preemptM(mp *m) {
528
529
530
531 }
532
View as plain text