Home | History | Annotate | Download | only in runtime
      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.
      4 
      5 package runtime
      6 
      7 import "unsafe"
      8 
      9 var sigset_all sigset = sigset{^uint32(0), ^uint32(0)}
     10 
     11 // Linux futex.
     12 //
     13 //	futexsleep(uint32 *addr, uint32 val)
     14 //	futexwakeup(uint32 *addr)
     15 //
     16 // Futexsleep atomically checks if *addr == val and if so, sleeps on addr.
     17 // Futexwakeup wakes up threads sleeping on addr.
     18 // Futexsleep is allowed to wake up spuriously.
     19 
     20 const (
     21 	_FUTEX_WAIT = 0
     22 	_FUTEX_WAKE = 1
     23 )
     24 
     25 // Atomically,
     26 //	if(*addr == val) sleep
     27 // Might be woken up spuriously; that's allowed.
     28 // Don't sleep longer than ns; ns < 0 means forever.
     29 //go:nosplit
     30 func futexsleep(addr *uint32, val uint32, ns int64) {
     31 	var ts timespec
     32 
     33 	// Some Linux kernels have a bug where futex of
     34 	// FUTEX_WAIT returns an internal error code
     35 	// as an errno.  Libpthread ignores the return value
     36 	// here, and so can we: as it says a few lines up,
     37 	// spurious wakeups are allowed.
     38 	if ns < 0 {
     39 		futex(unsafe.Pointer(addr), _FUTEX_WAIT, val, nil, nil, 0)
     40 		return
     41 	}
     42 
     43 	// It's difficult to live within the no-split stack limits here.
     44 	// On ARM and 386, a 64-bit divide invokes a general software routine
     45 	// that needs more stack than we can afford. So we use timediv instead.
     46 	// But on real 64-bit systems, where words are larger but the stack limit
     47 	// is not, even timediv is too heavy, and we really need to use just an
     48 	// ordinary machine instruction.
     49 	if ptrSize == 8 {
     50 		ts.set_sec(ns / 1000000000)
     51 		ts.set_nsec(int32(ns % 1000000000))
     52 	} else {
     53 		ts.tv_nsec = 0
     54 		ts.set_sec(int64(timediv(ns, 1000000000, (*int32)(unsafe.Pointer(&ts.tv_nsec)))))
     55 	}
     56 	futex(unsafe.Pointer(addr), _FUTEX_WAIT, val, unsafe.Pointer(&ts), nil, 0)
     57 }
     58 
     59 // If any procs are sleeping on addr, wake up at most cnt.
     60 //go:nosplit
     61 func futexwakeup(addr *uint32, cnt uint32) {
     62 	ret := futex(unsafe.Pointer(addr), _FUTEX_WAKE, cnt, nil, nil, 0)
     63 	if ret >= 0 {
     64 		return
     65 	}
     66 
     67 	// I don't know that futex wakeup can return
     68 	// EAGAIN or EINTR, but if it does, it would be
     69 	// safe to loop and call futex again.
     70 	systemstack(func() {
     71 		print("futexwakeup addr=", addr, " returned ", ret, "\n")
     72 	})
     73 
     74 	*(*int32)(unsafe.Pointer(uintptr(0x1006))) = 0x1006
     75 }
     76 
     77 func getproccount() int32 {
     78 	// This buffer is huge (8 kB) but we are on the system stack
     79 	// and there should be plenty of space (64 kB) -- except on ARM where
     80 	// the system stack itself is only 8kb (see golang.org/issue/11873).
     81 	// Also this is a leaf, so we're not holding up the memory for long.
     82 	// See golang.org/issue/11823.
     83 	// The suggested behavior here is to keep trying with ever-larger
     84 	// buffers, but we don't have a dynamic memory allocator at the
     85 	// moment, so that's a bit tricky and seems like overkill.
     86 	const maxCPUs = 64*1024*(1-goarch_arm) + 1024*goarch_arm
     87 	var buf [maxCPUs / (ptrSize * 8)]uintptr
     88 	r := sched_getaffinity(0, unsafe.Sizeof(buf), &buf[0])
     89 	n := int32(0)
     90 	for _, v := range buf[:r/ptrSize] {
     91 		for v != 0 {
     92 			n += int32(v & 1)
     93 			v >>= 1
     94 		}
     95 	}
     96 	if n == 0 {
     97 		n = 1
     98 	}
     99 	return n
    100 }
    101 
    102 // Clone, the Linux rfork.
    103 const (
    104 	_CLONE_VM             = 0x100
    105 	_CLONE_FS             = 0x200
    106 	_CLONE_FILES          = 0x400
    107 	_CLONE_SIGHAND        = 0x800
    108 	_CLONE_PTRACE         = 0x2000
    109 	_CLONE_VFORK          = 0x4000
    110 	_CLONE_PARENT         = 0x8000
    111 	_CLONE_THREAD         = 0x10000
    112 	_CLONE_NEWNS          = 0x20000
    113 	_CLONE_SYSVSEM        = 0x40000
    114 	_CLONE_SETTLS         = 0x80000
    115 	_CLONE_PARENT_SETTID  = 0x100000
    116 	_CLONE_CHILD_CLEARTID = 0x200000
    117 	_CLONE_UNTRACED       = 0x800000
    118 	_CLONE_CHILD_SETTID   = 0x1000000
    119 	_CLONE_STOPPED        = 0x2000000
    120 	_CLONE_NEWUTS         = 0x4000000
    121 	_CLONE_NEWIPC         = 0x8000000
    122 
    123 	cloneFlags = _CLONE_VM | /* share memory */
    124 		_CLONE_FS | /* share cwd, etc */
    125 		_CLONE_FILES | /* share fd table */
    126 		_CLONE_SIGHAND | /* share sig handler table */
    127 		_CLONE_THREAD /* revisit - okay for now */
    128 )
    129 
    130 // May run with m.p==nil, so write barriers are not allowed.
    131 //go:nowritebarrier
    132 func newosproc(mp *m, stk unsafe.Pointer) {
    133 	/*
    134 	 * note: strace gets confused if we use CLONE_PTRACE here.
    135 	 */
    136 	mp.tls[0] = uintptr(mp.id) // so 386 asm can find it
    137 	if false {
    138 		print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " clone=", funcPC(clone), " id=", mp.id, "/", mp.tls[0], " ostk=", &mp, "\n")
    139 	}
    140 
    141 	// Disable signals during clone, so that the new thread starts
    142 	// with signals disabled.  It will enable them in minit.
    143 	var oset sigset
    144 	rtsigprocmask(_SIG_SETMASK, &sigset_all, &oset, int32(unsafe.Sizeof(oset)))
    145 	ret := clone(cloneFlags, stk, unsafe.Pointer(mp), unsafe.Pointer(mp.g0), unsafe.Pointer(funcPC(mstart)))
    146 	rtsigprocmask(_SIG_SETMASK, &oset, nil, int32(unsafe.Sizeof(oset)))
    147 
    148 	if ret < 0 {
    149 		print("runtime: failed to create new OS thread (have ", mcount(), " already; errno=", -ret, ")\n")
    150 		throw("newosproc")
    151 	}
    152 }
    153 
    154 // Version of newosproc that doesn't require a valid G.
    155 //go:nosplit
    156 func newosproc0(stacksize uintptr, fn unsafe.Pointer) {
    157 	stack := sysAlloc(stacksize, &memstats.stacks_sys)
    158 	if stack == nil {
    159 		write(2, unsafe.Pointer(&failallocatestack[0]), int32(len(failallocatestack)))
    160 		exit(1)
    161 	}
    162 	ret := clone(cloneFlags, unsafe.Pointer(uintptr(stack)+stacksize), nil, nil, fn)
    163 	if ret < 0 {
    164 		write(2, unsafe.Pointer(&failthreadcreate[0]), int32(len(failthreadcreate)))
    165 		exit(1)
    166 	}
    167 }
    168 
    169 var failallocatestack = []byte("runtime: failed to allocate stack for the new OS thread\n")
    170 var failthreadcreate = []byte("runtime: failed to create new OS thread\n")
    171 
    172 func osinit() {
    173 	ncpu = getproccount()
    174 }
    175 
    176 var urandom_dev = []byte("/dev/urandom\x00")
    177 
    178 func getRandomData(r []byte) {
    179 	if startupRandomData != nil {
    180 		n := copy(r, startupRandomData)
    181 		extendRandom(r, n)
    182 		return
    183 	}
    184 	fd := open(&urandom_dev[0], 0 /* O_RDONLY */, 0)
    185 	n := read(fd, unsafe.Pointer(&r[0]), int32(len(r)))
    186 	closefd(fd)
    187 	extendRandom(r, int(n))
    188 }
    189 
    190 func goenvs() {
    191 	goenvs_unix()
    192 }
    193 
    194 // Called to initialize a new m (including the bootstrap m).
    195 // Called on the parent thread (main thread in case of bootstrap), can allocate memory.
    196 func mpreinit(mp *m) {
    197 	mp.gsignal = malg(32 * 1024) // Linux wants >= 2K
    198 	mp.gsignal.m = mp
    199 }
    200 
    201 func msigsave(mp *m) {
    202 	smask := (*sigset)(unsafe.Pointer(&mp.sigmask))
    203 	if unsafe.Sizeof(*smask) > unsafe.Sizeof(mp.sigmask) {
    204 		throw("insufficient storage for signal mask")
    205 	}
    206 	rtsigprocmask(_SIG_SETMASK, nil, smask, int32(unsafe.Sizeof(*smask)))
    207 }
    208 
    209 func gettid() uint32
    210 
    211 // Called to initialize a new m (including the bootstrap m).
    212 // Called on the new thread, can not allocate memory.
    213 func minit() {
    214 	// Initialize signal handling.
    215 	_g_ := getg()
    216 	signalstack(&_g_.m.gsignal.stack)
    217 
    218 	// for debuggers, in case cgo created the thread
    219 	_g_.m.procid = uint64(gettid())
    220 
    221 	// restore signal mask from m.sigmask and unblock essential signals
    222 	nmask := *(*sigset)(unsafe.Pointer(&_g_.m.sigmask))
    223 	for i := range sigtable {
    224 		if sigtable[i].flags&_SigUnblock != 0 {
    225 			nmask[(i-1)/32] &^= 1 << ((uint32(i) - 1) & 31)
    226 		}
    227 	}
    228 	rtsigprocmask(_SIG_SETMASK, &nmask, nil, int32(unsafe.Sizeof(nmask)))
    229 }
    230 
    231 // Called from dropm to undo the effect of an minit.
    232 func unminit() {
    233 	_g_ := getg()
    234 	smask := (*sigset)(unsafe.Pointer(&_g_.m.sigmask))
    235 	rtsigprocmask(_SIG_SETMASK, smask, nil, int32(unsafe.Sizeof(*smask)))
    236 	signalstack(nil)
    237 }
    238 
    239 func memlimit() uintptr {
    240 	/*
    241 		TODO: Convert to Go when something actually uses the result.
    242 
    243 		Rlimit rl;
    244 		extern byte runtimetext[], runtimeend[];
    245 		uintptr used;
    246 
    247 		if(runtimegetrlimit(RLIMIT_AS, &rl) != 0)
    248 			return 0;
    249 		if(rl.rlim_cur >= 0x7fffffff)
    250 			return 0;
    251 
    252 		// Estimate our VM footprint excluding the heap.
    253 		// Not an exact science: use size of binary plus
    254 		// some room for thread stacks.
    255 		used = runtimeend - runtimetext + (64<<20);
    256 		if(used >= rl.rlim_cur)
    257 			return 0;
    258 
    259 		// If there's not at least 16 MB left, we're probably
    260 		// not going to be able to do much.  Treat as no limit.
    261 		rl.rlim_cur -= used;
    262 		if(rl.rlim_cur < (16<<20))
    263 			return 0;
    264 
    265 		return rl.rlim_cur - used;
    266 	*/
    267 
    268 	return 0
    269 }
    270 
    271 //#ifdef GOARCH_386
    272 //#define sa_handler k_sa_handler
    273 //#endif
    274 
    275 func sigreturn()
    276 func sigtramp()
    277 
    278 func setsig(i int32, fn uintptr, restart bool) {
    279 	var sa sigactiont
    280 	memclr(unsafe.Pointer(&sa), unsafe.Sizeof(sa))
    281 	sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK | _SA_RESTORER
    282 	if restart {
    283 		sa.sa_flags |= _SA_RESTART
    284 	}
    285 	sa.sa_mask = ^uint64(0)
    286 	// Although Linux manpage says "sa_restorer element is obsolete and
    287 	// should not be used". x86_64 kernel requires it. Only use it on
    288 	// x86.
    289 	if GOARCH == "386" || GOARCH == "amd64" {
    290 		sa.sa_restorer = funcPC(sigreturn)
    291 	}
    292 	if fn == funcPC(sighandler) {
    293 		fn = funcPC(sigtramp)
    294 	}
    295 	sa.sa_handler = fn
    296 	if rt_sigaction(uintptr(i), &sa, nil, unsafe.Sizeof(sa.sa_mask)) != 0 {
    297 		throw("rt_sigaction failure")
    298 	}
    299 }
    300 
    301 func setsigstack(i int32) {
    302 	var sa sigactiont
    303 	if rt_sigaction(uintptr(i), nil, &sa, unsafe.Sizeof(sa.sa_mask)) != 0 {
    304 		throw("rt_sigaction failure")
    305 	}
    306 	if sa.sa_handler == 0 || sa.sa_handler == _SIG_DFL || sa.sa_handler == _SIG_IGN || sa.sa_flags&_SA_ONSTACK != 0 {
    307 		return
    308 	}
    309 	sa.sa_flags |= _SA_ONSTACK
    310 	if rt_sigaction(uintptr(i), &sa, nil, unsafe.Sizeof(sa.sa_mask)) != 0 {
    311 		throw("rt_sigaction failure")
    312 	}
    313 }
    314 
    315 func getsig(i int32) uintptr {
    316 	var sa sigactiont
    317 
    318 	memclr(unsafe.Pointer(&sa), unsafe.Sizeof(sa))
    319 	if rt_sigaction(uintptr(i), nil, &sa, unsafe.Sizeof(sa.sa_mask)) != 0 {
    320 		throw("rt_sigaction read failure")
    321 	}
    322 	if sa.sa_handler == funcPC(sigtramp) {
    323 		return funcPC(sighandler)
    324 	}
    325 	return sa.sa_handler
    326 }
    327 
    328 func signalstack(s *stack) {
    329 	var st sigaltstackt
    330 	if s == nil {
    331 		st.ss_flags = _SS_DISABLE
    332 	} else {
    333 		st.ss_sp = (*byte)(unsafe.Pointer(s.lo))
    334 		st.ss_size = s.hi - s.lo
    335 		st.ss_flags = 0
    336 	}
    337 	sigaltstack(&st, nil)
    338 }
    339 
    340 func updatesigmask(m sigmask) {
    341 	var mask sigset
    342 	copy(mask[:], m[:])
    343 	rtsigprocmask(_SIG_SETMASK, &mask, nil, int32(unsafe.Sizeof(mask)))
    344 }
    345 
    346 func unblocksig(sig int32) {
    347 	var mask sigset
    348 	mask[(sig-1)/32] |= 1 << ((uint32(sig) - 1) & 31)
    349 	rtsigprocmask(_SIG_UNBLOCK, &mask, nil, int32(unsafe.Sizeof(mask)))
    350 }
    351