1 // Copyright 2009 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.
10 var sigset_all sigset = sigset{^uint32(0), ^uint32(0)}
14 // futexsleep(uint32 *addr, uint32 val)
15 // futexwakeup(uint32 *addr)
17 // Futexsleep atomically checks if *addr == val and if so, sleeps on addr.
18 // Futexwakeup wakes up threads sleeping on addr.
19 // Futexsleep is allowed to wake up spuriously.
27 // if(*addr == val) sleep
28 // Might be woken up spuriously; that's allowed.
29 // Don't sleep longer than ns; ns < 0 means forever.
31 func futexsleep(addr *uint32, val uint32, ns int64) {
34 // Some Linux kernels have a bug where futex of
35 // FUTEX_WAIT returns an internal error code
36 // as an errno. Libpthread ignores the return value
37 // here, and so can we: as it says a few lines up,
38 // spurious wakeups are allowed.
40 futex(unsafe.Pointer(addr), _FUTEX_WAIT, val, nil, nil, 0)
44 // It's difficult to live within the no-split stack limits here.
45 // On ARM and 386, a 64-bit divide invokes a general software routine
46 // that needs more stack than we can afford. So we use timediv instead.
47 // But on real 64-bit systems, where words are larger but the stack limit
48 // is not, even timediv is too heavy, and we really need to use just an
49 // ordinary machine instruction.
51 ts.set_sec(ns / 1000000000)
52 ts.set_nsec(int32(ns % 1000000000))
55 ts.set_sec(int64(timediv(ns, 1000000000, (*int32)(unsafe.Pointer(&ts.tv_nsec)))))
57 futex(unsafe.Pointer(addr), _FUTEX_WAIT, val, unsafe.Pointer(&ts), nil, 0)
60 // If any procs are sleeping on addr, wake up at most cnt.
62 func futexwakeup(addr *uint32, cnt uint32) {
63 ret := futex(unsafe.Pointer(addr), _FUTEX_WAKE, cnt, nil, nil, 0)
68 // I don't know that futex wakeup can return
69 // EAGAIN or EINTR, but if it does, it would be
70 // safe to loop and call futex again.
72 print("futexwakeup addr=", addr, " returned ", ret, "\n")
75 *(*int32)(unsafe.Pointer(uintptr(0x1006))) = 0x1006
78 func getproccount() int32 {
80 r := sched_getaffinity(0, unsafe.Sizeof(buf), &buf[0])
82 for _, v := range buf[:r/ptrSize] {
83 for i := 0; i < 64; i++ {
94 // Clone, the Linux rfork.
99 _CLONE_SIGHAND = 0x800
100 _CLONE_PTRACE = 0x2000
101 _CLONE_VFORK = 0x4000
102 _CLONE_PARENT = 0x8000
103 _CLONE_THREAD = 0x10000
104 _CLONE_NEWNS = 0x20000
105 _CLONE_SYSVSEM = 0x40000
106 _CLONE_SETTLS = 0x80000
107 _CLONE_PARENT_SETTID = 0x100000
108 _CLONE_CHILD_CLEARTID = 0x200000
109 _CLONE_UNTRACED = 0x800000
110 _CLONE_CHILD_SETTID = 0x1000000
111 _CLONE_STOPPED = 0x2000000
112 _CLONE_NEWUTS = 0x4000000
113 _CLONE_NEWIPC = 0x8000000
116 func newosproc(mp *m, stk unsafe.Pointer) {
118 * note: strace gets confused if we use CLONE_PTRACE here.
120 var flags int32 = _CLONE_VM | /* share memory */
121 _CLONE_FS | /* share cwd, etc */
122 _CLONE_FILES | /* share fd table */
123 _CLONE_SIGHAND | /* share sig handler table */
124 _CLONE_THREAD /* revisit - okay for now */
126 mp.tls[0] = uintptr(mp.id) // so 386 asm can find it
128 print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " clone=", funcPC(clone), " id=", mp.id, "/", mp.tls[0], " ostk=", &mp, "\n")
131 // Disable signals during clone, so that the new thread starts
132 // with signals disabled. It will enable them in minit.
134 rtsigprocmask(_SIG_SETMASK, &sigset_all, &oset, int32(unsafe.Sizeof(oset)))
135 ret := clone(flags, stk, unsafe.Pointer(mp), unsafe.Pointer(mp.g0), unsafe.Pointer(funcPC(mstart)))
136 rtsigprocmask(_SIG_SETMASK, &oset, nil, int32(unsafe.Sizeof(oset)))
139 print("runtime: failed to create new OS thread (have ", mcount(), " already; errno=", -ret, ")\n")
145 ncpu = getproccount()
148 // Random bytes initialized at startup. These come
149 // from the ELF AT_RANDOM auxiliary vector (vdso_linux_amd64.c).
150 // byte* runtime·startup_random_data;
151 // uint32 runtime·startup_random_data_len;
153 var urandom_data [_HashRandomBytes]byte
154 var urandom_dev = []byte("/dev/random\x00")
157 func get_random_data(rnd *unsafe.Pointer, rnd_len *int32) {
158 if startup_random_data != nil {
159 *rnd = unsafe.Pointer(startup_random_data)
160 *rnd_len = int32(startup_random_data_len)
163 fd := open(&urandom_dev[0], 0 /* O_RDONLY */, 0)
164 if read(fd, unsafe.Pointer(&urandom_data), _HashRandomBytes) == _HashRandomBytes {
165 *rnd = unsafe.Pointer(&urandom_data[0])
166 *rnd_len = _HashRandomBytes
178 // Called to initialize a new m (including the bootstrap m).
179 // Called on the parent thread (main thread in case of bootstrap), can allocate memory.
180 func mpreinit(mp *m) {
181 mp.gsignal = malg(32 * 1024) // Linux wants >= 2K
185 // Called to initialize a new m (including the bootstrap m).
186 // Called on the new thread, can not allocate memory.
188 // Initialize signal handling.
190 signalstack((*byte)(unsafe.Pointer(_g_.m.gsignal.stack.lo)), 32*1024)
191 rtsigprocmask(_SIG_SETMASK, &sigset_none, nil, int32(unsafe.Sizeof(sigset_none)))
194 // Called from dropm to undo the effect of an minit.
199 func memlimit() uintptr {
201 TODO: Convert to Go when something actually uses the result.
204 extern byte runtime·text[], runtime·end[];
207 if(runtime·getrlimit(RLIMIT_AS, &rl) != 0)
209 if(rl.rlim_cur >= 0x7fffffff)
212 // Estimate our VM footprint excluding the heap.
213 // Not an exact science: use size of binary plus
214 // some room for thread stacks.
215 used = runtime·end - runtime·text + (64<<20);
216 if(used >= rl.rlim_cur)
219 // If there's not at least 16 MB left, we're probably
220 // not going to be able to do much. Treat as no limit.
222 if(rl.rlim_cur < (16<<20))
225 return rl.rlim_cur - used;
232 //#define sa_handler k_sa_handler
238 func setsig(i int32, fn uintptr, restart bool) {
240 memclr(unsafe.Pointer(&sa), unsafe.Sizeof(sa))
241 sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK | _SA_RESTORER
243 sa.sa_flags |= _SA_RESTART
245 sa.sa_mask = ^uint64(0)
246 // Although Linux manpage says "sa_restorer element is obsolete and
247 // should not be used". x86_64 kernel requires it. Only use it on
249 if GOARCH == "386" || GOARCH == "amd64" {
250 sa.sa_restorer = funcPC(sigreturn)
252 if fn == funcPC(sighandler) {
253 fn = funcPC(sigtramp)
256 if rt_sigaction(uintptr(i), &sa, nil, unsafe.Sizeof(sa.sa_mask)) != 0 {
257 gothrow("rt_sigaction failure")
261 func getsig(i int32) uintptr {
264 memclr(unsafe.Pointer(&sa), unsafe.Sizeof(sa))
265 if rt_sigaction(uintptr(i), nil, &sa, unsafe.Sizeof(sa.sa_mask)) != 0 {
266 gothrow("rt_sigaction read failure")
268 if sa.sa_handler == funcPC(sigtramp) {
269 return funcPC(sighandler)
274 func signalstack(p *byte, n int32) {
277 st.ss_size = uintptr(n)
280 st.ss_flags = _SS_DISABLE
282 sigaltstack(&st, nil)
285 func unblocksignals() {
286 rtsigprocmask(_SIG_SETMASK, &sigset_none, nil, int32(unsafe.Sizeof(sigset_none)))