...
Run Format

Source file src/runtime/os_linux.go

     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 (
     8		"runtime/internal/sys"
     9		"unsafe"
    10	)
    11	
    12	type mOS struct{}
    13	
    14	//go:noescape
    15	func futex(addr unsafe.Pointer, op int32, val uint32, ts, addr2 unsafe.Pointer, val3 uint32) int32
    16	
    17	// Linux futex.
    18	//
    19	//	futexsleep(uint32 *addr, uint32 val)
    20	//	futexwakeup(uint32 *addr)
    21	//
    22	// Futexsleep atomically checks if *addr == val and if so, sleeps on addr.
    23	// Futexwakeup wakes up threads sleeping on addr.
    24	// Futexsleep is allowed to wake up spuriously.
    25	
    26	const (
    27		_FUTEX_WAIT = 0
    28		_FUTEX_WAKE = 1
    29	)
    30	
    31	// Atomically,
    32	//	if(*addr == val) sleep
    33	// Might be woken up spuriously; that's allowed.
    34	// Don't sleep longer than ns; ns < 0 means forever.
    35	//go:nosplit
    36	func futexsleep(addr *uint32, val uint32, ns int64) {
    37		var ts timespec
    38	
    39		// Some Linux kernels have a bug where futex of
    40		// FUTEX_WAIT returns an internal error code
    41		// as an errno. Libpthread ignores the return value
    42		// here, and so can we: as it says a few lines up,
    43		// spurious wakeups are allowed.
    44		if ns < 0 {
    45			futex(unsafe.Pointer(addr), _FUTEX_WAIT, val, nil, nil, 0)
    46			return
    47		}
    48	
    49		// It's difficult to live within the no-split stack limits here.
    50		// On ARM and 386, a 64-bit divide invokes a general software routine
    51		// that needs more stack than we can afford. So we use timediv instead.
    52		// But on real 64-bit systems, where words are larger but the stack limit
    53		// is not, even timediv is too heavy, and we really need to use just an
    54		// ordinary machine instruction.
    55		if sys.PtrSize == 8 {
    56			ts.set_sec(ns / 1000000000)
    57			ts.set_nsec(int32(ns % 1000000000))
    58		} else {
    59			ts.tv_nsec = 0
    60			ts.set_sec(int64(timediv(ns, 1000000000, (*int32)(unsafe.Pointer(&ts.tv_nsec)))))
    61		}
    62		futex(unsafe.Pointer(addr), _FUTEX_WAIT, val, unsafe.Pointer(&ts), nil, 0)
    63	}
    64	
    65	// If any procs are sleeping on addr, wake up at most cnt.
    66	//go:nosplit
    67	func futexwakeup(addr *uint32, cnt uint32) {
    68		ret := futex(unsafe.Pointer(addr), _FUTEX_WAKE, cnt, nil, nil, 0)
    69		if ret >= 0 {
    70			return
    71		}
    72	
    73		// I don't know that futex wakeup can return
    74		// EAGAIN or EINTR, but if it does, it would be
    75		// safe to loop and call futex again.
    76		systemstack(func() {
    77			print("futexwakeup addr=", addr, " returned ", ret, "\n")
    78		})
    79	
    80		*(*int32)(unsafe.Pointer(uintptr(0x1006))) = 0x1006
    81	}
    82	
    83	func getproccount() int32 {
    84		// This buffer is huge (8 kB) but we are on the system stack
    85		// and there should be plenty of space (64 kB).
    86		// Also this is a leaf, so we're not holding up the memory for long.
    87		// See golang.org/issue/11823.
    88		// The suggested behavior here is to keep trying with ever-larger
    89		// buffers, but we don't have a dynamic memory allocator at the
    90		// moment, so that's a bit tricky and seems like overkill.
    91		const maxCPUs = 64 * 1024
    92		var buf [maxCPUs / (sys.PtrSize * 8)]uintptr
    93		r := sched_getaffinity(0, unsafe.Sizeof(buf), &buf[0])
    94		if r < 0 {
    95			return 1
    96		}
    97		n := int32(0)
    98		for _, v := range buf[:r/sys.PtrSize] {
    99			for v != 0 {
   100				n += int32(v & 1)
   101				v >>= 1
   102			}
   103		}
   104		if n == 0 {
   105			n = 1
   106		}
   107		return n
   108	}
   109	
   110	// Clone, the Linux rfork.
   111	const (
   112		_CLONE_VM             = 0x100
   113		_CLONE_FS             = 0x200
   114		_CLONE_FILES          = 0x400
   115		_CLONE_SIGHAND        = 0x800
   116		_CLONE_PTRACE         = 0x2000
   117		_CLONE_VFORK          = 0x4000
   118		_CLONE_PARENT         = 0x8000
   119		_CLONE_THREAD         = 0x10000
   120		_CLONE_NEWNS          = 0x20000
   121		_CLONE_SYSVSEM        = 0x40000
   122		_CLONE_SETTLS         = 0x80000
   123		_CLONE_PARENT_SETTID  = 0x100000
   124		_CLONE_CHILD_CLEARTID = 0x200000
   125		_CLONE_UNTRACED       = 0x800000
   126		_CLONE_CHILD_SETTID   = 0x1000000
   127		_CLONE_STOPPED        = 0x2000000
   128		_CLONE_NEWUTS         = 0x4000000
   129		_CLONE_NEWIPC         = 0x8000000
   130	
   131		cloneFlags = _CLONE_VM | /* share memory */
   132			_CLONE_FS | /* share cwd, etc */
   133			_CLONE_FILES | /* share fd table */
   134			_CLONE_SIGHAND | /* share sig handler table */
   135			_CLONE_THREAD /* revisit - okay for now */
   136	)
   137	
   138	//go:noescape
   139	func clone(flags int32, stk, mp, gp, fn unsafe.Pointer) int32
   140	
   141	// May run with m.p==nil, so write barriers are not allowed.
   142	//go:nowritebarrier
   143	func newosproc(mp *m, stk unsafe.Pointer) {
   144		/*
   145		 * note: strace gets confused if we use CLONE_PTRACE here.
   146		 */
   147		if false {
   148			print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " clone=", funcPC(clone), " id=", mp.id, " ostk=", &mp, "\n")
   149		}
   150	
   151		// Disable signals during clone, so that the new thread starts
   152		// with signals disabled. It will enable them in minit.
   153		var oset sigset
   154		sigprocmask(_SIG_SETMASK, &sigset_all, &oset)
   155		ret := clone(cloneFlags, stk, unsafe.Pointer(mp), unsafe.Pointer(mp.g0), unsafe.Pointer(funcPC(mstart)))
   156		sigprocmask(_SIG_SETMASK, &oset, nil)
   157	
   158		if ret < 0 {
   159			print("runtime: failed to create new OS thread (have ", mcount(), " already; errno=", -ret, ")\n")
   160			if ret == -_EAGAIN {
   161				println("runtime: may need to increase max user processes (ulimit -u)")
   162			}
   163			throw("newosproc")
   164		}
   165	}
   166	
   167	// Version of newosproc that doesn't require a valid G.
   168	//go:nosplit
   169	func newosproc0(stacksize uintptr, fn unsafe.Pointer) {
   170		stack := sysAlloc(stacksize, &memstats.stacks_sys)
   171		if stack == nil {
   172			write(2, unsafe.Pointer(&failallocatestack[0]), int32(len(failallocatestack)))
   173			exit(1)
   174		}
   175		ret := clone(cloneFlags, unsafe.Pointer(uintptr(stack)+stacksize), nil, nil, fn)
   176		if ret < 0 {
   177			write(2, unsafe.Pointer(&failthreadcreate[0]), int32(len(failthreadcreate)))
   178			exit(1)
   179		}
   180	}
   181	
   182	var failallocatestack = []byte("runtime: failed to allocate stack for the new OS thread\n")
   183	var failthreadcreate = []byte("runtime: failed to create new OS thread\n")
   184	
   185	const (
   186		_AT_NULL   = 0  // End of vector
   187		_AT_PAGESZ = 6  // System physical page size
   188		_AT_HWCAP  = 16 // hardware capability bit vector
   189		_AT_RANDOM = 25 // introduced in 2.6.29
   190		_AT_HWCAP2 = 26 // hardware capability bit vector 2
   191	)
   192	
   193	var procAuxv = []byte("/proc/self/auxv\x00")
   194	
   195	func sysargs(argc int32, argv **byte) {
   196		n := argc + 1
   197	
   198		// skip over argv, envp to get to auxv
   199		for argv_index(argv, n) != nil {
   200			n++
   201		}
   202	
   203		// skip NULL separator
   204		n++
   205	
   206		// now argv+n is auxv
   207		auxv := (*[1 << 28]uintptr)(add(unsafe.Pointer(argv), uintptr(n)*sys.PtrSize))
   208		if sysauxv(auxv[:]) == 0 {
   209			// In some situations we don't get a loader-provided
   210			// auxv, such as when loaded as a library on Android.
   211			// Fall back to /proc/self/auxv.
   212			fd := open(&procAuxv[0], 0 /* O_RDONLY */, 0)
   213			if fd < 0 {
   214				// On Android, /proc/self/auxv might be unreadable (issue 9229), so we fallback to
   215				// try using mincore to detect the physical page size.
   216				// mincore should return EINVAL when address is not a multiple of system page size.
   217				const size = 256 << 10 // size of memory region to allocate
   218				p := mmap(nil, size, _PROT_READ|_PROT_WRITE, _MAP_ANON|_MAP_PRIVATE, -1, 0)
   219				if uintptr(p) < 4096 {
   220					return
   221				}
   222				var n uintptr
   223				for n = 4 << 10; n < size; n <<= 1 {
   224					err := mincore(unsafe.Pointer(uintptr(p)+n), 1, &addrspace_vec[0])
   225					if err == 0 {
   226						physPageSize = n
   227						break
   228					}
   229				}
   230				if physPageSize == 0 {
   231					physPageSize = size
   232				}
   233				munmap(p, size)
   234				return
   235			}
   236			var buf [128]uintptr
   237			n := read(fd, noescape(unsafe.Pointer(&buf[0])), int32(unsafe.Sizeof(buf)))
   238			closefd(fd)
   239			if n < 0 {
   240				return
   241			}
   242			// Make sure buf is terminated, even if we didn't read
   243			// the whole file.
   244			buf[len(buf)-2] = _AT_NULL
   245			sysauxv(buf[:])
   246		}
   247	}
   248	
   249	func sysauxv(auxv []uintptr) int {
   250		var i int
   251		for ; auxv[i] != _AT_NULL; i += 2 {
   252			tag, val := auxv[i], auxv[i+1]
   253			switch tag {
   254			case _AT_RANDOM:
   255				// The kernel provides a pointer to 16-bytes
   256				// worth of random data.
   257				startupRandomData = (*[16]byte)(unsafe.Pointer(val))[:]
   258	
   259			case _AT_PAGESZ:
   260				physPageSize = val
   261			}
   262	
   263			archauxv(tag, val)
   264		}
   265		return i / 2
   266	}
   267	
   268	func osinit() {
   269		ncpu = getproccount()
   270	}
   271	
   272	var urandom_dev = []byte("/dev/urandom\x00")
   273	
   274	func getRandomData(r []byte) {
   275		if startupRandomData != nil {
   276			n := copy(r, startupRandomData)
   277			extendRandom(r, n)
   278			return
   279		}
   280		fd := open(&urandom_dev[0], 0 /* O_RDONLY */, 0)
   281		n := read(fd, unsafe.Pointer(&r[0]), int32(len(r)))
   282		closefd(fd)
   283		extendRandom(r, int(n))
   284	}
   285	
   286	func goenvs() {
   287		goenvs_unix()
   288	}
   289	
   290	// Called to do synchronous initialization of Go code built with
   291	// -buildmode=c-archive or -buildmode=c-shared.
   292	// None of the Go runtime is initialized.
   293	//go:nosplit
   294	//go:nowritebarrierrec
   295	func libpreinit() {
   296		initsig(true)
   297	}
   298	
   299	// Called to initialize a new m (including the bootstrap m).
   300	// Called on the parent thread (main thread in case of bootstrap), can allocate memory.
   301	func mpreinit(mp *m) {
   302		mp.gsignal = malg(32 * 1024) // Linux wants >= 2K
   303		mp.gsignal.m = mp
   304	}
   305	
   306	func gettid() uint32
   307	
   308	// Called to initialize a new m (including the bootstrap m).
   309	// Called on the new thread, cannot allocate memory.
   310	func minit() {
   311		minitSignals()
   312	
   313		// for debuggers, in case cgo created the thread
   314		getg().m.procid = uint64(gettid())
   315	}
   316	
   317	// Called from dropm to undo the effect of an minit.
   318	//go:nosplit
   319	func unminit() {
   320		unminitSignals()
   321	}
   322	
   323	func memlimit() uintptr {
   324		/*
   325			TODO: Convert to Go when something actually uses the result.
   326	
   327			Rlimit rl;
   328			extern byte runtime·text[], runtime·end[];
   329			uintptr used;
   330	
   331			if(runtime·getrlimit(RLIMIT_AS, &rl) != 0)
   332				return 0;
   333			if(rl.rlim_cur >= 0x7fffffff)
   334				return 0;
   335	
   336			// Estimate our VM footprint excluding the heap.
   337			// Not an exact science: use size of binary plus
   338			// some room for thread stacks.
   339			used = runtime·end - runtime·text + (64<<20);
   340			if(used >= rl.rlim_cur)
   341				return 0;
   342	
   343			// If there's not at least 16 MB left, we're probably
   344			// not going to be able to do much. Treat as no limit.
   345			rl.rlim_cur -= used;
   346			if(rl.rlim_cur < (16<<20))
   347				return 0;
   348	
   349			return rl.rlim_cur - used;
   350		*/
   351	
   352		return 0
   353	}
   354	
   355	//#ifdef GOARCH_386
   356	//#define sa_handler k_sa_handler
   357	//#endif
   358	
   359	func sigreturn()
   360	func sigtramp(sig uint32, info *siginfo, ctx unsafe.Pointer)
   361	func cgoSigtramp()
   362	
   363	//go:noescape
   364	func sigaltstack(new, old *stackt)
   365	
   366	//go:noescape
   367	func setitimer(mode int32, new, old *itimerval)
   368	
   369	//go:noescape
   370	func rtsigprocmask(how int32, new, old *sigset, size int32)
   371	
   372	//go:nosplit
   373	//go:nowritebarrierrec
   374	func sigprocmask(how int32, new, old *sigset) {
   375		rtsigprocmask(how, new, old, int32(unsafe.Sizeof(*new)))
   376	}
   377	
   378	//go:noescape
   379	func getrlimit(kind int32, limit unsafe.Pointer) int32
   380	func raise(sig uint32)
   381	func raiseproc(sig uint32)
   382	
   383	//go:noescape
   384	func sched_getaffinity(pid, len uintptr, buf *uintptr) int32
   385	func osyield()
   386	
   387	//go:nosplit
   388	//go:nowritebarrierrec
   389	func setsig(i uint32, fn uintptr) {
   390		var sa sigactiont
   391		sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK | _SA_RESTORER | _SA_RESTART
   392		sigfillset(&sa.sa_mask)
   393		// Although Linux manpage says "sa_restorer element is obsolete and
   394		// should not be used". x86_64 kernel requires it. Only use it on
   395		// x86.
   396		if GOARCH == "386" || GOARCH == "amd64" {
   397			sa.sa_restorer = funcPC(sigreturn)
   398		}
   399		if fn == funcPC(sighandler) {
   400			if iscgo {
   401				fn = funcPC(cgoSigtramp)
   402			} else {
   403				fn = funcPC(sigtramp)
   404			}
   405		}
   406		sa.sa_handler = fn
   407		rt_sigaction(uintptr(i), &sa, nil, unsafe.Sizeof(sa.sa_mask))
   408	}
   409	
   410	//go:nosplit
   411	//go:nowritebarrierrec
   412	func setsigstack(i uint32) {
   413		var sa sigactiont
   414		rt_sigaction(uintptr(i), nil, &sa, unsafe.Sizeof(sa.sa_mask))
   415		if sa.sa_flags&_SA_ONSTACK != 0 {
   416			return
   417		}
   418		sa.sa_flags |= _SA_ONSTACK
   419		rt_sigaction(uintptr(i), &sa, nil, unsafe.Sizeof(sa.sa_mask))
   420	}
   421	
   422	//go:nosplit
   423	//go:nowritebarrierrec
   424	func getsig(i uint32) uintptr {
   425		var sa sigactiont
   426		if rt_sigaction(uintptr(i), nil, &sa, unsafe.Sizeof(sa.sa_mask)) != 0 {
   427			throw("rt_sigaction read failure")
   428		}
   429		return sa.sa_handler
   430	}
   431	
   432	// setSignaltstackSP sets the ss_sp field of a stackt.
   433	//go:nosplit
   434	func setSignalstackSP(s *stackt, sp uintptr) {
   435		*(*uintptr)(unsafe.Pointer(&s.ss_sp)) = sp
   436	}
   437	
   438	func (c *sigctxt) fixsigcode(sig uint32) {
   439	}
   440	

View as plain text