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 pipe() (r, w int32, errno int32)
51 func pipe2(flags int32) (r, w int32, errno int32)
52 func closeonexec(fd int32)
53 func setNonblock(fd 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 func newosproc(mp *m) {
199 stk := unsafe.Pointer(mp.g0.stack.hi)
200 if false {
201 print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " thr_start=", abi.FuncPCABI0(thr_start), " id=", mp.id, " ostk=", &mp, "\n")
202 }
203
204 param := thrparam{
205 start_func: abi.FuncPCABI0(thr_start),
206 arg: unsafe.Pointer(mp),
207 stack_base: mp.g0.stack.lo,
208 stack_size: uintptr(stk) - mp.g0.stack.lo,
209 child_tid: nil,
210 parent_tid: nil,
211 tls_base: unsafe.Pointer(&mp.tls[0]),
212 tls_size: unsafe.Sizeof(mp.tls),
213 }
214
215 var oset sigset
216 sigprocmask(_SIG_SETMASK, &sigset_all, &oset)
217 ret := thr_new(¶m, int32(unsafe.Sizeof(param)))
218 sigprocmask(_SIG_SETMASK, &oset, nil)
219 if ret < 0 {
220 print("runtime: failed to create new OS thread (have ", mcount(), " already; errno=", -ret, ")\n")
221 throw("newosproc")
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 func libpreinit() {
269 initsig(true)
270 }
271
272 func osinit() {
273 ncpu = getncpu()
274 if physPageSize == 0 {
275 physPageSize = getPageSize()
276 }
277 }
278
279 var urandom_dev = []byte("/dev/urandom\x00")
280
281
282 func getRandomData(r []byte) {
283 fd := open(&urandom_dev[0], 0 , 0)
284 n := read(fd, unsafe.Pointer(&r[0]), int32(len(r)))
285 closefd(fd)
286 extendRandom(r, int(n))
287 }
288
289 func goenvs() {
290 goenvs_unix()
291 }
292
293
294
295 func mpreinit(mp *m) {
296 mp.gsignal = malg(32 * 1024)
297 mp.gsignal.m = mp
298 }
299
300
301
302 func minit() {
303 getg().m.procid = uint64(thr_self())
304
305
306
307
308
309
310
311
312
313
314 if gp := getg(); !isarchive && !islibrary && gp.m == &m0 && gp == gp.m.g0 {
315 st := stackt{ss_flags: _SS_DISABLE}
316 sigaltstack(&st, nil)
317 }
318
319 minitSignals()
320 }
321
322
323
324 func unminit() {
325 unminitSignals()
326 }
327
328
329
330 func mdestroy(mp *m) {
331 }
332
333 func sigtramp()
334
335 type sigactiont struct {
336 sa_handler uintptr
337 sa_flags int32
338 sa_mask sigset
339 }
340
341
342
343
344
345 func setsigstack(i uint32) {
346 var sa sigactiont
347 sigaction(i, nil, &sa)
348 if sa.sa_flags&_SA_ONSTACK != 0 {
349 return
350 }
351 sa.sa_flags |= _SA_ONSTACK
352 sigaction(i, &sa, nil)
353 }
354
355
356
357 func getsig(i uint32) uintptr {
358 var sa sigactiont
359 sigaction(i, nil, &sa)
360 return sa.sa_handler
361 }
362
363
364
365 func setSignalstackSP(s *stackt, sp uintptr) {
366 s.ss_sp = sp
367 }
368
369
370
371 func sigaddset(mask *sigset, i int) {
372 mask.__bits[(i-1)/32] |= 1 << ((uint32(i) - 1) & 31)
373 }
374
375 func sigdelset(mask *sigset, i int) {
376 mask.__bits[(i-1)/32] &^= 1 << ((uint32(i) - 1) & 31)
377 }
378
379
380 func (c *sigctxt) fixsigcode(sig uint32) {
381 }
382
383 func setProcessCPUProfiler(hz int32) {
384 setProcessCPUProfilerTimer(hz)
385 }
386
387 func setThreadCPUProfiler(hz int32) {
388 setThreadCPUProfilerHz(hz)
389 }
390
391
392 func validSIGPROF(mp *m, c *sigctxt) bool {
393 return true
394 }
395
396 func sysargs(argc int32, argv **byte) {
397 n := argc + 1
398
399
400 for argv_index(argv, n) != nil {
401 n++
402 }
403
404
405 n++
406
407
408 auxv := (*[1 << 28]uintptr)(add(unsafe.Pointer(argv), uintptr(n)*goarch.PtrSize))
409 sysauxv(auxv[:])
410 }
411
412 const (
413 _AT_NULL = 0
414 _AT_PAGESZ = 6
415 _AT_TIMEKEEP = 22
416 _AT_HWCAP = 25
417 _AT_HWCAP2 = 26
418 )
419
420 func sysauxv(auxv []uintptr) {
421 for i := 0; auxv[i] != _AT_NULL; i += 2 {
422 tag, val := auxv[i], auxv[i+1]
423 switch tag {
424
425 case _AT_PAGESZ:
426 physPageSize = val
427 case _AT_TIMEKEEP:
428 timekeepSharedPage = (*vdsoTimekeep)(unsafe.Pointer(val))
429 }
430
431 archauxv(tag, val)
432 }
433 }
434
435
436
437 func sysSigaction(sig uint32, new, old *sigactiont) {
438
439 if asmSigaction(uintptr(sig), new, old) != 0 {
440 systemstack(func() {
441 throw("sigaction failed")
442 })
443 }
444 }
445
446
447
448 func asmSigaction(sig uintptr, new, old *sigactiont) int32
449
450
451
452
453
454
455
456 func raise(sig uint32) {
457 thr_kill(thr_self(), int(sig))
458 }
459
460 func signalM(mp *m, sig int) {
461 thr_kill(thread(mp.procid), sig)
462 }
463
464
465
466 const sigPerThreadSyscall = 1 << 31
467
468
469 func runPerThreadSyscall() {
470 throw("runPerThreadSyscall only valid on linux")
471 }
472
View as plain text