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