diff --git a/src/cmd/link/internal/arm/asm.go b/src/cmd/link/internal/arm/asm.go index 9932d56e1a..f0a510f1f0 100644 --- a/src/cmd/link/internal/arm/asm.go +++ b/src/cmd/link/internal/arm/asm.go @@ -229,6 +229,10 @@ func adddynrel(ctxt *ld.Link, s *sym.Symbol, r *sym.Reloc) bool { switch r.Type { case objabi.R_CALLARM: + if ctxt.LinkMode == ld.LinkExternal { + // External linker will do this relocation. + return true + } addpltsym(ctxt, targ) r.Sym = ctxt.Syms.Lookup(".plt", 0) r.Add = int64(targ.Plt) diff --git a/src/cmd/link/internal/arm64/asm.go b/src/cmd/link/internal/arm64/asm.go index 0151fa7e0d..5b3b9e5880 100644 --- a/src/cmd/link/internal/arm64/asm.go +++ b/src/cmd/link/internal/arm64/asm.go @@ -92,8 +92,25 @@ func gentext(ctxt *ld.Link) { initarray_entry.AddAddr(ctxt.Arch, initfunc) } +// adddynrel implements just enough to support external linking to +// the system libc functions used by the runtime. func adddynrel(ctxt *ld.Link, s *sym.Symbol, r *sym.Reloc) bool { - log.Fatalf("adddynrel not implemented") + targ := r.Sym + + switch r.Type { + case objabi.R_CALL, + objabi.R_PCREL, + objabi.R_CALLARM64: + if targ.Type != sym.SDYNIMPORT { + // nothing to do, the relocation will be laid out in reloc + return true + } + if ctxt.LinkMode == ld.LinkExternal { + // External linker will do this relocation. + return true + } + } + log.Fatalf("adddynrel not implemented for relocation type %d (%s)", r.Type, sym.RelocName(ctxt.Arch, r.Type)) return false } diff --git a/src/cmd/vet/all/whitelist/darwin_arm.txt b/src/cmd/vet/all/whitelist/darwin_arm.txt index 0e619be462..8e935b6ff2 100644 --- a/src/cmd/vet/all/whitelist/darwin_arm.txt +++ b/src/cmd/vet/all/whitelist/darwin_arm.txt @@ -8,5 +8,4 @@ runtime/sys_darwin_arm.s: [arm] sigfwd: use of unnamed argument 0(FP); offset 0 // Ok. -runtime/sys_darwin_arm.s: [arm] bsdthread_start: function bsdthread_start missing Go declaration runtime/asm_arm.s: [arm] sigreturn: function sigreturn missing Go declaration diff --git a/src/cmd/vet/all/whitelist/darwin_arm64.txt b/src/cmd/vet/all/whitelist/darwin_arm64.txt index 793cccf8dd..8cab997961 100644 --- a/src/cmd/vet/all/whitelist/darwin_arm64.txt +++ b/src/cmd/vet/all/whitelist/darwin_arm64.txt @@ -2,7 +2,4 @@ runtime/sys_darwin_arm64.s: [arm64] sigtramp: 24(RSP) should be infostyle+8(FP) runtime/sys_darwin_arm64.s: [arm64] sigtramp: 24(RSP) should be infostyle+8(FP) -runtime/sys_darwin_arm64.s: [arm64] bsdthread_create: RET without writing to 4-byte ret+24(FP) -runtime/sys_darwin_arm64.s: [arm64] bsdthread_start: function bsdthread_start missing Go declaration -runtime/sys_darwin_arm64.s: [arm64] bsdthread_register: RET without writing to 4-byte ret+0(FP) runtime/asm_arm64.s: [arm64] sigreturn: function sigreturn missing Go declaration diff --git a/src/runtime/asm_arm.s b/src/runtime/asm_arm.s index a65be1cef2..545e58e9b0 100644 --- a/src/runtime/asm_arm.s +++ b/src/runtime/asm_arm.s @@ -588,9 +588,12 @@ TEXT ·asmcgocall(SB),NOSPLIT,$0-12 // We get called to create new OS threads too, and those // come in on the m->g0 stack already. MOVW g_m(g), R8 + MOVW m_gsignal(R8), R3 + CMP R3, g + BEQ noswitch MOVW m_g0(R8), R3 CMP R3, g - BEQ g0 + BEQ noswitch BL gosave<>(SB) MOVW R0, R5 MOVW R3, R0 @@ -599,7 +602,7 @@ TEXT ·asmcgocall(SB),NOSPLIT,$0-12 MOVW (g_sched+gobuf_sp)(g), R13 // Now on a scheduling stack (a pthread-created stack). -g0: +noswitch: SUB $24, R13 BIC $0x7, R13 // alignment for gcc ABI MOVW R4, 20(R13) // save old g diff --git a/src/runtime/asm_arm64.s b/src/runtime/asm_arm64.s index 2319b82255..d1b90b056c 100644 --- a/src/runtime/asm_arm64.s +++ b/src/runtime/asm_arm64.s @@ -869,9 +869,12 @@ TEXT ·asmcgocall(SB),NOSPLIT,$0-20 // We get called to create new OS threads too, and those // come in on the m->g0 stack already. MOVD g_m(g), R8 + MOVD m_gsignal(R8), R3 + CMP R3, g + BEQ noswitch MOVD m_g0(R8), R3 CMP R3, g - BEQ g0 + BEQ noswitch MOVD R0, R9 // gosave<> and save_g might clobber R0 BL gosave<>(SB) MOVD R3, g @@ -881,11 +884,12 @@ TEXT ·asmcgocall(SB),NOSPLIT,$0-20 MOVD R9, R0 // Now on a scheduling stack (a pthread-created stack). -g0: +noswitch: // Save room for two of our pointers /*, plus 32 bytes of callee // save area that lives on the caller stack. */ MOVD RSP, R13 SUB $16, R13 + BIC $0xf, R13 // alignment for gcc ABI MOVD R13, RSP MOVD R4, 0(RSP) // save old g on stack MOVD (g_stack+stack_hi)(R4), R4 diff --git a/src/runtime/defs_darwin_arm.go b/src/runtime/defs_darwin_arm.go index 6d769ac5a5..39a65bca01 100644 --- a/src/runtime/defs_darwin_arm.go +++ b/src/runtime/defs_darwin_arm.go @@ -258,3 +258,8 @@ type pthreadattr struct { X__sig int32 X__opaque [36]int8 } + +type machTimebaseInfo struct { + numer uint32 + denom uint32 +} diff --git a/src/runtime/defs_darwin_arm64.go b/src/runtime/defs_darwin_arm64.go index ce9a2b8c0e..607051ff88 100644 --- a/src/runtime/defs_darwin_arm64.go +++ b/src/runtime/defs_darwin_arm64.go @@ -261,3 +261,8 @@ type pthreadattr struct { X__sig int64 X__opaque [56]int8 } + +type machTimebaseInfo struct { + numer uint32 + denom uint32 +} diff --git a/src/runtime/mmap.go b/src/runtime/mmap.go index 80b89d2ef1..fe09e7029e 100644 --- a/src/runtime/mmap.go +++ b/src/runtime/mmap.go @@ -9,8 +9,7 @@ // +build !linux !amd64 // +build !linux !arm64 // +build !js -// +build !darwin !amd64 -// +build !darwin !386 +// +build !darwin package runtime diff --git a/src/runtime/os_darwin.go b/src/runtime/os_darwin.go index 9a5a03a45d..52153055f0 100644 --- a/src/runtime/os_darwin.go +++ b/src/runtime/os_darwin.go @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build 386 amd64 - package runtime import "unsafe" diff --git a/src/runtime/os_darwin_raw.go b/src/runtime/os_darwin_raw.go deleted file mode 100644 index 9fc0b7ec03..0000000000 --- a/src/runtime/os_darwin_raw.go +++ /dev/null @@ -1,593 +0,0 @@ -// Copyright 2009 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,arm darwin,arm64 - -// TODO(khr): move darwin/arm and darwin/arm64 over to calling libc instead of using raw system calls. - -package runtime - -import "unsafe" - -type mOS struct { - machport uint32 // return address for mach ipc - waitsema uint32 // semaphore for parking on locks -} - -var darwinVersion int - -func bsdthread_create(stk, arg unsafe.Pointer, fn uintptr) int32 -func bsdthread_register() int32 - -//go:noescape -func mach_msg_trap(h unsafe.Pointer, op int32, send_size, rcv_size, rcv_name, timeout, notify uint32) int32 - -func mach_reply_port() uint32 -func mach_task_self() uint32 -func mach_thread_self() uint32 - -//go:noescape -func sysctl(mib *uint32, miblen uint32, out *byte, size *uintptr, dst *byte, ndst uintptr) int32 - -func unimplemented(name string) { - println(name, "not implemented") - *(*int)(unsafe.Pointer(uintptr(1231))) = 1231 -} - -//go:nosplit -func semawakeup(mp *m) { - mach_semrelease(mp.waitsema) -} - -//go:nosplit -func semacreate(mp *m) { - if mp.waitsema != 0 { - return - } - systemstack(func() { - mp.waitsema = mach_semcreate() - }) -} - -// BSD interface for threading. -func osinit() { - // bsdthread_register delayed until end of goenvs so that we - // can look at the environment first. - - ncpu = getncpu() - physPageSize = getPageSize() - darwinVersion = getDarwinVersion() -} - -const ( - _CTL_KERN = 1 - _CTL_HW = 6 - _KERN_OSRELEASE = 2 - _HW_NCPU = 3 - _HW_PAGESIZE = 7 -) - -func getDarwinVersion() int { - // Use sysctl to fetch kern.osrelease - mib := [2]uint32{_CTL_KERN, _KERN_OSRELEASE} - var out [32]byte - nout := unsafe.Sizeof(out) - ret := sysctl(&mib[0], 2, (*byte)(unsafe.Pointer(&out)), &nout, nil, 0) - if ret >= 0 { - ver := 0 - for i := 0; i < int(nout) && out[i] >= '0' && out[i] <= '9'; i++ { - ver *= 10 - ver += int(out[i] - '0') - } - return ver - } - return 17 // should not happen: default to a newish version -} - -func getncpu() int32 { - // Use sysctl to fetch hw.ncpu. - 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 && int32(out) > 0 { - return int32(out) - } - return 1 -} - -func getPageSize() uintptr { - // Use sysctl to fetch hw.pagesize. - 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 && int32(out) > 0 { - return uintptr(out) - } - return 0 -} - -var urandom_dev = []byte("/dev/urandom\x00") - -//go:nosplit -func getRandomData(r []byte) { - fd := open(&urandom_dev[0], 0 /* O_RDONLY */, 0) - n := read(fd, unsafe.Pointer(&r[0]), int32(len(r))) - closefd(fd) - extendRandom(r, int(n)) -} - -func goenvs() { - goenvs_unix() - - // Register our thread-creation callback (see sys_darwin_{amd64,386}.s) - // but only if we're not using cgo. If we are using cgo we need - // to let the C pthread library install its own thread-creation callback. - if !iscgo { - if bsdthread_register() != 0 { - if gogetenv("DYLD_INSERT_LIBRARIES") != "" { - throw("runtime: bsdthread_register error (unset DYLD_INSERT_LIBRARIES)") - } - throw("runtime: bsdthread_register error") - } - } -} - -// May run with m.p==nil, so write barriers are not allowed. -//go:nowritebarrier -func newosproc(mp *m) { - stk := unsafe.Pointer(mp.g0.stack.hi) - if false { - print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " id=", mp.id, " ostk=", &mp, "\n") - } - - var oset sigset - sigprocmask(_SIG_SETMASK, &sigset_all, &oset) - errno := bsdthread_create(stk, unsafe.Pointer(mp), funcPC(mstart)) - sigprocmask(_SIG_SETMASK, &oset, nil) - - if errno < 0 { - print("runtime: failed to create new OS thread (have ", mcount(), " already; errno=", -errno, ")\n") - throw("runtime.newosproc") - } -} - -// newosproc0 is a version of newosproc that can be called before the runtime -// is initialized. -// -// As Go uses bsdthread_register when running without cgo, this function is -// not safe to use after initialization as it does not pass an M as fnarg. -// -//go:nosplit -func newosproc0(stacksize uintptr, fn uintptr) { - stack := sysAlloc(stacksize, &memstats.stacks_sys) - if stack == nil { - write(2, unsafe.Pointer(&failallocatestack[0]), int32(len(failallocatestack))) - exit(1) - } - stk := unsafe.Pointer(uintptr(stack) + stacksize) - - var oset sigset - sigprocmask(_SIG_SETMASK, &sigset_all, &oset) - errno := bsdthread_create(stk, nil, fn) - sigprocmask(_SIG_SETMASK, &oset, nil) - - if errno < 0 { - write(2, unsafe.Pointer(&failthreadcreate[0]), int32(len(failthreadcreate))) - exit(1) - } -} - -var failallocatestack = []byte("runtime: failed to allocate stack for the new OS thread\n") -var failthreadcreate = []byte("runtime: failed to create new OS thread\n") - -// Called to do synchronous initialization of Go code built with -// -buildmode=c-archive or -buildmode=c-shared. -// None of the Go runtime is initialized. -//go:nosplit -//go:nowritebarrierrec -func libpreinit() { - initsig(true) -} - -// Called to initialize a new m (including the bootstrap m). -// Called on the parent thread (main thread in case of bootstrap), can allocate memory. -func mpreinit(mp *m) { - mp.gsignal = malg(32 * 1024) // OS X wants >= 8K - mp.gsignal.m = mp -} - -// Called to initialize a new m (including the bootstrap m). -// Called on the new thread, cannot allocate memory. -func minit() { - // The alternate signal stack is buggy on arm and arm64. - // The signal handler handles it directly. - // The sigaltstack assembly function does nothing. - if GOARCH != "arm" && GOARCH != "arm64" { - minitSignalStack() - } - minitSignalMask() -} - -// Called from dropm to undo the effect of an minit. -//go:nosplit -func unminit() { - // The alternate signal stack is buggy on arm and arm64. - // See minit. - if GOARCH != "arm" && GOARCH != "arm64" { - unminitSignals() - } -} - -// Mach IPC, to get at semaphores -// Definitions are in /usr/include/mach on a Mac. - -func macherror(r int32, fn string) { - print("mach error ", fn, ": ", r, "\n") - throw("mach error") -} - -const _DebugMach = false - -var zerondr machndr - -func mach_msgh_bits(a, b uint32) uint32 { - return a | b<<8 -} - -func mach_msg(h *machheader, op int32, send_size, rcv_size, rcv_name, timeout, notify uint32) int32 { - // TODO: Loop on interrupt. - return mach_msg_trap(unsafe.Pointer(h), op, send_size, rcv_size, rcv_name, timeout, notify) -} - -// Mach RPC (MIG) -const ( - _MinMachMsg = 48 - _MachReply = 100 -) - -type codemsg struct { - h machheader - ndr machndr - code int32 -} - -func machcall(h *machheader, maxsize int32, rxsize int32) int32 { - _g_ := getg() - port := _g_.m.machport - if port == 0 { - port = mach_reply_port() - _g_.m.machport = port - } - - h.msgh_bits |= mach_msgh_bits(_MACH_MSG_TYPE_COPY_SEND, _MACH_MSG_TYPE_MAKE_SEND_ONCE) - h.msgh_local_port = port - h.msgh_reserved = 0 - id := h.msgh_id - - if _DebugMach { - p := (*[10000]unsafe.Pointer)(unsafe.Pointer(h)) - print("send:\t") - var i uint32 - for i = 0; i < h.msgh_size/uint32(unsafe.Sizeof(p[0])); i++ { - print(" ", p[i]) - if i%8 == 7 { - print("\n\t") - } - } - if i%8 != 0 { - print("\n") - } - } - ret := mach_msg(h, _MACH_SEND_MSG|_MACH_RCV_MSG, h.msgh_size, uint32(maxsize), port, 0, 0) - if ret != 0 { - if _DebugMach { - print("mach_msg error ", ret, "\n") - } - return ret - } - if _DebugMach { - p := (*[10000]unsafe.Pointer)(unsafe.Pointer(h)) - var i uint32 - for i = 0; i < h.msgh_size/uint32(unsafe.Sizeof(p[0])); i++ { - print(" ", p[i]) - if i%8 == 7 { - print("\n\t") - } - } - if i%8 != 0 { - print("\n") - } - } - if h.msgh_id != id+_MachReply { - if _DebugMach { - print("mach_msg _MachReply id mismatch ", h.msgh_id, " != ", id+_MachReply, "\n") - } - return -303 // MIG_REPLY_MISMATCH - } - // Look for a response giving the return value. - // Any call can send this back with an error, - // and some calls only have return values so they - // send it back on success too. I don't quite see how - // you know it's one of these and not the full response - // format, so just look if the message is right. - c := (*codemsg)(unsafe.Pointer(h)) - if uintptr(h.msgh_size) == unsafe.Sizeof(*c) && h.msgh_bits&_MACH_MSGH_BITS_COMPLEX == 0 { - if _DebugMach { - print("mig result ", c.code, "\n") - } - return c.code - } - if h.msgh_size != uint32(rxsize) { - if _DebugMach { - print("mach_msg _MachReply size mismatch ", h.msgh_size, " != ", rxsize, "\n") - } - return -307 // MIG_ARRAY_TOO_LARGE - } - return 0 -} - -// Semaphores! - -const ( - tmach_semcreate = 3418 - rmach_semcreate = tmach_semcreate + _MachReply - - tmach_semdestroy = 3419 - rmach_semdestroy = tmach_semdestroy + _MachReply - - _KERN_ABORTED = 14 - _KERN_OPERATION_TIMED_OUT = 49 -) - -type tmach_semcreatemsg struct { - h machheader - ndr machndr - policy int32 - value int32 -} - -type rmach_semcreatemsg struct { - h machheader - body machbody - semaphore machport -} - -type tmach_semdestroymsg struct { - h machheader - body machbody - semaphore machport -} - -func mach_semcreate() uint32 { - var m [256]uint8 - tx := (*tmach_semcreatemsg)(unsafe.Pointer(&m)) - rx := (*rmach_semcreatemsg)(unsafe.Pointer(&m)) - - tx.h.msgh_bits = 0 - tx.h.msgh_size = uint32(unsafe.Sizeof(*tx)) - tx.h.msgh_remote_port = mach_task_self() - tx.h.msgh_id = tmach_semcreate - tx.ndr = zerondr - - tx.policy = 0 // 0 = SYNC_POLICY_FIFO - tx.value = 0 - - for { - r := machcall(&tx.h, int32(unsafe.Sizeof(m)), int32(unsafe.Sizeof(*rx))) - if r == 0 { - break - } - if r == _KERN_ABORTED { // interrupted - continue - } - macherror(r, "semaphore_create") - } - if rx.body.msgh_descriptor_count != 1 { - unimplemented("mach_semcreate desc count") - } - return rx.semaphore.name -} - -func mach_semdestroy(sem uint32) { - var m [256]uint8 - tx := (*tmach_semdestroymsg)(unsafe.Pointer(&m)) - - tx.h.msgh_bits = _MACH_MSGH_BITS_COMPLEX - tx.h.msgh_size = uint32(unsafe.Sizeof(*tx)) - tx.h.msgh_remote_port = mach_task_self() - tx.h.msgh_id = tmach_semdestroy - tx.body.msgh_descriptor_count = 1 - tx.semaphore.name = sem - tx.semaphore.disposition = _MACH_MSG_TYPE_MOVE_SEND - tx.semaphore._type = 0 - - for { - r := machcall(&tx.h, int32(unsafe.Sizeof(m)), 0) - if r == 0 { - break - } - if r == _KERN_ABORTED { // interrupted - continue - } - macherror(r, "semaphore_destroy") - } -} - -// The other calls have simple system call traps in sys_darwin_{amd64,386}.s - -func mach_semaphore_wait(sema uint32) int32 -func mach_semaphore_timedwait(sema, sec, nsec uint32) int32 -func mach_semaphore_signal(sema uint32) int32 -func mach_semaphore_signal_all(sema uint32) int32 - -func semasleep1(ns int64) int32 { - _g_ := getg() - - if ns >= 0 { - var nsecs int32 - secs := timediv(ns, 1000000000, &nsecs) - r := mach_semaphore_timedwait(_g_.m.waitsema, uint32(secs), uint32(nsecs)) - if r == _KERN_ABORTED || r == _KERN_OPERATION_TIMED_OUT { - return -1 - } - if r != 0 { - macherror(r, "semaphore_wait") - } - return 0 - } - - for { - r := mach_semaphore_wait(_g_.m.waitsema) - if r == 0 { - break - } - // Note: We don't know how this call (with no timeout) can get _KERN_OPERATION_TIMED_OUT, - // but it does reliably, though at a very low rate, on OS X 10.8, 10.9, 10.10, and 10.11. - // See golang.org/issue/17161. - if r == _KERN_ABORTED || r == _KERN_OPERATION_TIMED_OUT { // interrupted - continue - } - macherror(r, "semaphore_wait") - } - return 0 -} - -//go:nosplit -func semasleep(ns int64) int32 { - var r int32 - systemstack(func() { - r = semasleep1(ns) - }) - return r -} - -//go:nosplit -func mach_semrelease(sem uint32) { - for { - r := mach_semaphore_signal(sem) - if r == 0 { - break - } - if r == _KERN_ABORTED { // interrupted - continue - } - - // mach_semrelease must be completely nosplit, - // because it is called from Go code. - // If we're going to die, start that process on the system stack - // to avoid a Go stack split. - systemstack(func() { macherror(r, "semaphore_signal") }) - } -} - -//go:nosplit -func osyield() { - usleep(1) -} - -const ( - _NSIG = 32 - _SI_USER = 0 /* empirically true, but not what headers say */ - _SIG_BLOCK = 1 - _SIG_UNBLOCK = 2 - _SIG_SETMASK = 3 - _SS_DISABLE = 4 -) - -//go:noescape -func sigprocmask(how int32, new, old *sigset) - -//go:noescape -func sigaction(mode uint32, new *sigactiont, old *usigactiont) - -//go:noescape -func sigaltstack(new, old *stackt) - -// darwin/arm64 uses registers instead of stack-based arguments. -// TODO: does this matter? -func sigtramp(fn uintptr, infostyle, sig uint32, info *siginfo, ctx unsafe.Pointer) - -//go:noescape -func setitimer(mode int32, new, old *itimerval) - -func raise(sig uint32) -func raiseproc(sig uint32) - -//extern SigTabTT runtime·sigtab[]; - -type sigset uint32 - -var sigset_all = ^sigset(0) - -//go:nosplit -//go:nowritebarrierrec -func setsig(i uint32, fn uintptr) { - var sa sigactiont - sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK | _SA_RESTART - sa.sa_mask = ^uint32(0) - sa.sa_tramp = unsafe.Pointer(funcPC(sigtramp)) // runtime·sigtramp's job is to call into real handler - *(*uintptr)(unsafe.Pointer(&sa.__sigaction_u)) = fn - sigaction(i, &sa, nil) -} - -//go:nosplit -//go:nowritebarrierrec -func setsigstack(i uint32) { - var osa usigactiont - sigaction(i, nil, &osa) - handler := *(*uintptr)(unsafe.Pointer(&osa.__sigaction_u)) - if osa.sa_flags&_SA_ONSTACK != 0 { - return - } - var sa sigactiont - *(*uintptr)(unsafe.Pointer(&sa.__sigaction_u)) = handler - sa.sa_tramp = unsafe.Pointer(funcPC(sigtramp)) - sa.sa_mask = osa.sa_mask - sa.sa_flags = osa.sa_flags | _SA_ONSTACK - sigaction(i, &sa, nil) -} - -//go:nosplit -//go:nowritebarrierrec -func getsig(i uint32) uintptr { - var sa usigactiont - sigaction(i, nil, &sa) - return *(*uintptr)(unsafe.Pointer(&sa.__sigaction_u)) -} - -// setSignaltstackSP sets the ss_sp field of a stackt. -//go:nosplit -func setSignalstackSP(s *stackt, sp uintptr) { - *(*uintptr)(unsafe.Pointer(&s.ss_sp)) = sp -} - -//go:nosplit -//go:nowritebarrierrec -func sigaddset(mask *sigset, i int) { - *mask |= 1 << (uint32(i) - 1) -} - -func sigdelset(mask *sigset, i int) { - *mask &^= 1 << (uint32(i) - 1) -} - -//go:linkname executablePath os.executablePath -var executablePath string - -func sysargs(argc int32, argv **byte) { - // skip over argv, envv and the first string will be the path - n := argc + 1 - for argv_index(argv, n) != nil { - n++ - } - executablePath = gostringnocopy(argv_index(argv, n+1)) - - // strip "executable_path=" prefix if available, it's added after OS X 10.11. - const prefix = "executable_path=" - if len(executablePath) > len(prefix) && executablePath[:len(prefix)] == prefix { - executablePath = executablePath[len(prefix):] - } -} diff --git a/src/runtime/proc.go b/src/runtime/proc.go index 6d4da3432a..e22432f8ed 100644 --- a/src/runtime/proc.go +++ b/src/runtime/proc.go @@ -1201,7 +1201,7 @@ func mstart() { mstart1() // Exit this thread. - if GOOS == "windows" || GOOS == "solaris" || GOOS == "plan9" || (GOOS == "darwin" && (GOARCH == "amd64" || GOARCH == "386")) { + if GOOS == "windows" || GOOS == "solaris" || GOOS == "plan9" || GOOS == "darwin" { // Window, Solaris, Darwin and Plan 9 always system-allocate // the stack, but put it in _g_.stack before mstart, // so the logic above hasn't set osStack yet. @@ -1525,7 +1525,7 @@ func allocm(_p_ *p, fn func()) *m { // In case of cgo or Solaris or Darwin, pthread_create will make us a stack. // Windows and Plan 9 will layout sched stack on OS stack. - if iscgo || GOOS == "solaris" || GOOS == "windows" || GOOS == "plan9" || (GOOS == "darwin" && (GOARCH == "386" || GOARCH == "amd64")) { + if iscgo || GOOS == "solaris" || GOOS == "windows" || GOOS == "plan9" || GOOS == "darwin" { mp.g0 = malg(-1) } else { mp.g0 = malg(8192 * sys.StackGuardMultiplier) diff --git a/src/runtime/stubs2.go b/src/runtime/stubs2.go index 2ebcd82cfd..02249d0aad 100644 --- a/src/runtime/stubs2.go +++ b/src/runtime/stubs2.go @@ -7,8 +7,7 @@ // +build !windows // +build !nacl // +build !js -// +build !darwin !amd64 -// +build !darwin !386 +// +build !darwin package runtime diff --git a/src/runtime/stubs4.go b/src/runtime/stubs4.go deleted file mode 100644 index ad0e48e455..0000000000 --- a/src/runtime/stubs4.go +++ /dev/null @@ -1,9 +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,arm darwin,arm64 - -package runtime - -func nanotime() int64 diff --git a/src/runtime/sys_darwin.go b/src/runtime/sys_darwin.go index c2df8a6f1a..57790c140c 100644 --- a/src/runtime/sys_darwin.go +++ b/src/runtime/sys_darwin.go @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build darwin,386 darwin,amd64 - package runtime import "unsafe" diff --git a/src/runtime/sys_darwin_arm.s b/src/runtime/sys_darwin_arm.s index 59b5f46a17..fcbcdbc42c 100644 --- a/src/runtime/sys_darwin_arm.s +++ b/src/runtime/sys_darwin_arm.s @@ -11,27 +11,14 @@ #include "textflag.h" // Copied from /usr/include/sys/syscall.h -#define SYS_exit 1 -#define SYS_read 3 -#define SYS_write 4 -#define SYS_open 5 -#define SYS_close 6 -#define SYS_mmap 197 -#define SYS_munmap 73 -#define SYS_madvise 75 #define SYS_gettimeofday 116 #define SYS_kill 37 #define SYS_getpid 20 -#define SYS___pthread_kill 328 #define SYS_pthread_sigmask 329 #define SYS_setitimer 83 #define SYS___sysctl 202 #define SYS_sigaction 46 #define SYS_sigreturn 184 -#define SYS_select 93 -#define SYS_bsdthread_register 366 -#define SYS_bsdthread_create 360 -#define SYS_bsdthread_terminate 361 #define SYS_kqueue 362 #define SYS_kevent 363 #define SYS_fcntl 92 @@ -41,85 +28,39 @@ TEXT notok<>(SB),NOSPLIT,$0 MOVW R8, (R8) B 0(PC) -TEXT runtime·open(SB),NOSPLIT,$0 - MOVW name+0(FP), R0 - MOVW mode+4(FP), R1 - MOVW perm+8(FP), R2 - MOVW $SYS_open, R12 - SWI $0x80 - MOVW.CS $-1, R0 - MOVW R0, ret+12(FP) +TEXT runtime·open_trampoline(SB),NOSPLIT,$0 + MOVW 4(R0), R1 // arg 2 mode + MOVW 8(R0), R2 // arg 3 perm + MOVW 0(R0), R0 // arg 1 name + BL libc_open(SB) RET -TEXT runtime·closefd(SB),NOSPLIT,$0 - MOVW fd+0(FP), R0 - MOVW $SYS_close, R12 - SWI $0x80 - MOVW.CS $-1, R0 - MOVW R0, ret+4(FP) +TEXT runtime·close_trampoline(SB),NOSPLIT,$0 + MOVW 0(R0), R0 // arg 1 fd + BL libc_close(SB) RET -TEXT runtime·write(SB),NOSPLIT,$0 - MOVW fd+0(FP), R0 - MOVW p+4(FP), R1 - MOVW n+8(FP), R2 - MOVW $SYS_write, R12 - SWI $0x80 - MOVW.CS $-1, R0 - MOVW R0, ret+12(FP) +TEXT runtime·write_trampoline(SB),NOSPLIT,$0 + MOVW 4(R0), R1 // arg 2 buf + MOVW 8(R0), R2 // arg 3 count + MOVW 0(R0), R0 // arg 1 fd + BL libc_write(SB) RET -TEXT runtime·read(SB),NOSPLIT,$0 - MOVW fd+0(FP), R0 - MOVW p+4(FP), R1 - MOVW n+8(FP), R2 - MOVW $SYS_read, R12 - SWI $0x80 - MOVW.CS $-1, R0 - MOVW R0, ret+12(FP) +TEXT runtime·read_trampoline(SB),NOSPLIT,$0 + MOVW 4(R0), R1 // arg 2 buf + MOVW 8(R0), R2 // arg 3 count + MOVW 0(R0), R0 // arg 1 fd + BL libc_read(SB) RET -TEXT runtime·exit(SB),NOSPLIT|NOFRAME,$0 - MOVW code+0(FP), R0 - MOVW $SYS_exit, R12 - SWI $0x80 +TEXT runtime·exit_trampoline(SB),NOSPLIT|NOFRAME,$0 + MOVW 0(R0), R0 // arg 0 code + BL libc_exit(SB) MOVW $1234, R0 MOVW $1002, R1 MOVW R0, (R1) // fail hard -// Exit this OS thread (like pthread_exit, which eventually -// calls __bsdthread_terminate). -TEXT exit1<>(SB),NOSPLIT,$0 - // Because of exitThread below, this must not use the stack. - // __bsdthread_terminate takes 4 word-size arguments. - // Set them all to 0. (None are an exit status.) - MOVW $0, R0 - MOVW $0, R1 - MOVW $0, R2 - MOVW $0, R3 - MOVW $SYS_bsdthread_terminate, R12 - SWI $0x80 - MOVW $1234, R0 - MOVW $1003, R1 - MOVW R0, (R1) // fail hard - -// func exitThread(wait *uint32) -TEXT runtime·exitThread(SB),NOSPLIT,$0-4 - MOVW wait+0(FP), R0 - // We're done using the stack. - MOVW $0, R2 -storeloop: - LDREX (R0), R4 // loads R4 - STREX R2, (R0), R1 // stores R2 - CMP $0, R1 - BNE storeloop - JMP exit1<>(SB) - -TEXT runtime·raise(SB),NOSPLIT,$0 - // Ideally we'd send the signal to the current thread, - // not the whole process, but that's too hard on OS X. - JMP runtime·raiseproc(SB) - TEXT runtime·raiseproc(SB),NOSPLIT,$24 MOVW $SYS_getpid, R12 SWI $0x80 @@ -130,41 +71,49 @@ TEXT runtime·raiseproc(SB),NOSPLIT,$24 SWI $0x80 RET -TEXT runtime·mmap(SB),NOSPLIT,$0 - MOVW addr+0(FP), R0 - MOVW n+4(FP), R1 - MOVW prot+8(FP), R2 - MOVW flags+12(FP), R3 - MOVW fd+16(FP), R4 - MOVW off+20(FP), R5 - MOVW $0, R6 // off_t is uint64_t - MOVW $SYS_mmap, R12 - SWI $0x80 +TEXT runtime·mmap_trampoline(SB),NOSPLIT,$0 + MOVW R0, R8 + MOVW 0(R8), R0 // arg 1 addr + MOVW 4(R8), R1 // arg 2 len + MOVW 8(R8), R2 // arg 3 prot + MOVW 12(R8), R3 // arg 4 flags + MOVW 16(R8), R4 // arg 5 fid + MOVW 20(R8), R5 // arg 6 offset + MOVW $0, R6 // off_t is uint64_t + // Only R0-R3 are used for arguments, the rest + // go on the stack. + MOVM.DB.W [R4-R6], (R13) + BL libc_mmap(SB) + ADD $12, R13 MOVW $0, R1 - BCC ok - MOVW R1, p+24(FP) - MOVW R0, err+28(FP) - RET + MOVW $-1, R2 + CMP R0, R2 + BNE ok + BL libc_error(SB) + MOVW (R0), R1 + MOVW $0, R0 ok: - MOVW R0, p+24(FP) - MOVW R1, err+28(FP) + MOVW R0, 24(R8) // ret 1 addr + MOVW R1, 28(R8) // ret 2 err RET -TEXT runtime·munmap(SB),NOSPLIT,$0 - MOVW addr+0(FP), R0 - MOVW n+4(FP), R1 - MOVW $SYS_munmap, R12 - SWI $0x80 - BL.CS notok<>(SB) +TEXT runtime·munmap_trampoline(SB),NOSPLIT,$0 + MOVW 4(R0), R1 // arg 2 len + MOVW 0(R0), R0 // arg 1 addr + BL libc_munmap(SB) + MOVW $-1, R2 + CMP R0, R2 + BL.EQ notok<>(SB) RET -TEXT runtime·madvise(SB),NOSPLIT,$0 - MOVW addr+0(FP), R0 - MOVW n+4(FP), R1 - MOVW flags+8(FP), R2 - MOVW $SYS_madvise, R12 - SWI $0x80 - BL.CS notok<>(SB) +TEXT runtime·madvise_trampoline(SB),NOSPLIT,$0 + MOVW 4(R0), R1 // arg 2 len + MOVW 8(R0), R2 // arg 3 advice + MOVW 0(R0), R0 // arg 1 addr + BL libc_madvise(SB) + MOVW $-1, R2 + CMP R0, R2 + BL.EQ notok<>(SB) RET TEXT runtime·setitimer(SB),NOSPLIT,$0 @@ -195,28 +144,36 @@ inreg: MOVW R2, nsec+8(FP) RET -TEXT runtime·nanotime(SB),NOSPLIT,$32 - MOVW $8(R13), R0 // timeval - MOVW $0, R1 // zone - MOVW $0, R2 // see issue 16570 - MOVW $SYS_gettimeofday, R12 - SWI $0x80 // Note: R0 is tv_sec, R1 is tv_usec - CMP $0, R0 - BNE inreg - MOVW 8(R13), R0 - MOVW 12(R13), R1 -inreg: - MOVW R1, R2 - MOVW $1000000000, R3 - MULLU R0, R3, (R1, R0) - MOVW $1000, R3 - MOVW $0, R4 - MUL R3, R2 - ADD.S R2, R0 - ADC R4, R1 +GLOBL timebase<>(SB),NOPTR,$(machTimebaseInfo__size) - MOVW R0, ret_lo+0(FP) - MOVW R1, ret_hi+4(FP) +TEXT runtime·nanotime_trampoline(SB),NOSPLIT,$0 + MOVW R0, R8 + BL libc_mach_absolute_time(SB) + MOVW R0, 0(R8) + MOVW R1, 4(R8) + MOVW timebase<>+machTimebaseInfo_numer(SB), R6 + MOVW $timebase<>+machTimebaseInfo_denom(SB), R5 + MOVW (R5), R7 + DMB MB_ISH // memory barrier for atomic read + CMP $0, R7 + BNE initialized + + SUB $(machTimebaseInfo__size+7)/8*8, R13 + MOVW R13, R0 + BL libc_mach_timebase_info(SB) + MOVW machTimebaseInfo_numer(R13), R6 + MOVW machTimebaseInfo_denom(R13), R7 + ADD $(machTimebaseInfo__size+7)/8*8, R13 + + MOVW R6, timebase<>+machTimebaseInfo_numer(SB) + MOVW $timebase<>+machTimebaseInfo_denom(SB), R5 + DMB MB_ISH // memory barrier for atomic write + MOVW R7, (R5) + DMB MB_ISH + +initialized: + MOVW R6, 8(R8) + MOVW R7, 12(R8) RET TEXT runtime·sigfwd(SB),NOSPLIT,$0-16 @@ -318,20 +275,9 @@ TEXT runtime·sigaction(SB),NOSPLIT,$0 SWI $0x80 RET -TEXT runtime·usleep(SB),NOSPLIT,$12 - MOVW usec+0(FP), R0 - CALL runtime·usplitR0(SB) - MOVW R0, a-12(SP) - MOVW R1, b-8(SP) - - // select(0, 0, 0, 0, &tv) - MOVW $0, R0 - MOVW $0, R1 - MOVW $0, R2 - MOVW $0, R3 - MOVW $a-12(SP), R4 - MOVW $SYS_select, R12 - SWI $0x80 +TEXT runtime·usleep_trampoline(SB),NOSPLIT,$0 + MOVW 0(R0), R0 // arg 1 usec + BL libc_usleep(SB) RET TEXT ·publicationBarrier(SB),NOSPLIT|NOFRAME,$0-0 @@ -355,65 +301,6 @@ sysctl_ret: MOVW R0, ret+24(FP) RET -// Thread related functions -// func bsdthread_create(stk, arg unsafe.Pointer, fn uintptr) int32 -TEXT runtime·bsdthread_create(SB),NOSPLIT,$0 - // Set up arguments to bsdthread_create system call. - // The ones in quotes pass through to the thread callback - // uninterpreted, so we can put whatever we want there. - MOVW fn+8(FP), R0 // "func" - MOVW arg+4(FP), R1 // "arg" - MOVW stk+0(FP), R2 // stack - MOVW $0x01000000, R4 // flags = PTHREAD_START_CUSTOM - MOVW $0, R5 // paranoia - MOVW $SYS_bsdthread_create, R12 - SWI $0x80 - BCC create_ret - RSB $0, R0, R0 - MOVW R0, ret+12(FP) - RET -create_ret: - MOVW $0, R0 - MOVW R0, ret+12(FP) - RET - -// The thread that bsdthread_create creates starts executing here, -// because we registered this function using bsdthread_register -// at startup. -// R0 = "pthread" -// R1 = mach thread port -// R2 = "func" (= fn) -// R3 = "arg" (= m) -// R4 = stack -// R5 = flags (= 0) -// XXX: how to deal with R4/SP? ref: Libc-594.9.1/arm/pthreads/thread_start.s -TEXT runtime·bsdthread_start(SB),NOSPLIT,$0 - MOVW R1, m_procid(R3) // thread port is m->procid - MOVW m_g0(R3), g - MOVW R3, g_m(g) - // ARM don't have runtime·stackcheck(SB) - // disable runfast mode of vfp - EOR R12, R12 - WORD $0xeee1ca10 // fmxr fpscr, ip - BL (R2) // fn - BL exit1<>(SB) - RET - -// int32 bsdthread_register(void) -// registers callbacks for threadstart (see bsdthread_create above -// and wqthread and pthsize (not used). returns 0 on success. -TEXT runtime·bsdthread_register(SB),NOSPLIT,$0 - MOVW $runtime·bsdthread_start(SB), R0 // threadstart - MOVW $0, R1 // wqthread, not used by us - MOVW $0, R2 // pthsize, not used by us - MOVW $0, R3 // dummy_value [sic] - MOVW $0, R4 // targetconc_ptr - MOVW $0, R5 // dispatchqueue_offset - MOVW $SYS_bsdthread_register, R12 // bsdthread_register - SWI $0x80 - MOVW R0, ret+0(FP) - RET - // uint32 mach_msg_trap(void*, uint32, uint32, uint32, uint32, uint32, uint32) TEXT runtime·mach_msg_trap(SB),NOSPLIT,$0 MOVW h+0(FP), R0 @@ -519,3 +406,38 @@ TEXT runtime·closeonexec(SB),NOSPLIT,$0 // to do the stack switch ourselves. TEXT runtime·sigaltstack(SB),NOSPLIT,$0 RET + +// Thread related functions +// Note: On darwin/arm, the runtime always use runtime/cgo to +// create threads, so all thread related functions will just exit with a +// unique status. + +TEXT runtime·mstart_stub(SB),NOSPLIT,$0 + MOVW $44, R0 + BL libc_exit(SB) + RET + +TEXT runtime·pthread_attr_init_trampoline(SB),NOSPLIT,$0 + MOVW $45, R0 + BL libc_exit(SB) + RET + +TEXT runtime·pthread_attr_setstacksize_trampoline(SB),NOSPLIT,$0 + MOVW $46, R0 + BL libc_exit(SB) + RET + +TEXT runtime·pthread_attr_setdetachstate_trampoline(SB),NOSPLIT,$0 + MOVW $47, R0 + BL libc_exit(SB) + RET + +TEXT runtime·pthread_create_trampoline(SB),NOSPLIT,$0 + MOVW $48, R0 + BL libc_exit(SB) + RET + +TEXT runtime·raise_trampoline(SB),NOSPLIT,$0 + MOVW 0(R0), R0 // arg 1 sig + BL libc_raise(SB) + RET diff --git a/src/runtime/sys_darwin_arm64.s b/src/runtime/sys_darwin_arm64.s index 831e6dd2fc..f0d9032a60 100644 --- a/src/runtime/sys_darwin_arm64.s +++ b/src/runtime/sys_darwin_arm64.s @@ -11,27 +11,14 @@ #include "textflag.h" // Copied from /usr/include/sys/syscall.h -#define SYS_exit 1 -#define SYS_read 3 -#define SYS_write 4 -#define SYS_open 5 -#define SYS_close 6 -#define SYS_mmap 197 -#define SYS_munmap 73 -#define SYS_madvise 75 #define SYS_gettimeofday 116 #define SYS_kill 37 #define SYS_getpid 20 -#define SYS___pthread_kill 328 #define SYS_pthread_sigmask 329 #define SYS_setitimer 83 #define SYS___sysctl 202 #define SYS_sigaction 46 #define SYS_sigreturn 184 -#define SYS_select 93 -#define SYS_bsdthread_register 366 -#define SYS_bsdthread_create 360 -#define SYS_bsdthread_terminate 361 #define SYS_kqueue 362 #define SYS_kevent 363 #define SYS_fcntl 92 @@ -41,81 +28,39 @@ TEXT notok<>(SB),NOSPLIT,$0 MOVD R8, (R8) B 0(PC) -TEXT runtime·open(SB),NOSPLIT,$0 - MOVD name+0(FP), R0 - MOVW mode+8(FP), R1 - MOVW perm+12(FP), R2 - MOVD $SYS_open, R16 - SVC $0x80 - CSINV LO, R0, ZR, R0 - MOVW R0, ret+16(FP) +TEXT runtime·open_trampoline(SB),NOSPLIT,$0 + MOVW 8(R0), R1 // arg 2 flags + MOVW 12(R0), R2 // arg 3 mode + MOVD 0(R0), R0 // arg 1 pathname + BL libc_open(SB) RET -TEXT runtime·closefd(SB),NOSPLIT,$0 - MOVW fd+0(FP), R0 - MOVW $SYS_close, R16 - SVC $0x80 - CSINV LO, R0, ZR, R0 - MOVW R0, ret+8(FP) +TEXT runtime·close_trampoline(SB),NOSPLIT,$0 + MOVW 0(R0), R0 // arg 1 fd + BL libc_close(SB) RET -TEXT runtime·write(SB),NOSPLIT,$0 - MOVW fd+0(FP), R0 - MOVD p+8(FP), R1 - MOVW n+16(FP), R2 - MOVW $SYS_write, R16 - SVC $0x80 - CSINV LO, R0, ZR, R0 - MOVW R0, ret+24(FP) +TEXT runtime·write_trampoline(SB),NOSPLIT,$0 + MOVD 8(R0), R1 // arg 2 buf + MOVW 16(R0), R2 // arg 3 count + MOVW 0(R0), R0 // arg 1 fd + BL libc_write(SB) RET -TEXT runtime·read(SB),NOSPLIT,$0 - MOVW fd+0(FP), R0 - MOVD p+8(FP), R1 - MOVW n+16(FP), R2 - MOVW $SYS_read, R16 - SVC $0x80 - CSINV LO, R0, ZR, R0 - MOVW R0, ret+24(FP) +TEXT runtime·read_trampoline(SB),NOSPLIT,$0 + MOVD 8(R0), R1 // arg 2 buf + MOVW 16(R0), R2 // arg 3 count + MOVW 0(R0), R0 // arg 1 fd + BL libc_read(SB) RET -TEXT runtime·exit(SB),NOSPLIT|NOFRAME,$0 - MOVW code+0(FP), R0 - MOVW $SYS_exit, R16 - SVC $0x80 +TEXT runtime·exit_trampoline(SB),NOSPLIT|NOFRAME,$0 + MOVW 0(R0), R0 + BL libc_exit(SB) MOVD $1234, R0 MOVD $1002, R1 MOVD R0, (R1) // fail hard -// Exit this OS thread (like pthread_exit, which eventually -// calls __bsdthread_terminate). -TEXT exit1<>(SB),NOSPLIT,$0 - // Because of exitThread below, this must not use the stack. - // __bsdthread_terminate takes 4 word-size arguments. - // Set them all to 0. (None are an exit status.) - MOVW $0, R0 - MOVW $0, R1 - MOVW $0, R2 - MOVW $0, R3 - MOVW $SYS_bsdthread_terminate, R16 - SVC $0x80 - MOVD $1234, R0 - MOVD $1003, R1 - MOVD R0, (R1) // fail hard - -// func exitThread(wait *uint32) -TEXT runtime·exitThread(SB),NOSPLIT,$0-8 - MOVD wait+0(FP), R0 - // We're done using the stack. - MOVW $0, R1 - STLRW R1, (R0) - JMP exit1<>(SB) - -TEXT runtime·raise(SB),NOSPLIT,$0 - // Ideally we'd send the signal to the current thread, - // not the whole process, but that's too hard on OS X. - JMP runtime·raiseproc(SB) - TEXT runtime·raiseproc(SB),NOSPLIT,$0 MOVW $SYS_getpid, R16 SVC $0x80 @@ -126,41 +71,41 @@ TEXT runtime·raiseproc(SB),NOSPLIT,$0 SVC $0x80 RET -TEXT runtime·mmap(SB),NOSPLIT,$0 - MOVD addr+0(FP), R0 - MOVD n+8(FP), R1 - MOVW prot+16(FP), R2 - MOVW flags+20(FP), R3 - MOVW fd+24(FP), R4 - MOVW off+28(FP), R5 - MOVW $SYS_mmap, R16 - SVC $0x80 - BCC ok - MOVD $0, p+32(FP) - MOVD R0, err+40(FP) - RET +TEXT runtime·mmap_trampoline(SB),NOSPLIT,$0 + MOVD R0, R19 + MOVD 0(R19), R0 // arg 1 addr + MOVD 8(R19), R1 // arg 2 len + MOVW 16(R19), R2 // arg 3 prot + MOVW 20(R19), R3 // arg 4 flags + MOVW 24(R19), R4 // arg 5 fd + MOVW 28(R19), R5 // arg 6 off + BL libc_mmap(SB) + MOVD $0, R1 + MOVD $-1, R2 + CMP R0, R2 + BNE ok + BL libc_error(SB) + MOVD (R0), R1 + MOVD $0, R0 ok: - MOVD R0, p+32(FP) - MOVD $0, err+40(FP) + MOVD R0, 32(R19) // ret 1 p + MOVD R1, 40(R19) // ret 2 err RET -TEXT runtime·munmap(SB),NOSPLIT,$0 - MOVD addr+0(FP), R0 - MOVD n+8(FP), R1 - MOVW $SYS_munmap, R16 - SVC $0x80 - BCC 2(PC) +TEXT runtime·munmap_trampoline(SB),NOSPLIT,$0 + MOVD 8(R0), R1 // arg 2 len + MOVD 0(R0), R0 // arg 1 addr + BL libc_munmap(SB) + CMP $0, R0 + BEQ 2(PC) BL notok<>(SB) RET -TEXT runtime·madvise(SB),NOSPLIT,$0 - MOVD addr+0(FP), R0 - MOVD n+8(FP), R1 - MOVW flags+16(FP), R2 - MOVW $SYS_madvise, R16 - SVC $0x80 - BCC 2(PC) - BL notok<>(SB) +TEXT runtime·madvise_trampoline(SB),NOSPLIT,$0 + MOVD 8(R0), R1 // arg 2 len + MOVW 16(R0), R2 // arg 3 advice + MOVD 0(R0), R0 // arg 1 addr + BL libc_madvise(SB) RET TEXT runtime·setitimer(SB),NOSPLIT,$0 @@ -189,25 +134,32 @@ inreg: MOVW R1, nsec+8(FP) RET -TEXT runtime·nanotime(SB),NOSPLIT,$40 - MOVD RSP, R0 // timeval - MOVD R0, R9 // this is how dyld calls gettimeofday - MOVW $0, R1 // zone - MOVD $0, R2 // see issue 16570 - MOVW $SYS_gettimeofday, R16 - SVC $0x80 // Note: x0 is tv_sec, w1 is tv_usec - CMP $0, R0 - BNE inreg - MOVD 0(RSP), R0 - MOVW 8(RSP), R1 -inreg: - MOVW $1000000000, R3 - MUL R3, R0 - MOVW $1000, R3 - MUL R3, R1 - ADD R1, R0 +GLOBL timebase<>(SB),NOPTR,$(machTimebaseInfo__size) - MOVD R0, ret+0(FP) +TEXT runtime·nanotime_trampoline(SB),NOSPLIT,$40 + MOVD R0, R19 + BL libc_mach_absolute_time(SB) + MOVD R0, 0(R19) + MOVW timebase<>+machTimebaseInfo_numer(SB), R20 + MOVD $timebase<>+machTimebaseInfo_denom(SB), R21 + LDARW (R21), R21 // atomic read + CMP $0, R21 + BNE initialized + + SUB $(machTimebaseInfo__size+15)/16*16, RSP + MOVD RSP, R0 + BL libc_mach_timebase_info(SB) + MOVW machTimebaseInfo_numer(RSP), R20 + MOVW machTimebaseInfo_denom(RSP), R21 + ADD $(machTimebaseInfo__size+15)/16*16, RSP + + MOVW R20, timebase<>+machTimebaseInfo_numer(SB) + MOVD $timebase<>+machTimebaseInfo_denom(SB), R22 + STLRW R21, (R22) // atomic write + +initialized: + MOVW R20, 8(R19) + MOVW R21, 12(R19) RET TEXT runtime·sigfwd(SB),NOSPLIT,$0-32 @@ -310,24 +262,9 @@ TEXT runtime·sigaction(SB),NOSPLIT,$0 BL notok<>(SB) RET -TEXT runtime·usleep(SB),NOSPLIT,$24 - MOVW usec+0(FP), R0 - MOVW R0, R1 - MOVW $1000000, R2 - UDIV R2, R0 - MUL R0, R2 - SUB R2, R1 - MOVD R0, 0(RSP) - MOVW R1, 8(RSP) - - // select(0, 0, 0, 0, &tv) - MOVW $0, R0 - MOVW $0, R1 - MOVW $0, R2 - MOVW $0, R3 - MOVD RSP, R4 - MOVW $SYS_select, R16 - SVC $0x80 +TEXT runtime·usleep_trampoline(SB),NOSPLIT,$0 + MOVW 0(R0), R0 // arg 1 usec + BL libc_usleep(SB) RET TEXT runtime·sysctl(SB),NOSPLIT,$0 @@ -348,42 +285,6 @@ ok: MOVW R0, ret+48(FP) RET -// Thread related functions -// Note: On darwin/arm64, it is no longer possible to use bsdthread_register -// as the libc is always linked in. The runtime must use runtime/cgo to -// create threads, so all thread related functions will just exit with a -// unique status. -// void bsdthread_create(void *stk, M *m, G *g, void (*fn)(void)) -TEXT runtime·bsdthread_create(SB),NOSPLIT,$0 - MOVD $44, R0 - MOVW $SYS_exit, R16 - SVC $0x80 - RET - -// The thread that bsdthread_create creates starts executing here, -// because we registered this function using bsdthread_register -// at startup. -// R0 = "pthread" -// R1 = mach thread port -// R2 = "func" (= fn) -// R3 = "arg" (= m) -// R4 = stack -// R5 = flags (= 0) -TEXT runtime·bsdthread_start(SB),NOSPLIT,$0 - MOVD $45, R0 - MOVW $SYS_exit, R16 - SVC $0x80 - RET - -// int32 bsdthread_register(void) -// registers callbacks for threadstart (see bsdthread_create above -// and wqthread and pthsize (not used). returns 0 on success. -TEXT runtime·bsdthread_register(SB),NOSPLIT,$0 - MOVD $46, R0 - MOVW $SYS_exit, R16 - SVC $0x80 - RET - // uint32 mach_msg_trap(void*, uint32, uint32, uint32, uint32, uint32, uint32) TEXT runtime·mach_msg_trap(SB),NOSPLIT,$0 MOVD h+0(FP), R0 @@ -491,3 +392,38 @@ TEXT runtime·closeonexec(SB),NOSPLIT,$0 // to do the stack switch ourselves. TEXT runtime·sigaltstack(SB),NOSPLIT,$0 RET + +// Thread related functions +// Note: On darwin/arm64, the runtime always use runtime/cgo to +// create threads, so all thread related functions will just exit with a +// unique status. + +TEXT runtime·mstart_stub(SB),NOSPLIT,$0 + MOVW $44, R0 + BL libc_exit(SB) + RET + +TEXT runtime·pthread_attr_init_trampoline(SB),NOSPLIT,$0 + MOVW $45, R0 + BL libc_exit(SB) + RET + +TEXT runtime·pthread_attr_setstacksize_trampoline(SB),NOSPLIT,$0 + MOVW $46, R0 + BL libc_exit(SB) + RET + +TEXT runtime·pthread_attr_setdetachstate_trampoline(SB),NOSPLIT,$0 + MOVW $47, R0 + BL libc_exit(SB) + RET + +TEXT runtime·pthread_create_trampoline(SB),NOSPLIT,$0 + MOVW $48, R0 + BL libc_exit(SB) + RET + +TEXT runtime·raise_trampoline(SB),NOSPLIT,$0 + MOVW 0(R0), R0 // arg 1 sig + BL libc_raise(SB) + RET diff --git a/src/runtime/vlrt.go b/src/runtime/vlrt.go index d63da9c890..6d516b3afd 100644 --- a/src/runtime/vlrt.go +++ b/src/runtime/vlrt.go @@ -106,7 +106,6 @@ func _d2v(y *uint64, d float64) { *y = uint64(yhi)<<32 | uint64(ylo) } - func uint64div(n, d uint64) uint64 { // Check for 32 bit operands if uint32(n>>32) == 0 && uint32(d>>32) == 0 { @@ -131,6 +130,9 @@ func uint64mod(n, d uint64) uint64 { return r } +//go:nosplit +// nosplit because division is used in syscall context in nanotime on darwin/386 +// and darwin/arm where stack splits are not allowed. func int64div(n, d int64) int64 { // Check for 32 bit operands if int64(int32(n)) == n && int64(int32(d)) == d { @@ -191,6 +193,7 @@ func _mul64by32(lo64 *uint64, a uint64, b uint32) (hi32 uint32) //go:noescape func _div64by32(a uint64, b uint32, r *uint32) (q uint32) +//go:nosplit func dodiv(n, d uint64) (q, r uint64) { if GOARCH == "arm" { // arm doesn't have a division instruction, so @@ -234,6 +237,7 @@ func dodiv(n, d uint64) (q, r uint64) { return uint64(qhi)<<32 + uint64(qlo), uint64(rlo) } +//go:nosplit func slowdodiv(n, d uint64) (q, r uint64) { if d == 0 { panicdivide()