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 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 getRandomData(r []byte) {
331
332 t := nanotime()
333 v := getg().m.procid ^ uint64(t)
334
335 for len(r) > 0 {
336 v ^= 0xa0761d6478bd642f
337 v *= 0xe7037ed1a0b428db
338 size := 8
339 if len(r) < 8 {
340 size = len(r)
341 }
342 for i := 0; i < size; i++ {
343 r[i] = byte(v >> (8 * i))
344 }
345 r = r[size:]
346 v = v>>32 | v<<32
347 }
348 }
349
350 func initsig(preinit bool) {
351 if !preinit {
352 notify(unsafe.Pointer(abi.FuncPCABI0(sigtramp)))
353 }
354 }
355
356
357 func osyield() {
358 sleep(0)
359 }
360
361
362 func osyield_no_g() {
363 osyield()
364 }
365
366
367 func usleep(µs uint32) {
368 ms := int32(µs / 1000)
369 if ms == 0 {
370 ms = 1
371 }
372 sleep(ms)
373 }
374
375
376 func usleep_no_g(usec uint32) {
377 usleep(usec)
378 }
379
380
381 func nanotime1() int64 {
382 var scratch int64
383 ns := nsec(&scratch)
384
385 if ns == 0 {
386 return scratch
387 }
388 return ns
389 }
390
391 var goexits = []byte("go: exit ")
392 var emptystatus = []byte("\x00")
393 var exiting uint32
394
395 func goexitsall(status *byte) {
396 var buf [_ERRMAX]byte
397 if !atomic.Cas(&exiting, 0, 1) {
398 return
399 }
400 getg().m.locks++
401 n := copy(buf[:], goexits)
402 n = copy(buf[n:], gostringnocopy(status))
403 pid := getpid()
404 for mp := (*m)(atomic.Loadp(unsafe.Pointer(&allm))); mp != nil; mp = mp.alllink {
405 if mp.procid != 0 && mp.procid != pid {
406 postnote(mp.procid, buf[:])
407 }
408 }
409 getg().m.locks--
410 }
411
412 var procdir = []byte("/proc/")
413 var notefile = []byte("/note\x00")
414
415 func postnote(pid uint64, msg []byte) int {
416 var buf [128]byte
417 var tmp [32]byte
418 n := copy(buf[:], procdir)
419 n += copy(buf[n:], itoa(tmp[:], pid))
420 copy(buf[n:], notefile)
421 fd := open(&buf[0], _OWRITE, 0)
422 if fd < 0 {
423 return -1
424 }
425 len := findnull(&msg[0])
426 if write1(uintptr(fd), unsafe.Pointer(&msg[0]), int32(len)) != int32(len) {
427 closefd(fd)
428 return -1
429 }
430 closefd(fd)
431 return 0
432 }
433
434
435 func exit(e int32) {
436 var status []byte
437 if e == 0 {
438 status = emptystatus
439 } else {
440
441 var tmp [32]byte
442 sl := itoa(tmp[:len(tmp)-1], uint64(e))
443
444 status = sl[:len(sl)+1]
445 }
446 goexitsall(&status[0])
447 exits(&status[0])
448 }
449
450
451
452
453 func newosproc(mp *m) {
454 if false {
455 print("newosproc mp=", mp, " ostk=", &mp, "\n")
456 }
457 pid := rfork(_RFPROC | _RFMEM | _RFNOWAIT)
458 if pid < 0 {
459 throw("newosproc: rfork failed")
460 }
461 if pid == 0 {
462 tstart_plan9(mp)
463 }
464 }
465
466 func exitThread(wait *atomic.Uint32) {
467
468
469 throw("exitThread")
470 }
471
472
473 func semacreate(mp *m) {
474 }
475
476
477 func semasleep(ns int64) int {
478 gp := getg()
479 if ns >= 0 {
480 ms := timediv(ns, 1000000, nil)
481 if ms == 0 {
482 ms = 1
483 }
484 ret := plan9_tsemacquire(&gp.m.waitsemacount, ms)
485 if ret == 1 {
486 return 0
487 }
488 return -1
489 }
490 for plan9_semacquire(&gp.m.waitsemacount, 1) < 0 {
491
492 }
493 return 0
494 }
495
496
497 func semawakeup(mp *m) {
498 plan9_semrelease(&mp.waitsemacount, 1)
499 }
500
501
502 func read(fd int32, buf unsafe.Pointer, n int32) int32 {
503 return pread(fd, buf, n, -1)
504 }
505
506
507 func write1(fd uintptr, buf unsafe.Pointer, n int32) int32 {
508 return pwrite(int32(fd), buf, n, -1)
509 }
510
511 var _badsignal = []byte("runtime: signal received on thread not created by Go.\n")
512
513
514
515
516 func badsignal2() {
517 pwrite(2, unsafe.Pointer(&_badsignal[0]), int32(len(_badsignal)), -1)
518 exits(&_badsignal[0])
519 }
520
521 func raisebadsignal(sig uint32) {
522 badsignal2()
523 }
524
525 func _atoi(b []byte) int {
526 n := 0
527 for len(b) > 0 && '0' <= b[0] && b[0] <= '9' {
528 n = n*10 + int(b[0]) - '0'
529 b = b[1:]
530 }
531 return n
532 }
533
534 func signame(sig uint32) string {
535 if sig >= uint32(len(sigtable)) {
536 return ""
537 }
538 return sigtable[sig].name
539 }
540
541 const preemptMSupported = false
542
543 func preemptM(mp *m) {
544
545
546
547 }
548
View as plain text