Source file
src/runtime/os_freebsd.go
Documentation: runtime
1
2
3
4
5 package runtime
6
7 import (
8 "runtime/internal/sys"
9 "unsafe"
10 )
11
12 type mOS struct{}
13
14
15 func thr_new(param *thrparam, size int32) int32
16
17
18 func sigaltstack(new, old *stackt)
19
20
21 func sigprocmask(how int32, new, old *sigset)
22
23
24 func setitimer(mode int32, new, old *itimerval)
25
26
27 func sysctl(mib *uint32, miblen uint32, out *byte, size *uintptr, dst *byte, ndst uintptr) int32
28
29 func raiseproc(sig uint32)
30
31 func thr_self() thread
32 func thr_kill(tid thread, sig int)
33
34
35 func sys_umtx_op(addr *uint32, mode int32, val uint32, uaddr1 uintptr, ut *umtx_time) int32
36
37 func osyield()
38
39
40 func osyield_no_g() {
41 osyield()
42 }
43
44 func kqueue() int32
45
46
47 func kevent(kq int32, ch *keventt, nch int32, ev *keventt, nev int32, ts *timespec) int32
48
49 func pipe() (r, w int32, errno int32)
50 func pipe2(flags int32) (r, w int32, errno int32)
51 func closeonexec(fd int32)
52 func setNonblock(fd int32)
53
54
55 const (
56 _CTL_HW = 6
57 _HW_PAGESIZE = 7
58 )
59
60 var sigset_all = sigset{[4]uint32{^uint32(0), ^uint32(0), ^uint32(0), ^uint32(0)}}
61
62
63 const (
64 _CTL_QUERY = 0
65 _CTL_QUERY_MIB = 3
66 )
67
68
69
70 func sysctlnametomib(name []byte, mib *[_CTL_MAXNAME]uint32) uint32 {
71 oid := [2]uint32{_CTL_QUERY, _CTL_QUERY_MIB}
72 miblen := uintptr(_CTL_MAXNAME)
73 if sysctl(&oid[0], 2, (*byte)(unsafe.Pointer(mib)), &miblen, (*byte)(unsafe.Pointer(&name[0])), (uintptr)(len(name))) < 0 {
74 return 0
75 }
76 miblen /= unsafe.Sizeof(uint32(0))
77 if miblen <= 0 {
78 return 0
79 }
80 return uint32(miblen)
81 }
82
83 const (
84 _CPU_CURRENT_PID = -1
85 )
86
87
88 func cpuset_getaffinity(level int, which int, id int64, size int, mask *byte) int32
89
90
91 func getncpu() int32 {
92
93
94
95 const maxCPUs = 64 * 1024
96 var mask [maxCPUs / 8]byte
97 var mib [_CTL_MAXNAME]uint32
98
99
100
101
102
103
104
105
106 miblen := sysctlnametomib([]byte("kern.smp.maxcpus"), &mib)
107 if miblen == 0 {
108 return 1
109 }
110
111
112 dstsize := uintptr(4)
113 maxcpus := uint32(0)
114 if sysctl(&mib[0], miblen, (*byte)(unsafe.Pointer(&maxcpus)), &dstsize, nil, 0) != 0 {
115 return 1
116 }
117
118 maskSize := int(maxcpus+7) / 8
119 if maskSize < sys.PtrSize {
120 maskSize = sys.PtrSize
121 }
122 if maskSize > len(mask) {
123 maskSize = len(mask)
124 }
125
126 if cpuset_getaffinity(_CPU_LEVEL_WHICH, _CPU_WHICH_PID, _CPU_CURRENT_PID,
127 maskSize, (*byte)(unsafe.Pointer(&mask[0]))) != 0 {
128 return 1
129 }
130 n := int32(0)
131 for _, v := range mask[:maskSize] {
132 for v != 0 {
133 n += int32(v & 1)
134 v >>= 1
135 }
136 }
137 if n == 0 {
138 return 1
139 }
140 return n
141 }
142
143 func getPageSize() uintptr {
144 mib := [2]uint32{_CTL_HW, _HW_PAGESIZE}
145 out := uint32(0)
146 nout := unsafe.Sizeof(out)
147 ret := sysctl(&mib[0], 2, (*byte)(unsafe.Pointer(&out)), &nout, nil, 0)
148 if ret >= 0 {
149 return uintptr(out)
150 }
151 return 0
152 }
153
154
155
156
157
158
159 func futexsleep(addr *uint32, val uint32, ns int64) {
160 systemstack(func() {
161 futexsleep1(addr, val, ns)
162 })
163 }
164
165 func futexsleep1(addr *uint32, val uint32, ns int64) {
166 var utp *umtx_time
167 if ns >= 0 {
168 var ut umtx_time
169 ut._clockid = _CLOCK_MONOTONIC
170 ut._timeout.setNsec(ns)
171 utp = &ut
172 }
173 ret := sys_umtx_op(addr, _UMTX_OP_WAIT_UINT_PRIVATE, val, unsafe.Sizeof(*utp), utp)
174 if ret >= 0 || ret == -_EINTR || ret == -_ETIMEDOUT {
175 return
176 }
177 print("umtx_wait addr=", addr, " val=", val, " ret=", ret, "\n")
178 *(*int32)(unsafe.Pointer(uintptr(0x1005))) = 0x1005
179 }
180
181
182 func futexwakeup(addr *uint32, cnt uint32) {
183 ret := sys_umtx_op(addr, _UMTX_OP_WAKE_PRIVATE, cnt, 0, nil)
184 if ret >= 0 {
185 return
186 }
187
188 systemstack(func() {
189 print("umtx_wake_addr=", addr, " ret=", ret, "\n")
190 })
191 }
192
193 func thr_start()
194
195
196
197 func newosproc(mp *m) {
198 stk := unsafe.Pointer(mp.g0.stack.hi)
199 if false {
200 print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " thr_start=", funcPC(thr_start), " id=", mp.id, " ostk=", &mp, "\n")
201 }
202
203 param := thrparam{
204 start_func: funcPC(thr_start),
205 arg: unsafe.Pointer(mp),
206 stack_base: mp.g0.stack.lo,
207 stack_size: uintptr(stk) - mp.g0.stack.lo,
208 child_tid: nil,
209 parent_tid: nil,
210 tls_base: unsafe.Pointer(&mp.tls[0]),
211 tls_size: unsafe.Sizeof(mp.tls),
212 }
213
214 var oset sigset
215 sigprocmask(_SIG_SETMASK, &sigset_all, &oset)
216 ret := thr_new(¶m, int32(unsafe.Sizeof(param)))
217 sigprocmask(_SIG_SETMASK, &oset, nil)
218 if ret < 0 {
219 print("runtime: failed to create new OS thread (have ", mcount(), " already; errno=", -ret, ")\n")
220 throw("newosproc")
221 }
222 }
223
224
225
226 func newosproc0(stacksize uintptr, fn unsafe.Pointer) {
227 stack := sysAlloc(stacksize, &memstats.stacks_sys)
228 if stack == nil {
229 write(2, unsafe.Pointer(&failallocatestack[0]), int32(len(failallocatestack)))
230 exit(1)
231 }
232
233
234
235
236
237
238 param := thrparam{
239 start_func: funcPC(fn),
240 arg: nil,
241 stack_base: uintptr(stack),
242 stack_size: stacksize,
243 child_tid: nil,
244 parent_tid: nil,
245 tls_base: unsafe.Pointer(&m0.tls[0]),
246 tls_size: unsafe.Sizeof(m0.tls),
247 }
248
249 var oset sigset
250 sigprocmask(_SIG_SETMASK, &sigset_all, &oset)
251 ret := thr_new(¶m, int32(unsafe.Sizeof(param)))
252 sigprocmask(_SIG_SETMASK, &oset, nil)
253 if ret < 0 {
254 write(2, unsafe.Pointer(&failthreadcreate[0]), int32(len(failthreadcreate)))
255 exit(1)
256 }
257 }
258
259 var failallocatestack = []byte("runtime: failed to allocate stack for the new OS thread\n")
260 var failthreadcreate = []byte("runtime: failed to create new OS thread\n")
261
262
263
264
265
266
267 func libpreinit() {
268 initsig(true)
269 }
270
271 func osinit() {
272 ncpu = getncpu()
273 if physPageSize == 0 {
274 physPageSize = getPageSize()
275 }
276 }
277
278 var urandom_dev = []byte("/dev/urandom\x00")
279
280
281 func getRandomData(r []byte) {
282 fd := open(&urandom_dev[0], 0 , 0)
283 n := read(fd, unsafe.Pointer(&r[0]), int32(len(r)))
284 closefd(fd)
285 extendRandom(r, int(n))
286 }
287
288 func goenvs() {
289 goenvs_unix()
290 }
291
292
293
294 func mpreinit(mp *m) {
295 mp.gsignal = malg(32 * 1024)
296 mp.gsignal.m = mp
297 }
298
299
300
301 func minit() {
302 getg().m.procid = uint64(thr_self())
303
304
305
306
307
308
309
310
311
312
313 if gp := getg(); !isarchive && !islibrary && gp.m == &m0 && gp == gp.m.g0 {
314 st := stackt{ss_flags: _SS_DISABLE}
315 sigaltstack(&st, nil)
316 }
317
318 minitSignals()
319 }
320
321
322
323 func unminit() {
324 unminitSignals()
325 }
326
327
328
329 func mdestroy(mp *m) {
330 }
331
332 func sigtramp()
333
334 type sigactiont struct {
335 sa_handler uintptr
336 sa_flags int32
337 sa_mask sigset
338 }
339
340
341
342
343
344 func setsigstack(i uint32) {
345 var sa sigactiont
346 sigaction(i, nil, &sa)
347 if sa.sa_flags&_SA_ONSTACK != 0 {
348 return
349 }
350 sa.sa_flags |= _SA_ONSTACK
351 sigaction(i, &sa, nil)
352 }
353
354
355
356 func getsig(i uint32) uintptr {
357 var sa sigactiont
358 sigaction(i, nil, &sa)
359 return sa.sa_handler
360 }
361
362
363
364 func setSignalstackSP(s *stackt, sp uintptr) {
365 s.ss_sp = sp
366 }
367
368
369
370 func sigaddset(mask *sigset, i int) {
371 mask.__bits[(i-1)/32] |= 1 << ((uint32(i) - 1) & 31)
372 }
373
374 func sigdelset(mask *sigset, i int) {
375 mask.__bits[(i-1)/32] &^= 1 << ((uint32(i) - 1) & 31)
376 }
377
378
379 func (c *sigctxt) fixsigcode(sig uint32) {
380 }
381
382 func sysargs(argc int32, argv **byte) {
383 n := argc + 1
384
385
386 for argv_index(argv, n) != nil {
387 n++
388 }
389
390
391 n++
392
393
394 auxv := (*[1 << 28]uintptr)(add(unsafe.Pointer(argv), uintptr(n)*sys.PtrSize))
395 sysauxv(auxv[:])
396 }
397
398 const (
399 _AT_NULL = 0
400 _AT_PAGESZ = 6
401 _AT_TIMEKEEP = 22
402 _AT_HWCAP = 25
403 _AT_HWCAP2 = 26
404 )
405
406 func sysauxv(auxv []uintptr) {
407 for i := 0; auxv[i] != _AT_NULL; i += 2 {
408 tag, val := auxv[i], auxv[i+1]
409 switch tag {
410
411 case _AT_PAGESZ:
412 physPageSize = val
413 case _AT_TIMEKEEP:
414 timekeepSharedPage = (*vdsoTimekeep)(unsafe.Pointer(val))
415 }
416
417 archauxv(tag, val)
418 }
419 }
420
421
422
423 func sysSigaction(sig uint32, new, old *sigactiont) {
424
425 if asmSigaction(uintptr(sig), new, old) != 0 {
426 systemstack(func() {
427 throw("sigaction failed")
428 })
429 }
430 }
431
432
433
434 func asmSigaction(sig uintptr, new, old *sigactiont) int32
435
436
437
438
439
440
441
442 func raise(sig uint32) {
443 thr_kill(thr_self(), int(sig))
444 }
445
446 func signalM(mp *m, sig int) {
447 thr_kill(thread(mp.procid), sig)
448 }
449
View as plain text