blob: 284f3381d788977232d316a576cff28443e255dd [file] [log] [blame]
David du Colombiere9c57d82014-11-21 19:39:01 +01001// Copyright 2010 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package runtime
6
7import "unsafe"
8
9// Called to initialize a new m (including the bootstrap m).
10// Called on the parent thread (main thread in case of bootstrap), can allocate memory.
11func mpreinit(mp *m) {
12 // Initialize stack and goroutine for note handling.
13 mp.gsignal = malg(32 * 1024)
14 mp.gsignal.m = mp
15 mp.notesig = (*int8)(mallocgc(_ERRMAX, nil, _FlagNoScan))
16 // Initialize stack for handling strings from the
17 // errstr system call, as used in package syscall.
18 mp.errstr = (*byte)(mallocgc(_ERRMAX, nil, _FlagNoScan))
19}
20
21// Called to initialize a new m (including the bootstrap m).
22// Called on the new thread, can not allocate memory.
23func minit() {
24 // Mask all SSE floating-point exceptions
25 // when running on the 64-bit kernel.
26 setfpmasks()
27}
28
29// Called from dropm to undo the effect of an minit.
30func unminit() {
31}
32
33var sysstat = []byte("/dev/sysstat\x00")
34
35func getproccount() int32 {
36 var buf [2048]byte
37 fd := open(&sysstat[0], _OREAD, 0)
38 if fd < 0 {
39 return 1
40 }
41 ncpu := int32(0)
42 for {
43 n := read(fd, unsafe.Pointer(&buf), int32(len(buf)))
44 if n <= 0 {
45 break
46 }
47 for i := int32(0); i < n; i++ {
48 if buf[i] == '\n' {
49 ncpu++
50 }
51 }
52 }
53 close(fd)
54 if ncpu == 0 {
55 ncpu = 1
56 }
57 return ncpu
58}
59
60var pid = []byte("#c/pid\x00")
61
62func getpid() uint64 {
63 var b [20]byte
64 fd := open(&pid[0], 0, 0)
65 if fd >= 0 {
66 read(fd, unsafe.Pointer(&b), int32(len(b)))
67 close(fd)
68 }
69 c := b[:]
70 for c[0] == ' ' || c[0] == '\t' {
71 c = c[1:]
72 }
David du Colombier29b4e342014-12-29 17:35:42 +010073 return uint64(_atoi(c))
David du Colombiere9c57d82014-11-21 19:39:01 +010074}
75
76func osinit() {
77 initBloc()
78 ncpu = getproccount()
79 getg().m.procid = getpid()
80 notify(unsafe.Pointer(funcPC(sigtramp)))
81}
82
83func crash() {
84 notify(nil)
85 *(*int)(nil) = 0
86}
87
David du Colombiere9c57d82014-11-21 19:39:01 +010088//go:nosplit
Keith Randall6820be22014-12-09 14:40:40 -080089func getRandomData(r []byte) {
David du Colombier5c2233f2015-03-01 18:08:15 +010090 extendRandom(r, 0)
David du Colombiere9c57d82014-11-21 19:39:01 +010091}
92
93func goenvs() {
94}
95
96func initsig() {
97}
98
99//go:nosplit
100func osyield() {
101 sleep(0)
102}
103
104//go:nosplit
105func usleep(µs uint32) {
106 ms := int32(µs / 1000)
107 if ms == 0 {
108 ms = 1
109 }
110 sleep(ms)
111}
112
113//go:nosplit
114func nanotime() int64 {
115 var scratch int64
116 ns := nsec(&scratch)
117 // TODO(aram): remove hack after I fix _nsec in the pc64 kernel.
118 if ns == 0 {
119 return scratch
120 }
121 return ns
122}
123
124//go:nosplit
125func itoa(buf []byte, val uint64) []byte {
126 i := len(buf) - 1
127 for val >= 10 {
128 buf[i] = byte(val%10 + '0')
129 i--
130 val /= 10
131 }
132 buf[i] = byte(val + '0')
133 return buf[i:]
134}
135
136var goexits = []byte("go: exit ")
137
138func goexitsall(status *byte) {
139 var buf [_ERRMAX]byte
140 n := copy(buf[:], goexits)
141 n = copy(buf[n:], gostringnocopy(status))
142 pid := getpid()
143 for mp := (*m)(atomicloadp(unsafe.Pointer(&allm))); mp != nil; mp = mp.alllink {
144 if mp.procid != pid {
145 postnote(mp.procid, buf[:])
146 }
147 }
148}
149
150var procdir = []byte("/proc/")
151var notefile = []byte("/note\x00")
152
153func postnote(pid uint64, msg []byte) int {
154 var buf [128]byte
155 var tmp [32]byte
156 n := copy(buf[:], procdir)
157 n += copy(buf[n:], itoa(tmp[:], pid))
158 copy(buf[n:], notefile)
159 fd := open(&buf[0], _OWRITE, 0)
160 if fd < 0 {
161 return -1
162 }
163 len := findnull(&msg[0])
164 if write(uintptr(fd), (unsafe.Pointer)(&msg[0]), int32(len)) != int64(len) {
165 close(fd)
166 return -1
167 }
168 close(fd)
169 return 0
170}
171
172//go:nosplit
173func exit(e int) {
174 var status []byte
175 if e == 0 {
176 status = []byte("\x00")
177 } else {
178 // build error string
179 var tmp [32]byte
David du Colombier10be7972014-12-23 11:09:15 +0100180 status = []byte(gostringnocopy(&itoa(tmp[:len(tmp)-1], uint64(e))[0]))
David du Colombiere9c57d82014-11-21 19:39:01 +0100181 }
182 goexitsall(&status[0])
183 exits(&status[0])
184}
185
Austin Clements9e6f7aa2015-03-29 10:20:54 -0400186// May run with m.p==nil, so write barriers are not allowed.
Austin Clements392336f2015-03-26 15:50:22 -0400187//go:nowritebarrier
David du Colombiere9c57d82014-11-21 19:39:01 +0100188func newosproc(mp *m, stk unsafe.Pointer) {
189 if false {
190 print("newosproc mp=", mp, " ostk=", &mp, "\n")
191 }
192 pid := rfork(_RFPROC | _RFMEM | _RFNOWAIT)
193 if pid < 0 {
Keith Randallb2a950b2014-12-27 20:58:00 -0800194 throw("newosproc: rfork failed")
David du Colombiere9c57d82014-11-21 19:39:01 +0100195 }
196 if pid == 0 {
197 tstart_plan9(mp)
198 }
199}
200
201//go:nosplit
202func semacreate() uintptr {
203 return 1
204}
205
206//go:nosplit
207func semasleep(ns int64) int {
208 _g_ := getg()
209 if ns >= 0 {
210 ms := timediv(ns, 1000000, nil)
211 if ms == 0 {
212 ms = 1
213 }
214 ret := plan9_tsemacquire(&_g_.m.waitsemacount, ms)
215 if ret == 1 {
216 return 0 // success
217 }
218 return -1 // timeout or interrupted
219 }
220 for plan9_semacquire(&_g_.m.waitsemacount, 1) < 0 {
221 // interrupted; try again (c.f. lock_sema.go)
222 }
223 return 0 // success
224}
225
226//go:nosplit
227func semawakeup(mp *m) {
228 plan9_semrelease(&mp.waitsemacount, 1)
229}
230
231//go:nosplit
232func read(fd int32, buf unsafe.Pointer, n int32) int32 {
233 return pread(fd, buf, n, -1)
234}
235
236//go:nosplit
237func write(fd uintptr, buf unsafe.Pointer, n int32) int64 {
238 return int64(pwrite(int32(fd), buf, n, -1))
239}
240
241func memlimit() uint64 {
242 return 0
243}
244
245var _badsignal = []byte("runtime: signal received on thread not created by Go.\n")
246
247// This runs on a foreign stack, without an m or a g. No stack split.
248//go:nosplit
249func badsignal2() {
250 pwrite(2, unsafe.Pointer(&_badsignal[0]), int32(len(_badsignal)), -1)
251 exits(&_badsignal[0])
252}
253
David du Colombier29b4e342014-12-29 17:35:42 +0100254func _atoi(b []byte) int {
David du Colombiere9c57d82014-11-21 19:39:01 +0100255 n := 0
256 for len(b) > 0 && '0' <= b[0] && b[0] <= '9' {
257 n = n*10 + int(b[0]) - '0'
258 b = b[1:]
259 }
260 return n
261}