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