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.
9 // From FreeBSD's <sys/sysctl.h>
15 var sigset_none = sigset{}
16 var sigset_all = sigset{[4]uint32{^uint32(0), ^uint32(0), ^uint32(0), ^uint32(0)}}
18 func getncpu() int32 {
19 mib := [2]uint32{_CTL_HW, _HW_NCPU}
21 nout := unsafe.Sizeof(out)
22 ret := sysctl(&mib[0], 2, (*byte)(unsafe.Pointer(&out)), &nout, nil, 0)
29 // FreeBSD's umtx_op syscall is effectively the same as Linux's futex, and
30 // thus the code is largely similar. See Linux implementation
31 // and lock_futex.c for comments.
34 func futexsleep(addr *uint32, val uint32, ns int64) {
36 futexsleep1(addr, val, ns)
40 func futexsleep1(addr *uint32, val uint32, ns int64) {
45 ts.set_sec(int64(timediv(ns, 1000000000, (*int32)(unsafe.Pointer(&ts.tv_nsec)))))
48 ret := sys_umtx_op(addr, _UMTX_OP_WAIT_UINT_PRIVATE, val, nil, tsp)
49 if ret >= 0 || ret == -_EINTR {
52 print("umtx_wait addr=", addr, " val=", val, " ret=", ret, "\n")
53 *(*int32)(unsafe.Pointer(uintptr(0x1005))) = 0x1005
57 func futexwakeup(addr *uint32, cnt uint32) {
58 ret := sys_umtx_op(addr, _UMTX_OP_WAKE_PRIVATE, cnt, nil, nil)
64 print("umtx_wake_addr=", addr, " ret=", ret, "\n")
70 func newosproc(mp *m, stk unsafe.Pointer) {
72 print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " thr_start=", funcPC(thr_start), " id=", mp.id, "/", mp.tls[0], " ostk=", &mp, "\n")
75 // NOTE(rsc): This code is confused. stackbase is the top of the stack
76 // and is equal to stk. However, it's working, so I'm not changing it.
78 start_func: funcPC(thr_start),
79 arg: unsafe.Pointer(mp),
80 stack_base: mp.g0.stack.hi,
81 stack_size: uintptr(stk) - mp.g0.stack.hi,
82 child_tid: unsafe.Pointer(&mp.procid),
84 tls_base: unsafe.Pointer(&mp.tls[0]),
85 tls_size: unsafe.Sizeof(mp.tls),
87 mp.tls[0] = uintptr(mp.id) // so 386 asm can find it
90 sigprocmask(&sigset_all, &oset)
91 thr_new(¶m, int32(unsafe.Sizeof(param)))
92 sigprocmask(&oset, nil)
99 var urandom_data [_HashRandomBytes]byte
100 var urandom_dev = []byte("/dev/random\x00")
103 func get_random_data(rnd *unsafe.Pointer, rnd_len *int32) {
104 fd := open(&urandom_dev[0], 0 /* O_RDONLY */, 0)
105 if read(fd, unsafe.Pointer(&urandom_data), _HashRandomBytes) == _HashRandomBytes {
106 *rnd = unsafe.Pointer(&urandom_data[0])
107 *rnd_len = _HashRandomBytes
119 // Called to initialize a new m (including the bootstrap m).
120 // Called on the parent thread (main thread in case of bootstrap), can allocate memory.
121 func mpreinit(mp *m) {
122 mp.gsignal = malg(32 * 1024)
126 // Called to initialize a new m (including the bootstrap m).
127 // Called on the new thread, can not allocate memory.
131 // m.procid is a uint64, but thr_new writes a uint32 on 32-bit systems.
132 // Fix it up. (Only matters on big-endian, but be clean anyway.)
134 _g_.m.procid = uint64(*(*uint32)(unsafe.Pointer(&_g_.m.procid)))
137 // Initialize signal handling.
138 signalstack((*byte)(unsafe.Pointer(_g_.m.gsignal.stack.lo)), 32*1024)
139 sigprocmask(&sigset_none, nil)
142 // Called from dropm to undo the effect of an minit.
147 func memlimit() uintptr {
149 TODO: Convert to Go when something actually uses the result.
151 extern byte runtime·text[], runtime·end[];
154 if(runtime·getrlimit(RLIMIT_AS, &rl) != 0)
156 if(rl.rlim_cur >= 0x7fffffff)
159 // Estimate our VM footprint excluding the heap.
160 // Not an exact science: use size of binary plus
161 // some room for thread stacks.
162 used = runtime·end - runtime·text + (64<<20);
163 if(used >= rl.rlim_cur)
166 // If there's not at least 16 MB left, we're probably
167 // not going to be able to do much. Treat as no limit.
169 if(rl.rlim_cur < (16<<20))
172 return rl.rlim_cur - used;
180 type sigactiont struct {
186 func setsig(i int32, fn uintptr, restart bool) {
188 sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK
190 sa.sa_flags |= _SA_RESTART
192 sa.sa_mask = sigset_all
193 if fn == funcPC(sighandler) {
194 fn = funcPC(sigtramp)
197 sigaction(i, &sa, nil)
199 func getsig(i int32) uintptr {
201 sigaction(i, nil, &sa)
202 if sa.sa_handler == funcPC(sigtramp) {
203 return funcPC(sighandler)
208 func signalstack(p *byte, n int32) {
210 st.ss_sp = uintptr(unsafe.Pointer(p))
211 st.ss_size = uintptr(n)
214 st.ss_flags = _SS_DISABLE
216 sigaltstack(&st, nil)
219 func unblocksignals() {
220 sigprocmask(&sigset_none, nil)