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