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
223
224
225 func mdestroy(mp *m) {
226 }
227
228 var sysstat = []byte("/dev/sysstat\x00")
229
230 func getproccount() int32 {
231 var buf [2048]byte
232 fd := open(&sysstat[0], _OREAD, 0)
233 if fd < 0 {
234 return 1
235 }
236 ncpu := int32(0)
237 for {
238 n := read(fd, unsafe.Pointer(&buf), int32(len(buf)))
239 if n <= 0 {
240 break
241 }
242 for i := int32(0); i < n; i++ {
243 if buf[i] == '\n' {
244 ncpu++
245 }
246 }
247 }
248 closefd(fd)
249 if ncpu == 0 {
250 ncpu = 1
251 }
252 return ncpu
253 }
254
255 var devswap = []byte("/dev/swap\x00")
256 var pagesize = []byte(" pagesize\n")
257
258 func getPageSize() uintptr {
259 var buf [2048]byte
260 var pos int
261 fd := open(&devswap[0], _OREAD, 0)
262 if fd < 0 {
263
264
265
266 return minPhysPageSize
267 }
268 for pos < len(buf) {
269 n := read(fd, unsafe.Pointer(&buf[pos]), int32(len(buf)-pos))
270 if n <= 0 {
271 break
272 }
273 pos += int(n)
274 }
275 closefd(fd)
276 text := buf[:pos]
277
278 bol := 0
279 for i, c := range text {
280 if c == '\n' {
281 bol = i + 1
282 }
283 if bytesHasPrefix(text[i:], pagesize) {
284
285 return uintptr(_atoi(text[bol:]))
286 }
287 }
288
289 return minPhysPageSize
290 }
291
292 func bytesHasPrefix(s, prefix []byte) bool {
293 if len(s) < len(prefix) {
294 return false
295 }
296 for i, p := range prefix {
297 if s[i] != p {
298 return false
299 }
300 }
301 return true
302 }
303
304 var pid = []byte("#c/pid\x00")
305
306 func getpid() uint64 {
307 var b [20]byte
308 fd := open(&pid[0], 0, 0)
309 if fd >= 0 {
310 read(fd, unsafe.Pointer(&b), int32(len(b)))
311 closefd(fd)
312 }
313 c := b[:]
314 for c[0] == ' ' || c[0] == '\t' {
315 c = c[1:]
316 }
317 return uint64(_atoi(c))
318 }
319
320 func osinit() {
321 physPageSize = getPageSize()
322 initBloc()
323 ncpu = getproccount()
324 getg().m.procid = getpid()
325 }
326
327
328 func crash() {
329 notify(nil)
330 *(*int)(nil) = 0
331 }
332
333
334 func readRandom(r []byte) int {
335 return 0
336 }
337
338 func initsig(preinit bool) {
339 if !preinit {
340 notify(unsafe.Pointer(abi.FuncPCABI0(sigtramp)))
341 }
342 }
343
344
345 func osyield() {
346 sleep(0)
347 }
348
349
350 func osyield_no_g() {
351 osyield()
352 }
353
354
355 func usleep(µs uint32) {
356 ms := int32(µs / 1000)
357 if ms == 0 {
358 ms = 1
359 }
360 sleep(ms)
361 }
362
363
364 func usleep_no_g(usec uint32) {
365 usleep(usec)
366 }
367
368
369 func nanotime1() int64 {
370 var scratch int64
371 ns := nsec(&scratch)
372
373 if ns == 0 {
374 return scratch
375 }
376 return ns
377 }
378
379 var goexits = []byte("go: exit ")
380 var emptystatus = []byte("\x00")
381 var exiting uint32
382
383 func goexitsall(status *byte) {
384 var buf [_ERRMAX]byte
385 if !atomic.Cas(&exiting, 0, 1) {
386 return
387 }
388 getg().m.locks++
389 n := copy(buf[:], goexits)
390 n = copy(buf[n:], gostringnocopy(status))
391 pid := getpid()
392 for mp := (*m)(atomic.Loadp(unsafe.Pointer(&allm))); mp != nil; mp = mp.alllink {
393 if mp.procid != 0 && mp.procid != pid {
394 postnote(mp.procid, buf[:])
395 }
396 }
397 getg().m.locks--
398 }
399
400 var procdir = []byte("/proc/")
401 var notefile = []byte("/note\x00")
402
403 func postnote(pid uint64, msg []byte) int {
404 var buf [128]byte
405 var tmp [32]byte
406 n := copy(buf[:], procdir)
407 n += copy(buf[n:], itoa(tmp[:], pid))
408 copy(buf[n:], notefile)
409 fd := open(&buf[0], _OWRITE, 0)
410 if fd < 0 {
411 return -1
412 }
413 len := findnull(&msg[0])
414 if write1(uintptr(fd), unsafe.Pointer(&msg[0]), int32(len)) != int32(len) {
415 closefd(fd)
416 return -1
417 }
418 closefd(fd)
419 return 0
420 }
421
422
423 func exit(e int32) {
424 var status []byte
425 if e == 0 {
426 status = emptystatus
427 } else {
428
429 var tmp [32]byte
430 sl := itoa(tmp[:len(tmp)-1], uint64(e))
431
432 status = sl[:len(sl)+1]
433 }
434 goexitsall(&status[0])
435 exits(&status[0])
436 }
437
438
439
440
441 func newosproc(mp *m) {
442 if false {
443 print("newosproc mp=", mp, " ostk=", &mp, "\n")
444 }
445 pid := rfork(_RFPROC | _RFMEM | _RFNOWAIT)
446 if pid < 0 {
447 throw("newosproc: rfork failed")
448 }
449 if pid == 0 {
450 tstart_plan9(mp)
451 }
452 }
453
454 func exitThread(wait *atomic.Uint32) {
455
456
457 throw("exitThread")
458 }
459
460
461 func semacreate(mp *m) {
462 }
463
464
465 func semasleep(ns int64) int {
466 gp := getg()
467 if ns >= 0 {
468 ms := timediv(ns, 1000000, nil)
469 if ms == 0 {
470 ms = 1
471 }
472 ret := plan9_tsemacquire(&gp.m.waitsemacount, ms)
473 if ret == 1 {
474 return 0
475 }
476 return -1
477 }
478 for plan9_semacquire(&gp.m.waitsemacount, 1) < 0 {
479
480 }
481 return 0
482 }
483
484
485 func semawakeup(mp *m) {
486 plan9_semrelease(&mp.waitsemacount, 1)
487 }
488
489
490 func read(fd int32, buf unsafe.Pointer, n int32) int32 {
491 return pread(fd, buf, n, -1)
492 }
493
494
495 func write1(fd uintptr, buf unsafe.Pointer, n int32) int32 {
496 return pwrite(int32(fd), buf, n, -1)
497 }
498
499 var _badsignal = []byte("runtime: signal received on thread not created by Go.\n")
500
501
502
503
504 func badsignal2() {
505 pwrite(2, unsafe.Pointer(&_badsignal[0]), int32(len(_badsignal)), -1)
506 exits(&_badsignal[0])
507 }
508
509 func raisebadsignal(sig uint32) {
510 badsignal2()
511 }
512
513 func _atoi(b []byte) int {
514 n := 0
515 for len(b) > 0 && '0' <= b[0] && b[0] <= '9' {
516 n = n*10 + int(b[0]) - '0'
517 b = b[1:]
518 }
519 return n
520 }
521
522 func signame(sig uint32) string {
523 if sig >= uint32(len(sigtable)) {
524 return ""
525 }
526 return sigtable[sig].name
527 }
528
529 const preemptMSupported = false
530
531 func preemptM(mp *m) {
532
533
534
535 }
536
View as plain text