From: Ian Lance Taylor Date: Wed, 28 Aug 2019 20:39:32 +0000 (+0000) Subject: runtime: move osinit to Go X-Git-Tag: upstream/12.2.0~22175 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=32b1d51f16fe56b34e979fcfba4bc74dbd3592a9;p=platform%2Fupstream%2Fgcc.git 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 --- diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index 54a5935..3ae07c4 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -1,4 +1,4 @@ -5d15923ada640befb236d5fe94f0c724e98e99d7 +db738935c77443840994e5a9f77e619e67a4c43a The first line of this file holds the git revision number of the last merge done from the gofrontend repository. diff --git a/libgo/Makefile.am b/libgo/Makefile.am index 9348af9..341bac0 100644 --- a/libgo/Makefile.am +++ b/libgo/Makefile.am @@ -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 diff --git a/libgo/Makefile.in b/libgo/Makefile.in index 153bc95..f415ca6 100644 --- a/libgo/Makefile.in +++ b/libgo/Makefile.in @@ -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@ diff --git a/libgo/go/runtime/malloc.go b/libgo/go/runtime/malloc.go index c0b4caa..68e5494 100644 --- a/libgo/go/runtime/malloc.go +++ b/libgo/go/runtime/malloc.go @@ -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 diff --git a/libgo/go/runtime/netpoll_kqueue.go b/libgo/go/runtime/netpoll_kqueue.go index 3d62650..4ea3ac9 100644 --- a/libgo/go/runtime/netpoll_kqueue.go +++ b/libgo/go/runtime/netpoll_kqueue.go @@ -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) } diff --git a/libgo/go/runtime/os3_solaris.go b/libgo/go/runtime/os3_solaris.go index e67d32c..d5fbccd 100644 --- a/libgo/go/runtime/os3_solaris.go +++ b/libgo/go/runtime/os3_solaris.go @@ -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()) } diff --git a/libgo/go/runtime/os_aix.go b/libgo/go/runtime/os_aix.go index 9211f21..b337330 100644 --- a/libgo/go/runtime/os_aix.go +++ b/libgo/go/runtime/os_aix.go @@ -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 + } +} diff --git a/libgo/go/runtime/os_darwin.go b/libgo/go/runtime/os_darwin.go index 235f794..deaa9e9 100644 --- a/libgo/go/runtime/os_darwin.go +++ b/libgo/go/runtime/os_darwin.go @@ -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() +} diff --git a/libgo/go/runtime/os_dragonfly.go b/libgo/go/runtime/os_dragonfly.go index abcad72..d214f7f 100644 --- a/libgo/go/runtime/os_dragonfly.go +++ b/libgo/go/runtime/os_dragonfly.go @@ -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() + } +} diff --git a/libgo/go/runtime/os_freebsd.go b/libgo/go/runtime/os_freebsd.go index 4cce6fd..f8577e4 100644 --- a/libgo/go/runtime/os_freebsd.go +++ b/libgo/go/runtime/os_freebsd.go @@ -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 +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 diff --git a/libgo/go/runtime/os_hurd.go b/libgo/go/runtime/os_hurd.go index 1282553..3a545d0 100644 --- a/libgo/go/runtime/os_hurd.go +++ b/libgo/go/runtime/os_hurd.go @@ -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()) + } +} diff --git a/libgo/go/runtime/os_linux.go b/libgo/go/runtime/os_linux.go index 04314bd..b72872f 100644 --- a/libgo/go/runtime/os_linux.go +++ b/libgo/go/runtime/os_linux.go @@ -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() +} diff --git a/libgo/go/runtime/os_netbsd.go b/libgo/go/runtime/os_netbsd.go index 16a1192..b7aa953 100644 --- a/libgo/go/runtime/os_netbsd.go +++ b/libgo/go/runtime/os_netbsd.go @@ -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 +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() + } +} diff --git a/libgo/go/runtime/os_openbsd.go b/libgo/go/runtime/os_openbsd.go index 4f05665..4298172 100644 --- a/libgo/go/runtime/os_openbsd.go +++ b/libgo/go/runtime/os_openbsd.go @@ -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 +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 diff --git a/libgo/go/runtime/stubs.go b/libgo/go/runtime/stubs.go index e00d759..a81bf92 100644 --- a/libgo/go/runtime/stubs.go +++ b/libgo/go/runtime/stubs.go @@ -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 { diff --git a/libgo/go/runtime/stubs2.go b/libgo/go/runtime/stubs2.go index 1cb910c..dcbbffa 100644 --- a/libgo/go/runtime/stubs2.go +++ b/libgo/go/runtime/stubs2.go @@ -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 diff --git a/libgo/go/runtime/sys_darwin.go b/libgo/go/runtime/sys_darwin.go deleted file mode 100644 index f34ac88..0000000 --- a/libgo/go/runtime/sys_darwin.go +++ /dev/null @@ -1,429 +0,0 @@ -// 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. - -package runtime - -import "unsafe" - -// Call fn with arg as its argument. Return what fn returns. -// fn is the raw pc value of the entry point of the desired function. -// Switches to the system stack, if not already there. -// Preserves the calling point as the location where a profiler traceback will begin. -//go:nosplit -func libcCall(fn, arg unsafe.Pointer) int32 { - // Leave caller's PC/SP/G around for traceback. - gp := getg() - var mp *m - if gp != nil { - mp = gp.m - } - if mp != nil && mp.libcallsp == 0 { - mp.libcallg.set(gp) - mp.libcallpc = getcallerpc() - // sp must be the last, because once async cpu profiler finds - // all three values to be non-zero, it will use them - mp.libcallsp = getcallersp() - } else { - // Make sure we don't reset libcallsp. This makes - // libcCall reentrant; We remember the g/pc/sp for the - // first call on an M, until that libcCall instance - // returns. Reentrance only matters for signals, as - // libc never calls back into Go. The tricky case is - // where we call libcX from an M and record g/pc/sp. - // Before that call returns, a signal arrives on the - // same M and the signal handling code calls another - // libc function. We don't want that second libcCall - // from within the handler to be recorded, and we - // don't want that call's completion to zero - // libcallsp. - // We don't need to set libcall* while we're in a sighandler - // (even if we're not currently in libc) because we block all - // signals while we're handling a signal. That includes the - // profile signal, which is the one that uses the libcall* info. - mp = nil - } - res := asmcgocall(fn, arg) - if mp != nil { - mp.libcallsp = 0 - } - return res -} - -// The X versions of syscall expect the libc call to return a 64-bit result. -// Otherwise (the non-X version) expects a 32-bit result. -// This distinction is required because an error is indicated by returning -1, -// and we need to know whether to check 32 or 64 bits of the result. -// (Some libc functions that return 32 bits put junk in the upper 32 bits of AX.) - -//go:linkname syscall_syscall syscall.syscall -//go:nosplit -//go:cgo_unsafe_args -func syscall_syscall(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) { - entersyscallblock() - libcCall(unsafe.Pointer(funcPC(syscall)), unsafe.Pointer(&fn)) - exitsyscall() - return -} -func syscall() - -//go:linkname syscall_syscall6 syscall.syscall6 -//go:nosplit -//go:cgo_unsafe_args -func syscall_syscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) { - entersyscallblock() - libcCall(unsafe.Pointer(funcPC(syscall6)), unsafe.Pointer(&fn)) - exitsyscall() - return -} -func syscall6() - -//go:linkname syscall_syscall6X syscall.syscall6X -//go:nosplit -//go:cgo_unsafe_args -func syscall_syscall6X(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) { - entersyscallblock() - libcCall(unsafe.Pointer(funcPC(syscall6X)), unsafe.Pointer(&fn)) - exitsyscall() - return -} -func syscall6X() - -//go:linkname syscall_rawSyscall syscall.rawSyscall -//go:nosplit -//go:cgo_unsafe_args -func syscall_rawSyscall(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) { - libcCall(unsafe.Pointer(funcPC(syscall)), unsafe.Pointer(&fn)) - return -} - -//go:linkname syscall_rawSyscall6 syscall.rawSyscall6 -//go:nosplit -//go:cgo_unsafe_args -func syscall_rawSyscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) { - libcCall(unsafe.Pointer(funcPC(syscall6)), unsafe.Pointer(&fn)) - return -} - -// The *_trampoline functions convert from the Go calling convention to the C calling convention -// and then call the underlying libc function. They are defined in sys_darwin_$ARCH.s. - -//go:nosplit -//go:cgo_unsafe_args -func pthread_attr_init(attr *pthreadattr) int32 { - return libcCall(unsafe.Pointer(funcPC(pthread_attr_init_trampoline)), unsafe.Pointer(&attr)) -} -func pthread_attr_init_trampoline() - -//go:nosplit -//go:cgo_unsafe_args -func pthread_attr_setstacksize(attr *pthreadattr, size uintptr) int32 { - return libcCall(unsafe.Pointer(funcPC(pthread_attr_setstacksize_trampoline)), unsafe.Pointer(&attr)) -} -func pthread_attr_setstacksize_trampoline() - -//go:nosplit -//go:cgo_unsafe_args -func pthread_attr_setdetachstate(attr *pthreadattr, state int) int32 { - return libcCall(unsafe.Pointer(funcPC(pthread_attr_setdetachstate_trampoline)), unsafe.Pointer(&attr)) -} -func pthread_attr_setdetachstate_trampoline() - -//go:nosplit -//go:cgo_unsafe_args -func pthread_create(attr *pthreadattr, start uintptr, arg unsafe.Pointer) int32 { - return libcCall(unsafe.Pointer(funcPC(pthread_create_trampoline)), unsafe.Pointer(&attr)) -} -func pthread_create_trampoline() - -//go:nosplit -//go:cgo_unsafe_args -func raise(sig uint32) { - libcCall(unsafe.Pointer(funcPC(raise_trampoline)), unsafe.Pointer(&sig)) -} -func raise_trampoline() - -//go:nosplit -//go:cgo_unsafe_args -func pthread_self() (t pthread) { - libcCall(unsafe.Pointer(funcPC(pthread_self_trampoline)), unsafe.Pointer(&t)) - return -} -func pthread_self_trampoline() - -func mmap(addr unsafe.Pointer, n uintptr, prot, flags, fd int32, off uint32) (unsafe.Pointer, int) { - args := struct { - addr unsafe.Pointer - n uintptr - prot, flags, fd int32 - off uint32 - ret1 unsafe.Pointer - ret2 int - }{addr, n, prot, flags, fd, off, nil, 0} - libcCall(unsafe.Pointer(funcPC(mmap_trampoline)), unsafe.Pointer(&args)) - return args.ret1, args.ret2 -} -func mmap_trampoline() - -//go:nosplit -//go:cgo_unsafe_args -func munmap(addr unsafe.Pointer, n uintptr) { - libcCall(unsafe.Pointer(funcPC(munmap_trampoline)), unsafe.Pointer(&addr)) -} -func munmap_trampoline() - -//go:nosplit -//go:cgo_unsafe_args -func madvise(addr unsafe.Pointer, n uintptr, flags int32) { - libcCall(unsafe.Pointer(funcPC(madvise_trampoline)), unsafe.Pointer(&addr)) -} -func madvise_trampoline() - -//go:nosplit -//go:cgo_unsafe_args -func read(fd int32, p unsafe.Pointer, n int32) int32 { - return libcCall(unsafe.Pointer(funcPC(read_trampoline)), unsafe.Pointer(&fd)) -} -func read_trampoline() - -//go:nosplit -//go:cgo_unsafe_args -func closefd(fd int32) int32 { - return libcCall(unsafe.Pointer(funcPC(close_trampoline)), unsafe.Pointer(&fd)) -} -func close_trampoline() - -//go:nosplit -//go:cgo_unsafe_args -func exit(code int32) { - libcCall(unsafe.Pointer(funcPC(exit_trampoline)), unsafe.Pointer(&code)) -} -func exit_trampoline() - -//go:nosplit -//go:cgo_unsafe_args -func usleep(usec uint32) { - libcCall(unsafe.Pointer(funcPC(usleep_trampoline)), unsafe.Pointer(&usec)) -} -func usleep_trampoline() - -//go:nosplit -//go:cgo_unsafe_args -func write(fd uintptr, p unsafe.Pointer, n int32) int32 { - return libcCall(unsafe.Pointer(funcPC(write_trampoline)), unsafe.Pointer(&fd)) -} -func write_trampoline() - -//go:nosplit -//go:cgo_unsafe_args -func open(name *byte, mode, perm int32) (ret int32) { - return libcCall(unsafe.Pointer(funcPC(open_trampoline)), unsafe.Pointer(&name)) -} -func open_trampoline() - -//go:nosplit -//go:cgo_unsafe_args -func nanotime() int64 { - var r struct { - t int64 // raw timer - numer, denom uint32 // conversion factors. nanoseconds = t * numer / denom. - } - libcCall(unsafe.Pointer(funcPC(nanotime_trampoline)), unsafe.Pointer(&r)) - // Note: Apple seems unconcerned about overflow here. See - // https://developer.apple.com/library/content/qa/qa1398/_index.html - // Note also, numer == denom == 1 is common. - t := r.t - if r.numer != 1 { - t *= int64(r.numer) - } - if r.denom != 1 { - t /= int64(r.denom) - } - return t -} -func nanotime_trampoline() - -//go:nosplit -//go:cgo_unsafe_args -func walltime() (int64, int32) { - var t timeval - libcCall(unsafe.Pointer(funcPC(walltime_trampoline)), unsafe.Pointer(&t)) - return int64(t.tv_sec), 1000 * t.tv_usec -} -func walltime_trampoline() - -//go:nosplit -//go:cgo_unsafe_args -func sigaction(sig uint32, new *usigactiont, old *usigactiont) { - libcCall(unsafe.Pointer(funcPC(sigaction_trampoline)), unsafe.Pointer(&sig)) -} -func sigaction_trampoline() - -//go:nosplit -//go:cgo_unsafe_args -func sigprocmask(how uint32, new *sigset, old *sigset) { - libcCall(unsafe.Pointer(funcPC(sigprocmask_trampoline)), unsafe.Pointer(&how)) -} -func sigprocmask_trampoline() - -//go:nosplit -//go:cgo_unsafe_args -func sigaltstack(new *stackt, old *stackt) { - if new != nil && new.ss_flags&_SS_DISABLE != 0 && new.ss_size == 0 { - // Despite the fact that Darwin's sigaltstack man page says it ignores the size - // when SS_DISABLE is set, it doesn't. sigaltstack returns ENOMEM - // if we don't give it a reasonable size. - // ref: http://lists.llvm.org/pipermail/llvm-commits/Week-of-Mon-20140421/214296.html - new.ss_size = 32768 - } - libcCall(unsafe.Pointer(funcPC(sigaltstack_trampoline)), unsafe.Pointer(&new)) -} -func sigaltstack_trampoline() - -//go:nosplit -//go:cgo_unsafe_args -func raiseproc(sig uint32) { - libcCall(unsafe.Pointer(funcPC(raiseproc_trampoline)), unsafe.Pointer(&sig)) -} -func raiseproc_trampoline() - -//go:nosplit -//go:cgo_unsafe_args -func setitimer(mode int32, new, old *itimerval) { - libcCall(unsafe.Pointer(funcPC(setitimer_trampoline)), unsafe.Pointer(&mode)) -} -func setitimer_trampoline() - -//go:nosplit -//go:cgo_unsafe_args -func sysctl(mib *uint32, miblen uint32, out *byte, size *uintptr, dst *byte, ndst uintptr) int32 { - return libcCall(unsafe.Pointer(funcPC(sysctl_trampoline)), unsafe.Pointer(&mib)) -} -func sysctl_trampoline() - -//go:nosplit -//go:cgo_unsafe_args -func fcntl(fd, cmd, arg int32) int32 { - return libcCall(unsafe.Pointer(funcPC(fcntl_trampoline)), unsafe.Pointer(&fd)) -} -func fcntl_trampoline() - -//go:nosplit -//go:cgo_unsafe_args -func kqueue() int32 { - v := libcCall(unsafe.Pointer(funcPC(kqueue_trampoline)), nil) - return v -} -func kqueue_trampoline() - -//go:nosplit -//go:cgo_unsafe_args -func kevent(kq int32, ch *keventt, nch int32, ev *keventt, nev int32, ts *timespec) int32 { - return libcCall(unsafe.Pointer(funcPC(kevent_trampoline)), unsafe.Pointer(&kq)) -} -func kevent_trampoline() - -//go:nosplit -//go:cgo_unsafe_args -func pthread_mutex_init(m *pthreadmutex, attr *pthreadmutexattr) int32 { - return libcCall(unsafe.Pointer(funcPC(pthread_mutex_init_trampoline)), unsafe.Pointer(&m)) -} -func pthread_mutex_init_trampoline() - -//go:nosplit -//go:cgo_unsafe_args -func pthread_mutex_lock(m *pthreadmutex) int32 { - return libcCall(unsafe.Pointer(funcPC(pthread_mutex_lock_trampoline)), unsafe.Pointer(&m)) -} -func pthread_mutex_lock_trampoline() - -//go:nosplit -//go:cgo_unsafe_args -func pthread_mutex_unlock(m *pthreadmutex) int32 { - return libcCall(unsafe.Pointer(funcPC(pthread_mutex_unlock_trampoline)), unsafe.Pointer(&m)) -} -func pthread_mutex_unlock_trampoline() - -//go:nosplit -//go:cgo_unsafe_args -func pthread_cond_init(c *pthreadcond, attr *pthreadcondattr) int32 { - return libcCall(unsafe.Pointer(funcPC(pthread_cond_init_trampoline)), unsafe.Pointer(&c)) -} -func pthread_cond_init_trampoline() - -//go:nosplit -//go:cgo_unsafe_args -func pthread_cond_wait(c *pthreadcond, m *pthreadmutex) int32 { - return libcCall(unsafe.Pointer(funcPC(pthread_cond_wait_trampoline)), unsafe.Pointer(&c)) -} -func pthread_cond_wait_trampoline() - -//go:nosplit -//go:cgo_unsafe_args -func pthread_cond_timedwait_relative_np(c *pthreadcond, m *pthreadmutex, t *timespec) int32 { - return libcCall(unsafe.Pointer(funcPC(pthread_cond_timedwait_relative_np_trampoline)), unsafe.Pointer(&c)) -} -func pthread_cond_timedwait_relative_np_trampoline() - -//go:nosplit -//go:cgo_unsafe_args -func pthread_cond_signal(c *pthreadcond) int32 { - return libcCall(unsafe.Pointer(funcPC(pthread_cond_signal_trampoline)), unsafe.Pointer(&c)) -} -func pthread_cond_signal_trampoline() - -// Not used on Darwin, but must be defined. -func exitThread(wait *uint32) { -} - -//go:nosplit -func closeonexec(fd int32) { - fcntl(fd, _F_SETFD, _FD_CLOEXEC) -} - -// Tell the linker that the libc_* functions are to be found -// in a system library, with the libc_ prefix missing. - -//go:cgo_import_dynamic libc_pthread_attr_init pthread_attr_init "/usr/lib/libSystem.B.dylib" -//go:cgo_import_dynamic libc_pthread_attr_setstacksize pthread_attr_setstacksize "/usr/lib/libSystem.B.dylib" -//go:cgo_import_dynamic libc_pthread_attr_setdetachstate pthread_attr_setdetachstate "/usr/lib/libSystem.B.dylib" -//go:cgo_import_dynamic libc_pthread_create pthread_create "/usr/lib/libSystem.B.dylib" -//go:cgo_import_dynamic libc_exit exit "/usr/lib/libSystem.B.dylib" -//go:cgo_import_dynamic libc_raise raise "/usr/lib/libSystem.B.dylib" - -//go:cgo_import_dynamic libc_open open "/usr/lib/libSystem.B.dylib" -//go:cgo_import_dynamic libc_close close "/usr/lib/libSystem.B.dylib" -//go:cgo_import_dynamic libc_read read "/usr/lib/libSystem.B.dylib" -//go:cgo_import_dynamic libc_write write "/usr/lib/libSystem.B.dylib" - -//go:cgo_import_dynamic libc_mmap mmap "/usr/lib/libSystem.B.dylib" -//go:cgo_import_dynamic libc_munmap munmap "/usr/lib/libSystem.B.dylib" -//go:cgo_import_dynamic libc_madvise madvise "/usr/lib/libSystem.B.dylib" -//go:cgo_import_dynamic libc_error __error "/usr/lib/libSystem.B.dylib" -//go:cgo_import_dynamic libc_usleep usleep "/usr/lib/libSystem.B.dylib" - -//go:cgo_import_dynamic libc_mach_timebase_info mach_timebase_info "/usr/lib/libSystem.B.dylib" -//go:cgo_import_dynamic libc_mach_absolute_time mach_absolute_time "/usr/lib/libSystem.B.dylib" -//go:cgo_import_dynamic libc_gettimeofday gettimeofday "/usr/lib/libSystem.B.dylib" -//go:cgo_import_dynamic libc_sigaction sigaction "/usr/lib/libSystem.B.dylib" -//go:cgo_import_dynamic libc_pthread_sigmask pthread_sigmask "/usr/lib/libSystem.B.dylib" -//go:cgo_import_dynamic libc_sigaltstack sigaltstack "/usr/lib/libSystem.B.dylib" -//go:cgo_import_dynamic libc_getpid getpid "/usr/lib/libSystem.B.dylib" -//go:cgo_import_dynamic libc_kill kill "/usr/lib/libSystem.B.dylib" -//go:cgo_import_dynamic libc_setitimer setitimer "/usr/lib/libSystem.B.dylib" -//go:cgo_import_dynamic libc_sysctl sysctl "/usr/lib/libSystem.B.dylib" -//go:cgo_import_dynamic libc_fcntl fcntl "/usr/lib/libSystem.B.dylib" -//go:cgo_import_dynamic libc_kqueue kqueue "/usr/lib/libSystem.B.dylib" -//go:cgo_import_dynamic libc_kevent kevent "/usr/lib/libSystem.B.dylib" - -//go:cgo_import_dynamic libc_pthread_mutex_init pthread_mutex_init "/usr/lib/libSystem.B.dylib" -//go:cgo_import_dynamic libc_pthread_mutex_lock pthread_mutex_lock "/usr/lib/libSystem.B.dylib" -//go:cgo_import_dynamic libc_pthread_mutex_unlock pthread_mutex_unlock "/usr/lib/libSystem.B.dylib" -//go:cgo_import_dynamic libc_pthread_cond_init pthread_cond_init "/usr/lib/libSystem.B.dylib" -//go:cgo_import_dynamic libc_pthread_cond_wait pthread_cond_wait "/usr/lib/libSystem.B.dylib" -//go:cgo_import_dynamic libc_pthread_cond_timedwait_relative_np pthread_cond_timedwait_relative_np "/usr/lib/libSystem.B.dylib" -//go:cgo_import_dynamic libc_pthread_cond_signal pthread_cond_signal "/usr/lib/libSystem.B.dylib" - -// Magic incantation to get libSystem actually dynamically linked. -// TODO: Why does the code require this? See cmd/link/internal/ld/go.go -//go:cgo_import_dynamic _ _ "/usr/lib/libSystem.B.dylib" diff --git a/libgo/go/runtime/sys_darwin_32.go b/libgo/go/runtime/sys_darwin_32.go deleted file mode 100644 index 2f17091..0000000 --- a/libgo/go/runtime/sys_darwin_32.go +++ /dev/null @@ -1,32 +0,0 @@ -// 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() diff --git a/libgo/go/runtime/sys_darwin_64.go b/libgo/go/runtime/sys_darwin_64.go deleted file mode 100644 index 8c12881..0000000 --- a/libgo/go/runtime/sys_darwin_64.go +++ /dev/null @@ -1,32 +0,0 @@ -// 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() diff --git a/libgo/mkrsysinfo.sh b/libgo/mkrsysinfo.sh index 40bc34b..f1aa724 100755 --- a/libgo/mkrsysinfo.sh +++ b/libgo/mkrsysinfo.sh @@ -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. diff --git a/libgo/runtime/getncpu-aix.c b/libgo/runtime/getncpu-aix.c deleted file mode 100644 index 064eed8..0000000 --- a/libgo/runtime/getncpu-aix.c +++ /dev/null @@ -1,15 +0,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 -#include - -#include "runtime.h" -#include "defs.h" - -int32_t -getproccount(void) -{ - return _system_configuration.ncpus; -} diff --git a/libgo/runtime/getncpu-bsd.c b/libgo/runtime/getncpu-bsd.c deleted file mode 100644 index 00a81d1..0000000 --- a/libgo/runtime/getncpu-bsd.c +++ /dev/null @@ -1,24 +0,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 -#include - -#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; -} diff --git a/libgo/runtime/getncpu-hurd.c b/libgo/runtime/getncpu-hurd.c deleted file mode 100644 index 5d5d702..0000000 --- a/libgo/runtime/getncpu-hurd.c +++ /dev/null @@ -1,16 +0,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 - -#include "runtime.h" -#include "defs.h" - -int32 -getproccount(void) -{ - int32 n; - n = (int32)sysconf(_SC_NPROCESSORS_ONLN); - return n > 1 ? n : 1; -} diff --git a/libgo/runtime/getncpu-irix.c b/libgo/runtime/getncpu-irix.c deleted file mode 100644 index a65ca63..0000000 --- a/libgo/runtime/getncpu-irix.c +++ /dev/null @@ -1,16 +0,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 - -#include "runtime.h" -#include "defs.h" - -int32 -getproccount(void) -{ - int32 n; - n = (int32)sysconf(_SC_NPROC_ONLN); - return n > 1 ? n : 1; -} diff --git a/libgo/runtime/getncpu-linux.c b/libgo/runtime/getncpu-linux.c deleted file mode 100644 index de6606f..0000000 --- a/libgo/runtime/getncpu-linux.c +++ /dev/null @@ -1,36 +0,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 -#include - -// 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; -} diff --git a/libgo/runtime/getncpu-none.c b/libgo/runtime/getncpu-none.c deleted file mode 100644 index ba6fd4e..0000000 --- a/libgo/runtime/getncpu-none.c +++ /dev/null @@ -1,12 +0,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 "runtime.h" -#include "defs.h" - -int32 -getproccount(void) -{ - return 0; -} diff --git a/libgo/runtime/getncpu-solaris.c b/libgo/runtime/getncpu-solaris.c deleted file mode 100644 index 5d5d702..0000000 --- a/libgo/runtime/getncpu-solaris.c +++ /dev/null @@ -1,16 +0,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 - -#include "runtime.h" -#include "defs.h" - -int32 -getproccount(void) -{ - int32 n; - n = (int32)sysconf(_SC_NPROCESSORS_ONLN); - return n > 1 ? n : 1; -} diff --git a/libgo/runtime/go-libmain.c b/libgo/runtime/go-libmain.c index f379569..10b202b 100644 --- a/libgo/runtime/go-libmain.c +++ b/libgo/runtime/go-libmain.c @@ -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 ()); diff --git a/libgo/runtime/go-main.c b/libgo/runtime/go-main.c index 51ce15f..dcf763a 100644 --- a/libgo/runtime/go-main.c +++ b/libgo/runtime/go-main.c @@ -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 ()); diff --git a/libgo/runtime/runtime.h b/libgo/runtime/runtime.h index 6da7bdf..4102f5d 100644 --- a/libgo/runtime/runtime.h +++ b/libgo/runtime/runtime.h @@ -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 {