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 The first line of this file holds the git revision number of the last
merge done from the gofrontend repository. merge done from the gofrontend repository.

View File

@ -413,40 +413,6 @@ else
rtems_task_variable_add_file = rtems_task_variable_add_file =
endif 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_files = \
runtime/aeshash.c \ runtime/aeshash.c \
runtime/go-assert.c \ runtime/go-assert.c \
@ -479,8 +445,7 @@ runtime_files = \
runtime/stack.c \ runtime/stack.c \
runtime/yield.c \ runtime/yield.c \
runtime/go-context.S \ runtime/go-context.S \
$(rtems_task_variable_add_file) \ $(rtems_task_variable_add_file)
$(runtime_getncpu_file)
version.go: s-version; @true version.go: s-version; @true
s-version: Makefile s-version: Makefile

View File

@ -230,16 +230,7 @@ am__DEPENDENCIES_4 = $(am__DEPENDENCIES_2) \
libgo_llgo_la_DEPENDENCIES = $(am__DEPENDENCIES_4) libgo_llgo_la_DEPENDENCIES = $(am__DEPENDENCIES_4)
@LIBGO_IS_RTEMS_TRUE@am__objects_1 = \ @LIBGO_IS_RTEMS_TRUE@am__objects_1 = \
@LIBGO_IS_RTEMS_TRUE@ runtime/rtems-task-variable-add.lo @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 am__objects_2 = runtime/aeshash.lo runtime/go-assert.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 \
runtime/go-caller.lo runtime/go-callers.lo runtime/go-cdiv.lo \ runtime/go-caller.lo runtime/go-callers.lo runtime/go-cdiv.lo \
runtime/go-cgo.lo runtime/go-construct-map.lo \ runtime/go-cgo.lo runtime/go-construct-map.lo \
runtime/go-ffi.lo runtime/go-fieldtrack.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/go-unwind.lo runtime/go-varargs.lo \
runtime/env_posix.lo runtime/panic.lo runtime/print.lo \ runtime/env_posix.lo runtime/panic.lo runtime/print.lo \
runtime/proc.lo runtime/runtime_c.lo runtime/stack.lo \ runtime/proc.lo runtime/runtime_c.lo runtime/stack.lo \
runtime/yield.lo runtime/go-context.lo $(am__objects_1) \ runtime/yield.lo runtime/go-context.lo $(am__objects_1)
$(am__objects_2) am_libgo_llgo_la_OBJECTS = $(am__objects_2)
am_libgo_llgo_la_OBJECTS = $(am__objects_3)
libgo_llgo_la_OBJECTS = $(am_libgo_llgo_la_OBJECTS) libgo_llgo_la_OBJECTS = $(am_libgo_llgo_la_OBJECTS)
AM_V_lt = $(am__v_lt_@AM_V@) AM_V_lt = $(am__v_lt_@AM_V@)
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_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 $@ $(libgo_llgo_la_LDFLAGS) $(LDFLAGS) -o $@
@GOC_IS_LLGO_TRUE@am_libgo_llgo_la_rpath = -rpath $(toolexeclibdir) @GOC_IS_LLGO_TRUE@am_libgo_llgo_la_rpath = -rpath $(toolexeclibdir)
libgo_la_DEPENDENCIES = $(am__DEPENDENCIES_4) 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_OBJECTS = $(am_libgo_la_OBJECTS)
libgo_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ libgo_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
@ -871,15 +861,6 @@ noinst_DATA = internal/x/net/internal/nettest.gox \
zdefaultcc.go zdefaultcc.go
@LIBGO_IS_RTEMS_FALSE@rtems_task_variable_add_file = @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_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_files = \
runtime/aeshash.c \ runtime/aeshash.c \
runtime/go-assert.c \ runtime/go-assert.c \
@ -912,8 +893,7 @@ runtime_files = \
runtime/stack.c \ runtime/stack.c \
runtime/yield.c \ runtime/yield.c \
runtime/go-context.S \ runtime/go-context.S \
$(rtems_task_variable_add_file) \ $(rtems_task_variable_add_file)
$(runtime_getncpu_file)
GCCGO_INSTALL_NAME := $(shell echo gccgo|sed '$(program_transform_name)') GCCGO_INSTALL_NAME := $(shell echo gccgo|sed '$(program_transform_name)')
GCC_INSTALL_NAME := $(shell echo gcc|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/$(DEPDIR)/$(am__dirstamp)
runtime/rtems-task-variable-add.lo: runtime/$(am__dirstamp) \ runtime/rtems-task-variable-add.lo: runtime/$(am__dirstamp) \
runtime/$(DEPDIR)/$(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) 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) $(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)/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)/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-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-caller.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@runtime/$(DEPDIR)/go-callers.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@runtime/$(DEPDIR)/go-callers.Plo@am__quote@

View File

@ -335,6 +335,23 @@ const (
// mallocinit. // mallocinit.
var physPageSize uintptr 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: // OS-defined helpers:
// //
// sysAlloc obtains a large chunk of zeroed memory from the // 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 //extern __go_fcntl_uintptr
func fcntlUintptr(fd, cmd, arg uintptr) (uintptr, uintptr) func fcntlUintptr(fd, cmd, arg uintptr) (uintptr, uintptr)
//go:nosplit
func closeonexec(fd int32) { func closeonexec(fd int32) {
fcntlUintptr(uintptr(fd), _F_SETFD, _FD_CLOEXEC) fcntlUintptr(uintptr(fd), _F_SETFD, _FD_CLOEXEC)
} }

View File

@ -12,10 +12,27 @@ var executablePath string
func getexecname() *byte func getexecname() *byte
//extern getpagesize //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) { func sysargs(argc int32, argv **byte) {
physPageSize = uintptr(getpagesize())
executablePath = gostringnocopy(getexecname()) executablePath = gostringnocopy(getexecname())
} }

View File

@ -6,7 +6,16 @@
package runtime package runtime
import "unsafe" import (
"internal/cpu"
"unsafe"
)
//extern sysconf
func sysconf(int32) _C_long
//extern getsystemcfg
func getsystemcfg(int32) uint64
type mOS struct { type mOS struct {
waitsema uintptr // semaphore for parking on locks 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 ( const (
_CLOCK_REALTIME = 9 _CLOCK_REALTIME = 9
_CLOCK_MONOTONIC = 10 _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" 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 { type mOS struct {
initialized bool initialized bool
mutex pthreadmutex mutex pthreadmutex
@ -74,3 +92,58 @@ func semawakeup(mp *m) {
} }
pthread_mutex_unlock(&mp.mutex) 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 //extern umtx_wakeup
func sys_umtx_wakeup(addr *uint32, val int32) int32 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 //go:nosplit
func futexsleep(addr *uint32, val uint32, ns int64) { func futexsleep(addr *uint32, val uint32, ns int64) {
systemstack(func() { systemstack(func() {
@ -61,3 +87,10 @@ func futexwakeup(addr *uint32, cnt uint32) {
*(*int32)(unsafe.Pointer(uintptr(0x1006))) = 0x1006 *(*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 //extern _umtx_op
func sys_umtx_op(addr *uint32, mode int32, val uint32, uaddr1 uinptr, ts *umtx_time) int32 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 { func getPageSize() uintptr {
mib := [2]uint32{_CTL_HW, _HW_PAGESIZE} mib := [2]uint32{_CTL_HW, _HW_PAGESIZE}
out := uint32(0) 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) { func sysargs(argc int32, argv **byte) {
n := argc + 1 n := argc + 1

View File

@ -8,6 +8,12 @@ package runtime
import "unsafe" import "unsafe"
//extern sysconf
func sysconf(int32) _C_long
//extern getpagesize
func getPageSize() int32
type mOS struct { type mOS struct {
waitsema uintptr // semaphore for parking on locks waitsema uintptr // semaphore for parking on locks
} }
@ -85,3 +91,18 @@ func semawakeup(mp *m) {
throw("sem_post") 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))) 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. // Linux futex.
// //
// futexsleep(uint32 *addr, uint32 val) // futexsleep(uint32 *addr, uint32 val)
@ -84,6 +90,33 @@ func futexwakeup(addr *uint32, cnt uint32) {
*(*int32)(unsafe.Pointer(uintptr(0x1006))) = 0x1006 *(*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 ( const (
_AT_NULL = 0 // End of vector _AT_NULL = 0 // End of vector
_AT_PAGESZ = 6 // System physical page size _AT_PAGESZ = 6 // System physical page size
@ -178,3 +211,33 @@ func sysauxv(auxv []uintptr) int {
} }
return i / 2 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 //extern lwp_unpark
func lwp_unpark(lwp int32, hint unsafe.Pointer) int32 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 //go:nosplit
func semacreate(mp *m) { 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 //extern thrwakeup
func thrwakeup(ident uintptr, n int32) int32 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 //go:nosplit
func semacreate(mp *m) { 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. // used by the stack unwinder.
func unwindExceptionSize() uintptr 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 const uintptrMask = 1<<(8*sys.PtrSize) - 1
type bitvector struct { type bitvector struct {

View File

@ -6,7 +6,6 @@
// +build !windows // +build !windows
// +build !nacl // +build !nacl
// +build !js // +build !js
// +build !darwin
package runtime package runtime
@ -32,3 +31,6 @@ func exitThread(wait *uint32) {
// This is never used by gccgo. // This is never used by gccgo.
throw("exitThread") 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' \ -e 's/\([^a-zA-Z0-9_]\)_timespec\([^a-zA-Z0-9_]\)/\1timespec\2/g' \
>> ${OUT} >> ${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 # 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 # a field of type _in6_addr, but other types depend on _arpcom, so we need to
# put it back. # 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_ginit ();
runtime_check (); runtime_check ();
runtime_args (a->argc, (byte **) a->argv); runtime_args (a->argc, (byte **) a->argv);
setncpu (getproccount ()); runtime_osinit ();
setpagesize (getpagesize ());
runtime_schedinit (); runtime_schedinit ();
__go_go ((uintptr)(runtime_main), NULL); __go_go ((uintptr)(runtime_main), NULL);
runtime_mstart (runtime_m ()); runtime_mstart (runtime_m ());

View File

@ -52,8 +52,7 @@ main (int argc, char **argv)
runtime_cpuinit (); runtime_cpuinit ();
runtime_check (); runtime_check ();
runtime_args (argc, (byte **) argv); runtime_args (argc, (byte **) argv);
setncpu (getproccount ()); runtime_osinit ();
setpagesize (getpagesize ());
runtime_schedinit (); runtime_schedinit ();
__go_go ((uintptr)(runtime_main), NULL); __go_go ((uintptr)(runtime_main), NULL);
runtime_mstart (runtime_m ()); runtime_mstart (runtime_m ());

View File

@ -211,6 +211,8 @@ void runtime_gogo(G*)
struct __go_func_type; struct __go_func_type;
void runtime_args(int32, byte**) void runtime_args(int32, byte**)
__asm__ (GOSYM_PREFIX "runtime.args"); __asm__ (GOSYM_PREFIX "runtime.args");
void runtime_osinit(void)
__asm__ (GOSYM_PREFIX "runtime.osinit");
void runtime_alginit(void) void runtime_alginit(void)
__asm__ (GOSYM_PREFIX "runtime.alginit"); __asm__ (GOSYM_PREFIX "runtime.alginit");
void runtime_goargs(void) void runtime_goargs(void)
@ -429,8 +431,6 @@ extern void __go_syminfo_fnname_callback(void*, uintptr_t, const char*,
extern void runtime_main(void*) extern void runtime_main(void*)
__asm__(GOSYM_PREFIX "runtime.main"); __asm__(GOSYM_PREFIX "runtime.main");
int32 getproccount(void);
#define PREFETCH(p) __builtin_prefetch(p) #define PREFETCH(p) __builtin_prefetch(p)
void runtime_badsignal(int); void runtime_badsignal(int);
@ -456,12 +456,8 @@ extern void setSupportAES(bool)
__asm__ (GOSYM_PREFIX "runtime.setSupportAES"); __asm__ (GOSYM_PREFIX "runtime.setSupportAES");
extern void typedmemmove(const Type *, void *, const void *) extern void typedmemmove(const Type *, void *, const void *)
__asm__ (GOSYM_PREFIX "runtime.typedmemmove"); __asm__ (GOSYM_PREFIX "runtime.typedmemmove");
extern void setncpu(int32)
__asm__(GOSYM_PREFIX "runtime.setncpu");
extern Sched* runtime_getsched(void) extern Sched* runtime_getsched(void)
__asm__ (GOSYM_PREFIX "runtime.getsched"); __asm__ (GOSYM_PREFIX "runtime.getsched");
extern void setpagesize(uintptr_t)
__asm__(GOSYM_PREFIX "runtime.setpagesize");
struct funcfileline_return struct funcfileline_return
{ {