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