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)
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
}
// 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
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
// 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
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
// 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
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
X__sig int32
X__opaque [36]int8
}
+
+type machTimebaseInfo struct {
+ numer uint32
+ denom uint32
+}
X__sig int64
X__opaque [56]int8
}
+
+type machTimebaseInfo struct {
+ numer uint32
+ denom uint32
+}
// +build !linux !amd64
// +build !linux !arm64
// +build !js
-// +build !darwin !amd64
-// +build !darwin !386
+// +build !darwin
package runtime
// 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"
+++ /dev/null
-// 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):]
- }
-}
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.
// 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)
// +build !windows
// +build !nacl
// +build !js
-// +build !darwin !amd64
-// +build !darwin !386
+// +build !darwin
package runtime
+++ /dev/null
-// 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
// 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"
#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
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
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
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)
+
+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
- MOVW R0, ret_lo+0(FP)
- MOVW R1, ret_hi+4(FP)
+initialized:
+ MOVW R6, 8(R8)
+ MOVW R7, 12(R8)
RET
TEXT runtime·sigfwd(SB),NOSPLIT,$0-16
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
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
// 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
#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
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
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
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)
+
+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
- MOVD R0, ret+0(FP)
+initialized:
+ MOVW R20, 8(R19)
+ MOVW R21, 12(R19)
RET
TEXT runtime·sigfwd(SB),NOSPLIT,$0-32
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
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
// 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
*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 {
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 {
//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
return uint64(qhi)<<32 + uint64(qlo), uint64(rlo)
}
+//go:nosplit
func slowdodiv(n, d uint64) (q, r uint64) {
if d == 0 {
panicdivide()