1 // Copyright 2011 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
12 // From FreeBSD's <sys/sysctl.h>
18 var sigset_all = sigset{[4]uint32{^uint32(0), ^uint32(0), ^uint32(0), ^uint32(0)}}
20 func getncpu() int32 {
21 mib := [2]uint32{_CTL_HW, _HW_NCPU}
23 nout := unsafe.Sizeof(out)
24 ret := sysctl(&mib[0], 2, (*byte)(unsafe.Pointer(&out)), &nout, nil, 0)
31 // FreeBSD's umtx_op syscall is effectively the same as Linux's futex, and
32 // thus the code is largely similar. See Linux implementation
33 // and lock_futex.go for comments.
36 func futexsleep(addr *uint32, val uint32, ns int64) {
38 futexsleep1(addr, val, ns)
42 func futexsleep1(addr *uint32, val uint32, ns int64) {
47 ts.set_sec(int64(timediv(ns, 1000000000, (*int32)(unsafe.Pointer(&ts.tv_nsec)))))
50 ret := sys_umtx_op(addr, _UMTX_OP_WAIT_UINT_PRIVATE, val, nil, tsp)
51 if ret >= 0 || ret == -_EINTR {
54 print("umtx_wait addr=", addr, " val=", val, " ret=", ret, "\n")
55 *(*int32)(unsafe.Pointer(uintptr(0x1005))) = 0x1005
59 func futexwakeup(addr *uint32, cnt uint32) {
60 ret := sys_umtx_op(addr, _UMTX_OP_WAKE_PRIVATE, cnt, nil, nil)
66 print("umtx_wake_addr=", addr, " ret=", ret, "\n")
72 // May run with m.p==nil, so write barriers are not allowed.
74 func newosproc(mp *m, stk unsafe.Pointer) {
76 print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " thr_start=", funcPC(thr_start), " id=", mp.id, "/", mp.tls[0], " ostk=", &mp, "\n")
79 // NOTE(rsc): This code is confused. stackbase is the top of the stack
80 // and is equal to stk. However, it's working, so I'm not changing it.
82 start_func: funcPC(thr_start),
83 arg: unsafe.Pointer(mp),
84 stack_base: mp.g0.stack.hi,
85 stack_size: uintptr(stk) - mp.g0.stack.hi,
86 child_tid: unsafe.Pointer(&mp.procid),
88 tls_base: unsafe.Pointer(&mp.tls[0]),
89 tls_size: unsafe.Sizeof(mp.tls),
91 mp.tls[0] = uintptr(mp.id) // so 386 asm can find it
94 sigprocmask(_SIG_SETMASK, &sigset_all, &oset)
95 thr_new(¶m, int32(unsafe.Sizeof(param)))
96 sigprocmask(_SIG_SETMASK, &oset, nil)
103 var urandom_dev = []byte("/dev/urandom\x00")
106 func getRandomData(r []byte) {
107 fd := open(&urandom_dev[0], 0 /* O_RDONLY */, 0)
108 n := read(fd, unsafe.Pointer(&r[0]), int32(len(r)))
110 extendRandom(r, int(n))
117 // Called to initialize a new m (including the bootstrap m).
118 // Called on the parent thread (main thread in case of bootstrap), can allocate memory.
119 func mpreinit(mp *m) {
120 mp.gsignal = malg(32 * 1024)
124 func msigsave(mp *m) {
125 smask := (*sigset)(unsafe.Pointer(&mp.sigmask))
126 if unsafe.Sizeof(*smask) > unsafe.Sizeof(mp.sigmask) {
127 throw("insufficient storage for signal mask")
129 sigprocmask(_SIG_SETMASK, nil, smask)
132 // Called to initialize a new m (including the bootstrap m).
133 // Called on the new thread, can not allocate memory.
137 // m.procid is a uint64, but thr_new writes a uint32 on 32-bit systems.
138 // Fix it up. (Only matters on big-endian, but be clean anyway.)
139 if sys.PtrSize == 4 {
140 _g_.m.procid = uint64(*(*uint32)(unsafe.Pointer(&_g_.m.procid)))
143 // Initialize signal handling.
144 signalstack(&_g_.m.gsignal.stack)
146 // restore signal mask from m.sigmask and unblock essential signals
147 nmask := *(*sigset)(unsafe.Pointer(&_g_.m.sigmask))
148 for i := range sigtable {
149 if sigtable[i].flags&_SigUnblock != 0 {
150 nmask.__bits[(i-1)/32] &^= 1 << ((uint32(i) - 1) & 31)
153 sigprocmask(_SIG_SETMASK, &nmask, nil)
156 // Called from dropm to undo the effect of an minit.
159 smask := (*sigset)(unsafe.Pointer(&_g_.m.sigmask))
160 sigprocmask(_SIG_SETMASK, smask, nil)
164 func memlimit() uintptr {
166 TODO: Convert to Go when something actually uses the result.
168 extern byte runtime·text[], runtime·end[];
171 if(runtime·getrlimit(RLIMIT_AS, &rl) != 0)
173 if(rl.rlim_cur >= 0x7fffffff)
176 // Estimate our VM footprint excluding the heap.
177 // Not an exact science: use size of binary plus
178 // some room for thread stacks.
179 used = runtime·end - runtime·text + (64<<20);
180 if(used >= rl.rlim_cur)
183 // If there's not at least 16 MB left, we're probably
184 // not going to be able to do much. Treat as no limit.
186 if(rl.rlim_cur < (16<<20))
189 return rl.rlim_cur - used;
197 type sigactiont struct {
203 func setsig(i int32, fn uintptr, restart bool) {
205 sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK
207 sa.sa_flags |= _SA_RESTART
209 sa.sa_mask = sigset_all
210 if fn == funcPC(sighandler) {
211 fn = funcPC(sigtramp)
214 sigaction(i, &sa, nil)
217 func setsigstack(i int32) {
221 func getsig(i int32) uintptr {
223 sigaction(i, nil, &sa)
224 if sa.sa_handler == funcPC(sigtramp) {
225 return funcPC(sighandler)
230 func signalstack(s *stack) {
233 st.ss_flags = _SS_DISABLE
236 st.ss_size = s.hi - s.lo
239 sigaltstack(&st, nil)
242 func updatesigmask(m [(_NSIG + 31) / 32]uint32) {
244 copy(mask.__bits[:], m[:])
245 sigprocmask(_SIG_SETMASK, &mask, nil)
248 func unblocksig(sig int32) {
250 mask.__bits[(sig-1)/32] |= 1 << ((uint32(sig) - 1) & 31)
251 sigprocmask(_SIG_UNBLOCK, &mask, nil)