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