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