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