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
This commit is contained in:
Ian Lance Taylor 2019-08-28 20:39:32 +00:00
parent c980510a5a
commit 32b1d51f16
30 changed files with 494 additions and 739 deletions

View File

@ -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.

View File

@ -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

View File

@ -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@

View File

@ -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

View File

@ -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)
}

View File

@ -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())
}

View File

@ -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
}
}

View File

@ -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()
}

View File

@ -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()
}
}

View File

@ -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

View File

@ -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())
}
}

View File

@ -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()
}

View File

@ -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()
}
}

View File

@ -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

View File

@ -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 {

View File

@ -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

View File

@ -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"

View File

@ -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()

View File

@ -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()

View File

@ -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.

View File

@ -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 <sys/types.h>
#include <sys/systemcfg.h>
#include "runtime.h"
#include "defs.h"
int32_t
getproccount(void)
{
return _system_configuration.ncpus;
}

View File

@ -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 <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;
}

View File

@ -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 <unistd.h>
#include "runtime.h"
#include "defs.h"
int32
getproccount(void)
{
int32 n;
n = (int32)sysconf(_SC_NPROCESSORS_ONLN);
return n > 1 ? n : 1;
}

View File

@ -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 <unistd.h>
#include "runtime.h"
#include "defs.h"
int32
getproccount(void)
{
int32 n;
n = (int32)sysconf(_SC_NPROC_ONLN);
return n > 1 ? n : 1;
}

View File

@ -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 <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;
}

View File

@ -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;
}

View File

@ -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 <unistd.h>
#include "runtime.h"
#include "defs.h"
int32
getproccount(void)
{
int32 n;
n = (int32)sysconf(_SC_NPROCESSORS_ONLN);
return n > 1 ? n : 1;
}

View File

@ -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 ());

View File

@ -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 ());

View File

@ -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
{