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 if !canpanic() {
78 throw("unexpected signal during runtime execution")
79 }
80
81 note := gostringnocopy((*byte)(unsafe.Pointer(gp.m.notesig)))
82 switch gp.sig {
83 case _SIGRFAULT, _SIGWFAULT:
84 i := indexNoFloat(note, "addr=")
85 if i >= 0 {
86 i += 5
87 } else if i = indexNoFloat(note, "va="); i >= 0 {
88 i += 3
89 } else {
90 panicmem()
91 }
92 addr := note[i:]
93 gp.sigcode1 = uintptr(atolwhex(addr))
94 if gp.sigcode1 < 0x1000 {
95 panicmem()
96 }
97 if gp.paniconfault {
98 panicmemAddr(gp.sigcode1)
99 }
100 if inUserArenaChunk(gp.sigcode1) {
101
102
103
104 print("accessed data from freed user arena ", hex(gp.sigcode1), "\n")
105 } else {
106 print("unexpected fault address ", hex(gp.sigcode1), "\n")
107 }
108 throw("fault")
109 case _SIGTRAP:
110 if gp.paniconfault {
111 panicmem()
112 }
113 throw(note)
114 case _SIGINTDIV:
115 panicdivide()
116 case _SIGFLOAT:
117 panicfloat()
118 default:
119 panic(errorString(note))
120 }
121 }
122
123
124
125 func indexNoFloat(s, t string) int {
126 if len(t) == 0 {
127 return 0
128 }
129 for i := 0; i < len(s); i++ {
130 if s[i] == t[0] && stringslite.HasPrefix(s[i:], t) {
131 return i
132 }
133 }
134 return -1
135 }
136
137 func atolwhex(p string) int64 {
138 for stringslite.HasPrefix(p, " ") || stringslite.HasPrefix(p, "\t") {
139 p = p[1:]
140 }
141 neg := false
142 if stringslite.HasPrefix(p, "-") || stringslite.HasPrefix(p, "+") {
143 neg = p[0] == '-'
144 p = p[1:]
145 for stringslite.HasPrefix(p, " ") || stringslite.HasPrefix(p, "\t") {
146 p = p[1:]
147 }
148 }
149 var n int64
150 switch {
151 case stringslite.HasPrefix(p, "0x"), stringslite.HasPrefix(p, "0X"):
152 p = p[2:]
153 for ; len(p) > 0; p = p[1:] {
154 if '0' <= p[0] && p[0] <= '9' {
155 n = n*16 + int64(p[0]-'0')
156 } else if 'a' <= p[0] && p[0] <= 'f' {
157 n = n*16 + int64(p[0]-'a'+10)
158 } else if 'A' <= p[0] && p[0] <= 'F' {
159 n = n*16 + int64(p[0]-'A'+10)
160 } else {
161 break
162 }
163 }
164 case stringslite.HasPrefix(p, "0"):
165 for ; len(p) > 0 && '0' <= p[0] && p[0] <= '7'; p = p[1:] {
166 n = n*8 + int64(p[0]-'0')
167 }
168 default:
169 for ; len(p) > 0 && '0' <= p[0] && p[0] <= '9'; p = p[1:] {
170 n = n*10 + int64(p[0]-'0')
171 }
172 }
173 if neg {
174 n = -n
175 }
176 return n
177 }
178
179 type sigset struct{}
180
181
182
183 func mpreinit(mp *m) {
184
185 mp.gsignal = malg(32 * 1024)
186 mp.gsignal.m = mp
187 mp.notesig = (*int8)(mallocgc(_ERRMAX, nil, true))
188
189
190 mp.errstr = (*byte)(mallocgc(_ERRMAX, nil, true))
191 }
192
193 func sigsave(p *sigset) {
194 }
195
196 func msigrestore(sigmask sigset) {
197 }
198
199
200
201 func clearSignalHandlers() {
202 }
203
204 func sigblock(exiting bool) {
205 }
206
207
208
209 func minit() {
210 if atomic.Load(&exiting) != 0 {
211 exits(&emptystatus[0])
212 }
213
214
215 setfpmasks()
216 }
217
218
219 func unminit() {
220 }
221
222
223
224
225
226
227
228 func mdestroy(mp *m) {
229 }
230
231 var sysstat = []byte("/dev/sysstat\x00")
232
233 func getCPUCount() int32 {
234 var buf [2048]byte
235 fd := open(&sysstat[0], _OREAD|_OCEXEC, 0)
236 if fd < 0 {
237 return 1
238 }
239 ncpu := int32(0)
240 for {
241 n := read(fd, unsafe.Pointer(&buf), int32(len(buf)))
242 if n <= 0 {
243 break
244 }
245 for i := int32(0); i < n; i++ {
246 if buf[i] == '\n' {
247 ncpu++
248 }
249 }
250 }
251 closefd(fd)
252 if ncpu == 0 {
253 ncpu = 1
254 }
255 return ncpu
256 }
257
258 var devswap = []byte("/dev/swap\x00")
259 var pagesize = []byte(" pagesize\n")
260
261 func getPageSize() uintptr {
262 var buf [2048]byte
263 var pos int
264 fd := open(&devswap[0], _OREAD|_OCEXEC, 0)
265 if fd < 0 {
266
267
268
269 return minPhysPageSize
270 }
271 for pos < len(buf) {
272 n := read(fd, unsafe.Pointer(&buf[pos]), int32(len(buf)-pos))
273 if n <= 0 {
274 break
275 }
276 pos += int(n)
277 }
278 closefd(fd)
279 text := buf[:pos]
280
281 bol := 0
282 for i, c := range text {
283 if c == '\n' {
284 bol = i + 1
285 }
286 if bytesHasPrefix(text[i:], pagesize) {
287
288 return uintptr(_atoi(text[bol:]))
289 }
290 }
291
292 return minPhysPageSize
293 }
294
295 func bytesHasPrefix(s, prefix []byte) bool {
296 if len(s) < len(prefix) {
297 return false
298 }
299 for i, p := range prefix {
300 if s[i] != p {
301 return false
302 }
303 }
304 return true
305 }
306
307 var pid = []byte("#c/pid\x00")
308
309 func getpid() uint64 {
310 var b [20]byte
311 fd := open(&pid[0], 0, 0)
312 if fd >= 0 {
313 read(fd, unsafe.Pointer(&b), int32(len(b)))
314 closefd(fd)
315 }
316 c := b[:]
317 for c[0] == ' ' || c[0] == '\t' {
318 c = c[1:]
319 }
320 return uint64(_atoi(c))
321 }
322
323 var (
324 bintimeFD int32 = -1
325
326 bintimeDev = []byte("/dev/bintime\x00")
327 randomDev = []byte("/dev/random\x00")
328 )
329
330 func osinit() {
331 physPageSize = getPageSize()
332 initBloc()
333 numCPUStartup = getCPUCount()
334 getg().m.procid = getpid()
335
336 fd := open(&bintimeDev[0], _OREAD|_OCEXEC, 0)
337 if fd < 0 {
338 fatal("cannot open /dev/bintime")
339 }
340 bintimeFD = fd
341
342
343
344
345
346 if bintimeFD < 18 {
347 if dupfd(bintimeFD, 18) < 0 {
348 fatal("cannot dup /dev/bintime onto 18")
349 }
350 closefd(bintimeFD)
351 bintimeFD = 18
352 }
353 }
354
355
356 func crash() {
357 notify(nil)
358 *(*int)(nil) = 0
359 }
360
361
362
363
364
365
366 func readRandom(r []byte) int {
367 return 0
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 byteorder.BEUint64(b[:])
577 }
578
579
580 func nanotime1() int64 {
581 var t [4]uint64
582 if readtime(&t[0], 1, 4) == 4 {
583
584
585 return int64(frombe(t[3]))
586 }
587
588 return int64(frombe(t[0]))
589 }
590
591
592 func walltime() (sec int64, nsec int32) {
593 var t [1]uint64
594 readtime(&t[0], 1, 1)
595 return timesplit(frombe(t[0]))
596 }
597
View as plain text