Commit 32b1d51f by Ian Lance Taylor

runtime: move osinit to Go

    
    This is a step toward updating libgo to 1.13.  This adds the 1.13
    version of the osinit function to Go code, and removes the
    corresponding code from the C runtime.  This should simplify future updates.
    Some additional 1.13 code was brought in to simplify this change.
    
    Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/191717

From-SVN: r275010
parent c980510a
5d15923ada640befb236d5fe94f0c724e98e99d7
db738935c77443840994e5a9f77e619e67a4c43a
The first line of this file holds the git revision number of the last
merge done from the gofrontend repository.
......@@ -413,40 +413,6 @@ else
rtems_task_variable_add_file =
endif
if LIBGO_IS_LINUX
runtime_getncpu_file = runtime/getncpu-linux.c
else
if LIBGO_IS_DARWIN
runtime_getncpu_file = runtime/getncpu-bsd.c
else
if LIBGO_IS_IRIX
runtime_getncpu_file = runtime/getncpu-irix.c
else
if LIBGO_IS_SOLARIS
runtime_getncpu_file = runtime/getncpu-solaris.c
else
if LIBGO_IS_FREEBSD
runtime_getncpu_file = runtime/getncpu-bsd.c
else
if LIBGO_IS_NETBSD
runtime_getncpu_file = runtime/getncpu-bsd.c
else
if LIBGO_IS_AIX
runtime_getncpu_file = runtime/getncpu-aix.c
else
if LIBGO_IS_HURD
runtime_getncpu_file = runtime/getncpu-hurd.c
else
runtime_getncpu_file = runtime/getncpu-none.c
endif
endif
endif
endif
endif
endif
endif
endif
runtime_files = \
runtime/aeshash.c \
runtime/go-assert.c \
......@@ -479,8 +445,7 @@ runtime_files = \
runtime/stack.c \
runtime/yield.c \
runtime/go-context.S \
$(rtems_task_variable_add_file) \
$(runtime_getncpu_file)
$(rtems_task_variable_add_file)
version.go: s-version; @true
s-version: Makefile
......
......@@ -230,16 +230,7 @@ am__DEPENDENCIES_4 = $(am__DEPENDENCIES_2) \
libgo_llgo_la_DEPENDENCIES = $(am__DEPENDENCIES_4)
@LIBGO_IS_RTEMS_TRUE@am__objects_1 = \
@LIBGO_IS_RTEMS_TRUE@ runtime/rtems-task-variable-add.lo
@LIBGO_IS_AIX_FALSE@@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_HURD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@am__objects_2 = runtime/getncpu-none.lo
@LIBGO_IS_AIX_FALSE@@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_HURD_TRUE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@am__objects_2 = runtime/getncpu-hurd.lo
@LIBGO_IS_AIX_TRUE@@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@am__objects_2 = runtime/getncpu-aix.lo
@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_TRUE@@LIBGO_IS_SOLARIS_FALSE@am__objects_2 = runtime/getncpu-bsd.lo
@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_TRUE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@am__objects_2 = runtime/getncpu-bsd.lo
@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@am__objects_2 = runtime/getncpu-solaris.lo
@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_IRIX_TRUE@@LIBGO_IS_LINUX_FALSE@am__objects_2 = runtime/getncpu-irix.lo
@LIBGO_IS_DARWIN_TRUE@@LIBGO_IS_LINUX_FALSE@am__objects_2 = runtime/getncpu-bsd.lo
@LIBGO_IS_LINUX_TRUE@am__objects_2 = runtime/getncpu-linux.lo
am__objects_3 = runtime/aeshash.lo runtime/go-assert.lo \
am__objects_2 = runtime/aeshash.lo runtime/go-assert.lo \
runtime/go-caller.lo runtime/go-callers.lo runtime/go-cdiv.lo \
runtime/go-cgo.lo runtime/go-construct-map.lo \
runtime/go-ffi.lo runtime/go-fieldtrack.lo \
......@@ -252,9 +243,8 @@ am__objects_3 = runtime/aeshash.lo runtime/go-assert.lo \
runtime/go-unwind.lo runtime/go-varargs.lo \
runtime/env_posix.lo runtime/panic.lo runtime/print.lo \
runtime/proc.lo runtime/runtime_c.lo runtime/stack.lo \
runtime/yield.lo runtime/go-context.lo $(am__objects_1) \
$(am__objects_2)
am_libgo_llgo_la_OBJECTS = $(am__objects_3)
runtime/yield.lo runtime/go-context.lo $(am__objects_1)
am_libgo_llgo_la_OBJECTS = $(am__objects_2)
libgo_llgo_la_OBJECTS = $(am_libgo_llgo_la_OBJECTS)
AM_V_lt = $(am__v_lt_@AM_V@)
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
......@@ -265,7 +255,7 @@ libgo_llgo_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(libgo_llgo_la_LDFLAGS) $(LDFLAGS) -o $@
@GOC_IS_LLGO_TRUE@am_libgo_llgo_la_rpath = -rpath $(toolexeclibdir)
libgo_la_DEPENDENCIES = $(am__DEPENDENCIES_4)
am_libgo_la_OBJECTS = $(am__objects_3)
am_libgo_la_OBJECTS = $(am__objects_2)
libgo_la_OBJECTS = $(am_libgo_la_OBJECTS)
libgo_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
......@@ -871,15 +861,6 @@ noinst_DATA = internal/x/net/internal/nettest.gox \
zdefaultcc.go
@LIBGO_IS_RTEMS_FALSE@rtems_task_variable_add_file =
@LIBGO_IS_RTEMS_TRUE@rtems_task_variable_add_file = runtime/rtems-task-variable-add.c
@LIBGO_IS_AIX_FALSE@@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_HURD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@runtime_getncpu_file = runtime/getncpu-none.c
@LIBGO_IS_AIX_FALSE@@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_HURD_TRUE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@runtime_getncpu_file = runtime/getncpu-hurd.c
@LIBGO_IS_AIX_TRUE@@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@runtime_getncpu_file = runtime/getncpu-aix.c
@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_TRUE@@LIBGO_IS_SOLARIS_FALSE@runtime_getncpu_file = runtime/getncpu-bsd.c
@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_TRUE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@runtime_getncpu_file = runtime/getncpu-bsd.c
@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@runtime_getncpu_file = runtime/getncpu-solaris.c
@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_IRIX_TRUE@@LIBGO_IS_LINUX_FALSE@runtime_getncpu_file = runtime/getncpu-irix.c
@LIBGO_IS_DARWIN_TRUE@@LIBGO_IS_LINUX_FALSE@runtime_getncpu_file = runtime/getncpu-bsd.c
@LIBGO_IS_LINUX_TRUE@runtime_getncpu_file = runtime/getncpu-linux.c
runtime_files = \
runtime/aeshash.c \
runtime/go-assert.c \
......@@ -912,8 +893,7 @@ runtime_files = \
runtime/stack.c \
runtime/yield.c \
runtime/go-context.S \
$(rtems_task_variable_add_file) \
$(runtime_getncpu_file)
$(rtems_task_variable_add_file)
GCCGO_INSTALL_NAME := $(shell echo gccgo|sed '$(program_transform_name)')
GCC_INSTALL_NAME := $(shell echo gcc|sed '$(program_transform_name)')
......@@ -1385,20 +1365,6 @@ runtime/go-context.lo: runtime/$(am__dirstamp) \
runtime/$(DEPDIR)/$(am__dirstamp)
runtime/rtems-task-variable-add.lo: runtime/$(am__dirstamp) \
runtime/$(DEPDIR)/$(am__dirstamp)
runtime/getncpu-none.lo: runtime/$(am__dirstamp) \
runtime/$(DEPDIR)/$(am__dirstamp)
runtime/getncpu-hurd.lo: runtime/$(am__dirstamp) \
runtime/$(DEPDIR)/$(am__dirstamp)
runtime/getncpu-aix.lo: runtime/$(am__dirstamp) \
runtime/$(DEPDIR)/$(am__dirstamp)
runtime/getncpu-bsd.lo: runtime/$(am__dirstamp) \
runtime/$(DEPDIR)/$(am__dirstamp)
runtime/getncpu-solaris.lo: runtime/$(am__dirstamp) \
runtime/$(DEPDIR)/$(am__dirstamp)
runtime/getncpu-irix.lo: runtime/$(am__dirstamp) \
runtime/$(DEPDIR)/$(am__dirstamp)
runtime/getncpu-linux.lo: runtime/$(am__dirstamp) \
runtime/$(DEPDIR)/$(am__dirstamp)
libgo-llgo.la: $(libgo_llgo_la_OBJECTS) $(libgo_llgo_la_DEPENDENCIES) $(EXTRA_libgo_llgo_la_DEPENDENCIES)
$(AM_V_CCLD)$(libgo_llgo_la_LINK) $(am_libgo_llgo_la_rpath) $(libgo_llgo_la_OBJECTS) $(libgo_llgo_la_LIBADD) $(LIBS)
......@@ -1416,13 +1382,6 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@runtime/$(DEPDIR)/aeshash.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@runtime/$(DEPDIR)/env_posix.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@runtime/$(DEPDIR)/getncpu-aix.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@runtime/$(DEPDIR)/getncpu-bsd.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@runtime/$(DEPDIR)/getncpu-hurd.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@runtime/$(DEPDIR)/getncpu-irix.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@runtime/$(DEPDIR)/getncpu-linux.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@runtime/$(DEPDIR)/getncpu-none.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@runtime/$(DEPDIR)/getncpu-solaris.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@runtime/$(DEPDIR)/go-assert.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@runtime/$(DEPDIR)/go-caller.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@runtime/$(DEPDIR)/go-callers.Plo@am__quote@
......
......@@ -335,6 +335,23 @@ const (
// mallocinit.
var physPageSize uintptr
// physHugePageSize is the size in bytes of the OS's default physical huge
// page size whose allocation is opaque to the application. It is assumed
// and verified to be a power of two.
//
// If set, this must be set by the OS init code (typically in osinit) before
// mallocinit. However, setting it at all is optional, and leaving the default
// value is always safe (though potentially less efficient).
//
// Since physHugePageSize is always assumed to be a power of two,
// physHugePageShift is defined as physHugePageSize == 1 << physHugePageShift.
// The purpose of physHugePageShift is to avoid doing divisions in
// performance critical functions.
var (
physHugePageSize uintptr
physHugePageShift uint
)
// OS-defined helpers:
//
// sysAlloc obtains a large chunk of zeroed memory from the
......
......@@ -20,6 +20,7 @@ func kevent(kq int32, ch *keventt, nch uintptr, ev *keventt, nev uintptr, ts *ti
//extern __go_fcntl_uintptr
func fcntlUintptr(fd, cmd, arg uintptr) (uintptr, uintptr)
//go:nosplit
func closeonexec(fd int32) {
fcntlUintptr(uintptr(fd), _F_SETFD, _FD_CLOEXEC)
}
......
......@@ -12,10 +12,27 @@ var executablePath string
func getexecname() *byte
//extern getpagesize
func getpagesize() int32
func getPageSize() int32
//extern sysconf
func sysconf(int32) _C_long
func getncpu() int32 {
n := int32(sysconf(__SC_NPROCESSORS_ONLN))
if n < 1 {
return 1
}
return n
}
func osinit() {
ncpu = getncpu()
if physPageSize == 0 {
physPageSize = uintptr(getPageSize())
}
}
func sysargs(argc int32, argv **byte) {
physPageSize = uintptr(getpagesize())
executablePath = gostringnocopy(getexecname())
}
......
......@@ -6,7 +6,16 @@
package runtime
import "unsafe"
import (
"internal/cpu"
"unsafe"
)
//extern sysconf
func sysconf(int32) _C_long
//extern getsystemcfg
func getsystemcfg(int32) uint64
type mOS struct {
waitsema uintptr // semaphore for parking on locks
......@@ -106,7 +115,32 @@ func semawakeup(mp *m) {
}
}
func osinit() {
ncpu = int32(sysconf(__SC_NPROCESSORS_ONLN))
physPageSize = uintptr(sysconf(__SC_PAGE_SIZE))
setupSystemConf()
}
const (
_CLOCK_REALTIME = 9
_CLOCK_MONOTONIC = 10
)
const (
// getsystemcfg constants
_SC_IMPL = 2
_IMPL_POWER8 = 0x10000
_IMPL_POWER9 = 0x20000
)
// setupSystemConf retrieves information about the CPU and updates
// cpu.HWCap variables.
func setupSystemConf() {
impl := getsystemcfg(_SC_IMPL)
if impl&_IMPL_POWER8 != 0 {
cpu.HWCap2 |= cpu.PPC_FEATURE2_ARCH_2_07
}
if impl&_IMPL_POWER9 != 0 {
cpu.HWCap2 |= cpu.PPC_FEATURE2_ARCH_3_00
}
}
......@@ -6,6 +6,24 @@ package runtime
import "unsafe"
//extern pipe
func libcPipe([2]int32) int32
func pipe() (r, w int32, e int32) {
var p [2]int32
r := libcPipe(noescape(unsafe.Pointer(&p)))
if r < 0 {
e = int32(errno())
}
return p[0], p[1], e
}
//go:nosplit
func setNonblock(fd int32) {
flags := fcntlUintptr(uintptr(fd), _F_GETFL, 0)
fcntlUintptr(uintptr(fd), _F_SETFL, flags|_O_NONBLOCK)
}
type mOS struct {
initialized bool
mutex pthreadmutex
......@@ -74,3 +92,58 @@ func semawakeup(mp *m) {
}
pthread_mutex_unlock(&mp.mutex)
}
// The read and write file descriptors used by the sigNote functions.
var sigNoteRead, sigNoteWrite int32
// sigNoteSetup initializes an async-signal-safe note.
//
// The current implementation of notes on Darwin is not async-signal-safe,
// because the functions pthread_mutex_lock, pthread_cond_signal, and
// pthread_mutex_unlock, called by semawakeup, are not async-signal-safe.
// There is only one case where we need to wake up a note from a signal
// handler: the sigsend function. The signal handler code does not require
// all the features of notes: it does not need to do a timed wait.
// This is a separate implementation of notes, based on a pipe, that does
// not support timed waits but is async-signal-safe.
func sigNoteSetup(*note) {
if sigNoteRead != 0 || sigNoteWrite != 0 {
throw("duplicate sigNoteSetup")
}
var errno int32
sigNoteRead, sigNoteWrite, errno = pipe()
if errno != 0 {
throw("pipe failed")
}
closeonexec(sigNoteRead)
closeonexec(sigNoteWrite)
// Make the write end of the pipe non-blocking, so that if the pipe
// buffer is somehow full we will not block in the signal handler.
// Leave the read end of the pipe blocking so that we will block
// in sigNoteSleep.
setNonblock(sigNoteWrite)
}
// sigNoteWakeup wakes up a thread sleeping on a note created by sigNoteSetup.
func sigNoteWakeup(*note) {
var b byte
write(uintptr(sigNoteWrite), unsafe.Pointer(&b), 1)
}
// sigNoteSleep waits for a note created by sigNoteSetup to be woken.
func sigNoteSleep(*note) {
entersyscallblock()
var b byte
read(sigNoteRead, unsafe.Pointer(&b), 1)
exitsyscall()
}
// BSD interface for threading.
func osinit() {
// pthread_create delayed until end of goenvs so that we
// can look at the environment first.
ncpu = getncpu()
physPageSize = getPageSize()
}
......@@ -19,6 +19,32 @@ func sys_umtx_sleep(addr *uint32, val, timeout int32) int32
//extern umtx_wakeup
func sys_umtx_wakeup(addr *uint32, val int32) int32
//go:noescape
//extern sysctl
func sysctl(*uint32, uint32, *byte, *uintptr, *byte, uintptr) int32
func getncpu() int32 {
mib := [2]uint32{_CTL_HW, _HW_NCPU}
out := uint32(0)
nout := uintptr(unsafe.Sizeof(out))
ret := sysctl(&mib[0], 2, (*byte)(unsafe.Pointer(&out)), &nout, nil, 0)
if ret >= 0 {
return int32(out)
}
return 1
}
func getPageSize() uintptr {
mib := [2]uint32{_CTL_HW, _HW_PAGESIZE}
out := uint32(0)
nout := uintptr(unsafe.Sizeof(out))
ret := sysctl(&mib[0], 2, (*byte)(unsafe.Pointer(&out)), &nout, nil, 0)
if ret >= 0 {
return uintptr(out)
}
return 0
}
//go:nosplit
func futexsleep(addr *uint32, val uint32, ns int64) {
systemstack(func() {
......@@ -61,3 +87,10 @@ func futexwakeup(addr *uint32, cnt uint32) {
*(*int32)(unsafe.Pointer(uintptr(0x1006))) = 0x1006
})
}
func osinit() {
ncpu = getncpu()
if physPageSize == 0 {
physPageSize = getPageSize()
}
}
......@@ -14,6 +14,104 @@ type mOS struct{}
//extern _umtx_op
func sys_umtx_op(addr *uint32, mode int32, val uint32, uaddr1 uinptr, ts *umtx_time) int32
//go:noescape
//extern sysctl
func sysctl(*uint32, uint32, *byte, *uintptr, *byte, uintptr) int32
const (
_CTL_MAXNAME = 24
_CPU_LEVEL_WHICH = 3
_CPU_WHICH_PID = 2
)
// From FreeBSD's <sys/sysctl.h>
const (
_CTL_HW = 6
_HW_PAGESIZE = 7
)
// Undocumented numbers from FreeBSD's lib/libc/gen/sysctlnametomib.c.
const (
_CTL_QUERY = 0
_CTL_QUERY_MIB = 3
)
// sysctlnametomib fill mib with dynamically assigned sysctl entries of name,
// return count of effected mib slots, return 0 on error.
func sysctlnametomib(name []byte, mib *[_CTL_MAXNAME]uint32) uint32 {
oid := [2]uint32{_CTL_QUERY, _CTL_QUERY_MIB}
miblen := uintptr(_CTL_MAXNAME)
if sysctl(&oid[0], 2, (*byte)(unsafe.Pointer(mib)), &miblen, (*byte)(unsafe.Pointer(&name[0])), (uintptr)(len(name))) < 0 {
return 0
}
miblen /= unsafe.Sizeof(uint32(0))
if miblen <= 0 {
return 0
}
return uint32(miblen)
}
const (
_CPU_CURRENT_PID = -1 // Current process ID.
)
//go:noescape
//extern cpuset_getaffinity
func cpuset_getaffinity(level int32, which int32, id int64, size uintptr, mask *byte) int32
//go:systemstack
func getncpu() int32 {
// Use a large buffer for the CPU mask. We're on the system
// stack, so this is fine, and we can't allocate memory for a
// dynamically-sized buffer at this point.
const maxCPUs = 64 * 1024
var mask [maxCPUs / 8]byte
var mib [_CTL_MAXNAME]uint32
// According to FreeBSD's /usr/src/sys/kern/kern_cpuset.c,
// cpuset_getaffinity return ERANGE when provided buffer size exceed the limits in kernel.
// Querying kern.smp.maxcpus to calculate maximum buffer size.
// See https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=200802
// Variable kern.smp.maxcpus introduced at Dec 23 2003, revision 123766,
// with dynamically assigned sysctl entries.
miblen := sysctlnametomib([]byte("kern.smp.maxcpus"), &mib)
if miblen == 0 {
return 1
}
// Query kern.smp.maxcpus.
dstsize := uintptr(4)
maxcpus := uint32(0)
if sysctl(&mib[0], miblen, (*byte)(unsafe.Pointer(&maxcpus)), &dstsize, nil, 0) != 0 {
return 1
}
maskSize := uintptr(int(maxcpus+7) / 8)
if maskSize < sys.PtrSize {
maskSize = sys.PtrSize
}
if maskSize > uintptr(len(mask)) {
maskSize = uintptr(len(mask))
}
if cpuset_getaffinity(_CPU_LEVEL_WHICH, _CPU_WHICH_PID, _CPU_CURRENT_PID,
maskSize, (*byte)(unsafe.Pointer(&mask[0]))) != 0 {
return 1
}
n := int32(0)
for _, v := range mask[:maskSize] {
for v != 0 {
n += int32(v & 1)
v >>= 1
}
}
if n == 0 {
return 1
}
return n
}
func getPageSize() uintptr {
mib := [2]uint32{_CTL_HW, _HW_PAGESIZE}
out := uint32(0)
......@@ -64,6 +162,13 @@ func futexwakeup(addr *uint32, cnt uint32) {
})
}
func osinit() {
ncpu = getncpu()
if physPageSize == 0 {
physPageSize = getPageSize()
}
}
func sysargs(argc int32, argv **byte) {
n := argc + 1
......
......@@ -8,6 +8,12 @@ package runtime
import "unsafe"
//extern sysconf
func sysconf(int32) _C_long
//extern getpagesize
func getPageSize() int32
type mOS struct {
waitsema uintptr // semaphore for parking on locks
}
......@@ -85,3 +91,18 @@ func semawakeup(mp *m) {
throw("sem_post")
}
}
func getncpu() int32 {
n := int32(sysconf(_SC_NPROCESSORS_ONLN))
if n < 1 {
return 1
}
return n
}
func osinit() {
ncpu = getncpu()
if physPageSize == 0 {
physPageSize = uintptr(getPageSize())
}
}
......@@ -17,6 +17,12 @@ func futex(addr unsafe.Pointer, op int32, val uint32, ts, addr2 unsafe.Pointer,
return int32(syscall(_SYS_futex, uintptr(addr), uintptr(op), uintptr(val), uintptr(ts), uintptr(addr2), uintptr(val3)))
}
// For sched_getaffinity use the system call rather than the libc call,
// because the system call returns the number of entries set by the kernel.
func sched_getaffinity(pid _pid_t, cpusetsize uintptr, mask *byte) int32 {
return int32(syscall(_SYS_sched_getaffinity, uintptr(pid), cpusetsize, uintptr(unsafe.Pointer(mask)), 0, 0, 0))
}
// Linux futex.
//
// futexsleep(uint32 *addr, uint32 val)
......@@ -84,6 +90,33 @@ func futexwakeup(addr *uint32, cnt uint32) {
*(*int32)(unsafe.Pointer(uintptr(0x1006))) = 0x1006
}
func getproccount() int32 {
// This buffer is huge (8 kB) but we are on the system stack
// and there should be plenty of space (64 kB).
// Also this is a leaf, so we're not holding up the memory for long.
// See golang.org/issue/11823.
// The suggested behavior here is to keep trying with ever-larger
// buffers, but we don't have a dynamic memory allocator at the
// moment, so that's a bit tricky and seems like overkill.
const maxCPUs = 64 * 1024
var buf [maxCPUs / 8]byte
r := sched_getaffinity(0, unsafe.Sizeof(buf), &buf[0])
if r < 0 {
return 1
}
n := int32(0)
for _, v := range buf[:r] {
for v != 0 {
n += int32(v & 1)
v >>= 1
}
}
if n == 0 {
n = 1
}
return n
}
const (
_AT_NULL = 0 // End of vector
_AT_PAGESZ = 6 // System physical page size
......@@ -178,3 +211,33 @@ func sysauxv(auxv []uintptr) int {
}
return i / 2
}
var sysTHPSizePath = []byte("/sys/kernel/mm/transparent_hugepage/hpage_pmd_size\x00")
func getHugePageSize() uintptr {
var numbuf [20]byte
fd := open(&sysTHPSizePath[0], 0 /* O_RDONLY */, 0)
if fd < 0 {
return 0
}
n := read(fd, noescape(unsafe.Pointer(&numbuf[0])), int32(len(numbuf)))
closefd(fd)
if n <= 0 {
return 0
}
l := n - 1 // remove trailing newline
v, ok := atoi(slicebytetostringtmp(numbuf[:l]))
if !ok || v < 0 {
v = 0
}
if v&(v-1) != 0 {
// v is not a power of 2
return 0
}
return uintptr(v)
}
func osinit() {
ncpu = getproccount()
physHugePageSize = getHugePageSize()
}
......@@ -22,6 +22,39 @@ func lwp_park(ts int32, rel int32, abstime *timespec, unpark int32, hint, unpark
//extern lwp_unpark
func lwp_unpark(lwp int32, hint unsafe.Pointer) int32
//go:noescape
//extern sysctl
func sysctl(*uint32, uint32, *byte, *uintptr, *byte, uintptr) int32
// From NetBSD's <sys/sysctl.h>
const (
_CTL_HW = 6
_HW_NCPU = 3
_HW_PAGESIZE = 7
)
func getncpu() int32 {
mib := [2]uint32{_CTL_HW, _HW_NCPU}
out := uint32(0)
nout := unsafe.Sizeof(out)
ret := sysctl(&mib[0], 2, (*byte)(unsafe.Pointer(&out)), &nout, nil, 0)
if ret >= 0 {
return int32(out)
}
return 1
}
func getPageSize() uintptr {
mib := [2]uint32{_CTL_HW, _HW_PAGESIZE}
out := uint32(0)
nout := unsafe.Sizeof(out)
ret := sysctl(&mib[0], 2, (*byte)(unsafe.Pointer(&out)), &nout, nil, 0)
if ret >= 0 {
return uintptr(out)
}
return 0
}
//go:nosplit
func semacreate(mp *m) {
}
......@@ -77,3 +110,10 @@ func semawakeup(mp *m) {
})
}
}
func osinit() {
ncpu = getncpu()
if physPageSize == 0 {
physPageSize = getPageSize()
}
}
......@@ -22,6 +22,58 @@ func thrsleep(ident uintptr, clock_id int32, tsp *timespec, lock uintptr, abort
//extern thrwakeup
func thrwakeup(ident uintptr, n int32) int32
//go:noescape
//extern sysctl
func sysctl(*uint32, uint32, *byte, *uintptr, *byte, uintptr) int32
// From OpenBSD's <sys/sysctl.h>
const (
_CTL_KERN = 1
_KERN_OSREV = 3
_CTL_HW = 6
_HW_NCPU = 3
_HW_PAGESIZE = 7
_HW_NCPUONLINE = 25
)
func sysctlInt(mib []uint32) (int32, bool) {
var out int32
nout := unsafe.Sizeof(out)
ret := sysctl(&mib[0], uint32(len(mib)), (*byte)(unsafe.Pointer(&out)), &nout, nil, 0)
if ret < 0 {
return 0, false
}
return out, true
}
func getncpu() int32 {
// Try hw.ncpuonline first because hw.ncpu would report a number twice as
// high as the actual CPUs running on OpenBSD 6.4 with hyperthreading
// disabled (hw.smt=0). See https://golang.org/issue/30127
if n, ok := sysctlInt([]uint32{_CTL_HW, _HW_NCPUONLINE}); ok {
return int32(n)
}
if n, ok := sysctlInt([]uint32{_CTL_HW, _HW_NCPU}); ok {
return int32(n)
}
return 1
}
func getPageSize() uintptr {
if ps, ok := sysctlInt([]uint32{_CTL_HW, _HW_PAGESIZE}); ok {
return uintptr(ps)
}
return 0
}
func getOSRev() int {
if osrev, ok := sysctlInt([]uint32{_CTL_KERN, _KERN_OSREV}); ok {
return int(osrev)
}
return 0
}
//go:nosplit
func semacreate(mp *m) {
}
......@@ -75,3 +127,11 @@ func semawakeup(mp *m) {
})
}
}
func osinit() {
ncpu = getncpu()
physPageSize = getPageSize()
haveMapStack = getOSRev() >= 201805 // OpenBSD 6.3
}
var haveMapStack = false
......@@ -333,20 +333,6 @@ func rethrowException()
// used by the stack unwinder.
func unwindExceptionSize() uintptr
// Called by C code to set the number of CPUs.
//go:linkname setncpu runtime.setncpu
func setncpu(n int32) {
ncpu = n
}
// Called by C code to set the page size.
//go:linkname setpagesize runtime.setpagesize
func setpagesize(s uintptr) {
if physPageSize == 0 {
physPageSize = s
}
}
const uintptrMask = 1<<(8*sys.PtrSize) - 1
type bitvector struct {
......
......@@ -6,7 +6,6 @@
// +build !windows
// +build !nacl
// +build !js
// +build !darwin
package runtime
......@@ -32,3 +31,6 @@ func exitThread(wait *uint32) {
// This is never used by gccgo.
throw("exitThread")
}
// So that the C initialization code can call osinit.
//go:linkname osinit runtime.osinit
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin
// +build 386 arm
package runtime
import "unsafe"
//go:linkname syscall_syscall9 syscall.syscall9
//go:nosplit
//go:cgo_unsafe_args
func syscall_syscall9(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2, err uintptr) {
entersyscallblock()
libcCall(unsafe.Pointer(funcPC(syscall9)), unsafe.Pointer(&fn))
exitsyscall()
return
}
func syscall9()
//go:linkname syscall_syscallPtr syscall.syscallPtr
//go:nosplit
//go:cgo_unsafe_args
func syscall_syscallPtr(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
entersyscallblock()
libcCall(unsafe.Pointer(funcPC(syscallPtr)), unsafe.Pointer(&fn))
exitsyscall()
return
}
func syscallPtr()
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin
// +build amd64 arm64
package runtime
import "unsafe"
//go:linkname syscall_syscallX syscall.syscallX
//go:nosplit
//go:cgo_unsafe_args
func syscall_syscallX(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
entersyscallblock()
libcCall(unsafe.Pointer(funcPC(syscallX)), unsafe.Pointer(&fn))
exitsyscall()
return
}
func syscallX()
//go:linkname syscall_syscallXPtr syscall.syscallXPtr
//go:nosplit
//go:cgo_unsafe_args
func syscall_syscallXPtr(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
entersyscallblock()
libcCall(unsafe.Pointer(funcPC(syscallXPtr)), unsafe.Pointer(&fn))
exitsyscall()
return
}
func syscallXPtr()
......@@ -31,6 +31,19 @@ grep -v '^// ' gen-sysinfo.go | \
-e 's/\([^a-zA-Z0-9_]\)_timespec\([^a-zA-Z0-9_]\)/\1timespec\2/g' \
>> ${OUT}
# The C long type, needed because that is the type that ptrace returns.
sizeof_long=`grep '^const ___SIZEOF_LONG__ = ' gen-sysinfo.go | sed -e 's/.*= //'`
if test "$sizeof_long" = "4"; then
echo "type _C_long int32" >> ${OUT}
echo "type _C_ulong uint32" >> ${OUT}
elif test "$sizeof_long" = "8"; then
echo "type _C_long int64" >> ${OUT}
echo "type _C_ulong uint64" >> ${OUT}
else
echo 1>&2 "mkrsysinfo.sh: could not determine size of long (got $sizeof_long)"
exit 1
fi
# On AIX, the _arpcom struct, is filtered by the above grep sequence, as it as
# a field of type _in6_addr, but other types depend on _arpcom, so we need to
# put it back.
......
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#include <sys/types.h>
#include <sys/systemcfg.h>
#include "runtime.h"
#include "defs.h"
int32_t
getproccount(void)
{
return _system_configuration.ncpus;
}
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#include <sys/types.h>
#include <sys/sysctl.h>
#include "runtime.h"
#include "defs.h"
int32
getproccount(void)
{
int mib[2], out;
size_t len;
mib[0] = CTL_HW;
mib[1] = HW_NCPU;
len = sizeof(out);
if(sysctl(mib, 2, &out, &len, NULL, 0) >= 0)
return (int32)out;
else
return 0;
}
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#include <unistd.h>
#include "runtime.h"
#include "defs.h"
int32
getproccount(void)
{
int32 n;
n = (int32)sysconf(_SC_NPROCESSORS_ONLN);
return n > 1 ? n : 1;
}
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#include <unistd.h>
#include "runtime.h"
#include "defs.h"
int32
getproccount(void)
{
int32 n;
n = (int32)sysconf(_SC_NPROC_ONLN);
return n > 1 ? n : 1;
}
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#include <features.h>
#include <sched.h>
// CPU_COUNT is only provided by glibc 2.6 or higher
#ifndef CPU_COUNT
#define CPU_COUNT(set) _CPU_COUNT((unsigned int *)(set), sizeof(*(set))/sizeof(unsigned int))
static int _CPU_COUNT(unsigned int *set, size_t len) {
int cnt;
cnt = 0;
while (len--)
cnt += __builtin_popcount(*set++);
return cnt;
}
#endif
#include "runtime.h"
#include "defs.h"
int32
getproccount(void)
{
cpu_set_t set;
int32 r, cnt;
cnt = 0;
r = sched_getaffinity(0, sizeof(set), &set);
if(r == 0)
cnt += CPU_COUNT(&set);
return cnt ? cnt : 1;
}
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#include "runtime.h"
#include "defs.h"
int32
getproccount(void)
{
return 0;
}
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#include <unistd.h>
#include "runtime.h"
#include "defs.h"
int32
getproccount(void)
{
int32 n;
n = (int32)sysconf(_SC_NPROCESSORS_ONLN);
return n > 1 ? n : 1;
}
......@@ -228,8 +228,7 @@ gostart (void *arg)
runtime_ginit ();
runtime_check ();
runtime_args (a->argc, (byte **) a->argv);
setncpu (getproccount ());
setpagesize (getpagesize ());
runtime_osinit ();
runtime_schedinit ();
__go_go ((uintptr)(runtime_main), NULL);
runtime_mstart (runtime_m ());
......
......@@ -52,8 +52,7 @@ main (int argc, char **argv)
runtime_cpuinit ();
runtime_check ();
runtime_args (argc, (byte **) argv);
setncpu (getproccount ());
setpagesize (getpagesize ());
runtime_osinit ();
runtime_schedinit ();
__go_go ((uintptr)(runtime_main), NULL);
runtime_mstart (runtime_m ());
......
......@@ -211,6 +211,8 @@ void runtime_gogo(G*)
struct __go_func_type;
void runtime_args(int32, byte**)
__asm__ (GOSYM_PREFIX "runtime.args");
void runtime_osinit(void)
__asm__ (GOSYM_PREFIX "runtime.osinit");
void runtime_alginit(void)
__asm__ (GOSYM_PREFIX "runtime.alginit");
void runtime_goargs(void)
......@@ -429,8 +431,6 @@ extern void __go_syminfo_fnname_callback(void*, uintptr_t, const char*,
extern void runtime_main(void*)
__asm__(GOSYM_PREFIX "runtime.main");
int32 getproccount(void);
#define PREFETCH(p) __builtin_prefetch(p)
void runtime_badsignal(int);
......@@ -456,12 +456,8 @@ extern void setSupportAES(bool)
__asm__ (GOSYM_PREFIX "runtime.setSupportAES");
extern void typedmemmove(const Type *, void *, const void *)
__asm__ (GOSYM_PREFIX "runtime.typedmemmove");
extern void setncpu(int32)
__asm__(GOSYM_PREFIX "runtime.setncpu");
extern Sched* runtime_getsched(void)
__asm__ (GOSYM_PREFIX "runtime.getsched");
extern void setpagesize(uintptr_t)
__asm__(GOSYM_PREFIX "runtime.setpagesize");
struct funcfileline_return
{
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment