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