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