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