Source file
src/runtime/os_plan9.go
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
73 func os_sigpipe() {
74 throw("too many writes on closed pipe")
75 }
76
77 func sigpanic() {
78 gp := getg()
79 if !canpanic() {
80 throw("unexpected signal during runtime execution")
81 }
82
83 note := gostringnocopy((*byte)(unsafe.Pointer(gp.m.notesig)))
84 switch gp.sig {
85 case _SIGRFAULT, _SIGWFAULT:
86 i := indexNoFloat(note, "addr=")
87 if i >= 0 {
88 i += 5
89 } else if i = indexNoFloat(note, "va="); i >= 0 {
90 i += 3
91 } else {
92 panicmem()
93 }
94 addr := note[i:]
95 gp.sigcode1 = uintptr(atolwhex(addr))
96 if gp.sigcode1 < 0x1000 {
97 panicmem()
98 }
99 if gp.paniconfault {
100 panicmemAddr(gp.sigcode1)
101 }
102 if inUserArenaChunk(gp.sigcode1) {
103
104
105
106 print("accessed data from freed user arena ", hex(gp.sigcode1), "\n")
107 } else {
108 print("unexpected fault address ", hex(gp.sigcode1), "\n")
109 }
110 throw("fault")
111 case _SIGTRAP:
112 if gp.paniconfault {
113 panicmem()
114 }
115 throw(note)
116 case _SIGINTDIV:
117 panicdivide()
118 case _SIGFLOAT:
119 panicfloat()
120 default:
121 panic(errorString(note))
122 }
123 }
124
125
126
127 func indexNoFloat(s, t string) int {
128 if len(t) == 0 {
129 return 0
130 }
131 for i := 0; i < len(s); i++ {
132 if s[i] == t[0] && hasPrefix(s[i:], t) {
133 return i
134 }
135 }
136 return -1
137 }
138
139 func atolwhex(p string) int64 {
140 for hasPrefix(p, " ") || hasPrefix(p, "\t") {
141 p = p[1:]
142 }
143 neg := false
144 if hasPrefix(p, "-") || hasPrefix(p, "+") {
145 neg = p[0] == '-'
146 p = p[1:]
147 for hasPrefix(p, " ") || hasPrefix(p, "\t") {
148 p = p[1:]
149 }
150 }
151 var n int64
152 switch {
153 case hasPrefix(p, "0x"), hasPrefix(p, "0X"):
154 p = p[2:]
155 for ; len(p) > 0; p = p[1:] {
156 if '0' <= p[0] && p[0] <= '9' {
157 n = n*16 + int64(p[0]-'0')
158 } else if 'a' <= p[0] && p[0] <= 'f' {
159 n = n*16 + int64(p[0]-'a'+10)
160 } else if 'A' <= p[0] && p[0] <= 'F' {
161 n = n*16 + int64(p[0]-'A'+10)
162 } else {
163 break
164 }
165 }
166 case hasPrefix(p, "0"):
167 for ; len(p) > 0 && '0' <= p[0] && p[0] <= '7'; p = p[1:] {
168 n = n*8 + int64(p[0]-'0')
169 }
170 default:
171 for ; len(p) > 0 && '0' <= p[0] && p[0] <= '9'; p = p[1:] {
172 n = n*10 + int64(p[0]-'0')
173 }
174 }
175 if neg {
176 n = -n
177 }
178 return n
179 }
180
181 type sigset struct{}
182
183
184
185 func mpreinit(mp *m) {
186
187 mp.gsignal = malg(32 * 1024)
188 mp.gsignal.m = mp
189 mp.notesig = (*int8)(mallocgc(_ERRMAX, nil, true))
190
191
192 mp.errstr = (*byte)(mallocgc(_ERRMAX, nil, true))
193 }
194
195 func sigsave(p *sigset) {
196 }
197
198 func msigrestore(sigmask sigset) {
199 }
200
201
202
203 func clearSignalHandlers() {
204 }
205
206 func sigblock(exiting bool) {
207 }
208
209
210
211 func minit() {
212 if atomic.Load(&exiting) != 0 {
213 exits(&emptystatus[0])
214 }
215
216
217 setfpmasks()
218 }
219
220
221 func unminit() {
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, 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, 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 func osinit() {
322 initBloc()
323 ncpu = getproccount()
324 physPageSize = getPageSize()
325 getg().m.procid = getpid()
326 }
327
328
329 func crash() {
330 notify(nil)
331 *(*int)(nil) = 0
332 }
333
334
335 func getRandomData(r []byte) {
336
337 t := nanotime()
338 v := getg().m.procid ^ uint64(t)
339
340 for len(r) > 0 {
341 v ^= 0xa0761d6478bd642f
342 v *= 0xe7037ed1a0b428db
343 size := 8
344 if len(r) < 8 {
345 size = len(r)
346 }
347 for i := 0; i < size; i++ {
348 r[i] = byte(v >> (8 * i))
349 }
350 r = r[size:]
351 v = v>>32 | v<<32
352 }
353 }
354
355 func initsig(preinit bool) {
356 if !preinit {
357 notify(unsafe.Pointer(abi.FuncPCABI0(sigtramp)))
358 }
359 }
360
361
362 func osyield() {
363 sleep(0)
364 }
365
366
367 func osyield_no_g() {
368 osyield()
369 }
370
371
372 func usleep(µs uint32) {
373 ms := int32(µs / 1000)
374 if ms == 0 {
375 ms = 1
376 }
377 sleep(ms)
378 }
379
380
381 func usleep_no_g(usec uint32) {
382 usleep(usec)
383 }
384
385
386 func nanotime1() int64 {
387 var scratch int64
388 ns := nsec(&scratch)
389
390 if ns == 0 {
391 return scratch
392 }
393 return ns
394 }
395
396 var goexits = []byte("go: exit ")
397 var emptystatus = []byte("\x00")
398 var exiting uint32
399
400 func goexitsall(status *byte) {
401 var buf [_ERRMAX]byte
402 if !atomic.Cas(&exiting, 0, 1) {
403 return
404 }
405 getg().m.locks++
406 n := copy(buf[:], goexits)
407 n = copy(buf[n:], gostringnocopy(status))
408 pid := getpid()
409 for mp := (*m)(atomic.Loadp(unsafe.Pointer(&allm))); mp != nil; mp = mp.alllink {
410 if mp.procid != 0 && mp.procid != pid {
411 postnote(mp.procid, buf[:])
412 }
413 }
414 getg().m.locks--
415 }
416
417 var procdir = []byte("/proc/")
418 var notefile = []byte("/note\x00")
419
420 func postnote(pid uint64, msg []byte) int {
421 var buf [128]byte
422 var tmp [32]byte
423 n := copy(buf[:], procdir)
424 n += copy(buf[n:], itoa(tmp[:], pid))
425 copy(buf[n:], notefile)
426 fd := open(&buf[0], _OWRITE, 0)
427 if fd < 0 {
428 return -1
429 }
430 len := findnull(&msg[0])
431 if write1(uintptr(fd), unsafe.Pointer(&msg[0]), int32(len)) != int32(len) {
432 closefd(fd)
433 return -1
434 }
435 closefd(fd)
436 return 0
437 }
438
439
440 func exit(e int32) {
441 var status []byte
442 if e == 0 {
443 status = emptystatus
444 } else {
445
446 var tmp [32]byte
447 sl := itoa(tmp[:len(tmp)-1], uint64(e))
448
449 status = sl[:len(sl)+1]
450 }
451 goexitsall(&status[0])
452 exits(&status[0])
453 }
454
455
456
457
458 func newosproc(mp *m) {
459 if false {
460 print("newosproc mp=", mp, " ostk=", &mp, "\n")
461 }
462 pid := rfork(_RFPROC | _RFMEM | _RFNOWAIT)
463 if pid < 0 {
464 throw("newosproc: rfork failed")
465 }
466 if pid == 0 {
467 tstart_plan9(mp)
468 }
469 }
470
471 func exitThread(wait *atomic.Uint32) {
472
473
474 throw("exitThread")
475 }
476
477
478 func semacreate(mp *m) {
479 }
480
481
482 func semasleep(ns int64) int {
483 gp := getg()
484 if ns >= 0 {
485 ms := timediv(ns, 1000000, nil)
486 if ms == 0 {
487 ms = 1
488 }
489 ret := plan9_tsemacquire(&gp.m.waitsemacount, ms)
490 if ret == 1 {
491 return 0
492 }
493 return -1
494 }
495 for plan9_semacquire(&gp.m.waitsemacount, 1) < 0 {
496
497 }
498 return 0
499 }
500
501
502 func semawakeup(mp *m) {
503 plan9_semrelease(&mp.waitsemacount, 1)
504 }
505
506
507 func read(fd int32, buf unsafe.Pointer, n int32) int32 {
508 return pread(fd, buf, n, -1)
509 }
510
511
512 func write1(fd uintptr, buf unsafe.Pointer, n int32) int32 {
513 return pwrite(int32(fd), buf, n, -1)
514 }
515
516 var _badsignal = []byte("runtime: signal received on thread not created by Go.\n")
517
518
519
520
521 func badsignal2() {
522 pwrite(2, unsafe.Pointer(&_badsignal[0]), int32(len(_badsignal)), -1)
523 exits(&_badsignal[0])
524 }
525
526 func raisebadsignal(sig uint32) {
527 badsignal2()
528 }
529
530 func _atoi(b []byte) int {
531 n := 0
532 for len(b) > 0 && '0' <= b[0] && b[0] <= '9' {
533 n = n*10 + int(b[0]) - '0'
534 b = b[1:]
535 }
536 return n
537 }
538
539 func signame(sig uint32) string {
540 if sig >= uint32(len(sigtable)) {
541 return ""
542 }
543 return sigtable[sig].name
544 }
545
546 const preemptMSupported = false
547
548 func preemptM(mp *m) {
549
550
551
552 }
553
View as plain text