This CL removes the last of the direct system calls in the runtime package.
This is the last CL for 1.11.
Use libcCall instead of asmcgocall in a few places I accidentally used
the wrong one.
For 1.12, we need to think about whether/how the syscall package
should be moved over to libc.
Update #17490
Change-Id: I4f0bd9cd6023f662f2e29588266fdfae5233898f
Reviewed-on: https://go-review.googlesource.com/118736
Run-TryBot: Keith Randall <khr@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
// Ok
-runtime/sys_darwin_386.s: [386] sysenter: function sysenter missing Go declaration
runtime/sys_darwin_386.s: [386] setldt: function setldt missing Go declaration
/*
#define __DARWIN_UNIX03 0
-#include <mach/mach.h>
-#include <mach/message.h>
#include <mach/mach_time.h>
#include <sys/types.h>
#include <sys/time.h>
import "C"
const (
- EINTR = C.EINTR
- EFAULT = C.EFAULT
+ EINTR = C.EINTR
+ EFAULT = C.EFAULT
+ ETIMEDOUT = C.ETIMEDOUT
PROT_NONE = C.PROT_NONE
PROT_READ = C.PROT_READ
MADV_DONTNEED = C.MADV_DONTNEED
MADV_FREE = C.MADV_FREE
- MACH_MSG_TYPE_MOVE_RECEIVE = C.MACH_MSG_TYPE_MOVE_RECEIVE
- MACH_MSG_TYPE_MOVE_SEND = C.MACH_MSG_TYPE_MOVE_SEND
- MACH_MSG_TYPE_MOVE_SEND_ONCE = C.MACH_MSG_TYPE_MOVE_SEND_ONCE
- MACH_MSG_TYPE_COPY_SEND = C.MACH_MSG_TYPE_COPY_SEND
- MACH_MSG_TYPE_MAKE_SEND = C.MACH_MSG_TYPE_MAKE_SEND
- MACH_MSG_TYPE_MAKE_SEND_ONCE = C.MACH_MSG_TYPE_MAKE_SEND_ONCE
- MACH_MSG_TYPE_COPY_RECEIVE = C.MACH_MSG_TYPE_COPY_RECEIVE
-
- MACH_MSG_PORT_DESCRIPTOR = C.MACH_MSG_PORT_DESCRIPTOR
- MACH_MSG_OOL_DESCRIPTOR = C.MACH_MSG_OOL_DESCRIPTOR
- MACH_MSG_OOL_PORTS_DESCRIPTOR = C.MACH_MSG_OOL_PORTS_DESCRIPTOR
- MACH_MSG_OOL_VOLATILE_DESCRIPTOR = C.MACH_MSG_OOL_VOLATILE_DESCRIPTOR
-
- MACH_MSGH_BITS_COMPLEX = C.MACH_MSGH_BITS_COMPLEX
-
- MACH_SEND_MSG = C.MACH_SEND_MSG
- MACH_RCV_MSG = C.MACH_RCV_MSG
- MACH_RCV_LARGE = C.MACH_RCV_LARGE
-
- MACH_SEND_TIMEOUT = C.MACH_SEND_TIMEOUT
- MACH_SEND_INTERRUPT = C.MACH_SEND_INTERRUPT
- MACH_SEND_ALWAYS = C.MACH_SEND_ALWAYS
- MACH_SEND_TRAILER = C.MACH_SEND_TRAILER
- MACH_RCV_TIMEOUT = C.MACH_RCV_TIMEOUT
- MACH_RCV_NOTIFY = C.MACH_RCV_NOTIFY
- MACH_RCV_INTERRUPT = C.MACH_RCV_INTERRUPT
- MACH_RCV_OVERWRITE = C.MACH_RCV_OVERWRITE
-
- NDR_PROTOCOL_2_0 = C.NDR_PROTOCOL_2_0
- NDR_INT_BIG_ENDIAN = C.NDR_INT_BIG_ENDIAN
- NDR_INT_LITTLE_ENDIAN = C.NDR_INT_LITTLE_ENDIAN
- NDR_FLOAT_IEEE = C.NDR_FLOAT_IEEE
- NDR_CHAR_ASCII = C.NDR_CHAR_ASCII
-
SA_SIGINFO = C.SA_SIGINFO
SA_RESTART = C.SA_RESTART
SA_ONSTACK = C.SA_ONSTACK
FD_CLOEXEC = C.FD_CLOEXEC
)
-type MachBody C.mach_msg_body_t
-type MachHeader C.mach_msg_header_t
-type MachNDR C.NDR_record_t
-type MachPort C.mach_msg_port_descriptor_t
-
type StackT C.struct_sigaltstack
type Sighandler C.union___sigaction_u
type Pthread C.pthread_t
type PthreadAttr C.pthread_attr_t
+type PthreadMutex C.pthread_mutex_t
+type PthreadMutexAttr C.pthread_mutexattr_t
+type PthreadCond C.pthread_cond_t
+type PthreadCondAttr C.pthread_condattr_t
type MachTimebaseInfo C.mach_timebase_info_data_t
import "unsafe"
const (
- _EINTR = 0x4
- _EFAULT = 0xe
+ _EINTR = 0x4
+ _EFAULT = 0xe
+ _ETIMEDOUT = 0x3c
_PROT_NONE = 0x0
_PROT_READ = 0x1
_MADV_DONTNEED = 0x4
_MADV_FREE = 0x5
- _MACH_MSG_TYPE_MOVE_RECEIVE = 0x10
- _MACH_MSG_TYPE_MOVE_SEND = 0x11
- _MACH_MSG_TYPE_MOVE_SEND_ONCE = 0x12
- _MACH_MSG_TYPE_COPY_SEND = 0x13
- _MACH_MSG_TYPE_MAKE_SEND = 0x14
- _MACH_MSG_TYPE_MAKE_SEND_ONCE = 0x15
- _MACH_MSG_TYPE_COPY_RECEIVE = 0x16
-
- _MACH_MSG_PORT_DESCRIPTOR = 0x0
- _MACH_MSG_OOL_DESCRIPTOR = 0x1
- _MACH_MSG_OOL_PORTS_DESCRIPTOR = 0x2
- _MACH_MSG_OOL_VOLATILE_DESCRIPTOR = 0x3
-
- _MACH_MSGH_BITS_COMPLEX = 0x80000000
-
- _MACH_SEND_MSG = 0x1
- _MACH_RCV_MSG = 0x2
- _MACH_RCV_LARGE = 0x4
-
- _MACH_SEND_TIMEOUT = 0x10
- _MACH_SEND_INTERRUPT = 0x40
- _MACH_SEND_ALWAYS = 0x10000
- _MACH_SEND_TRAILER = 0x20000
- _MACH_RCV_TIMEOUT = 0x100
- _MACH_RCV_NOTIFY = 0x200
- _MACH_RCV_INTERRUPT = 0x400
- _MACH_RCV_OVERWRITE = 0x1000
-
- _NDR_PROTOCOL_2_0 = 0x0
- _NDR_INT_BIG_ENDIAN = 0x0
- _NDR_INT_LITTLE_ENDIAN = 0x1
- _NDR_FLOAT_IEEE = 0x0
- _NDR_CHAR_ASCII = 0x0
-
_SA_SIGINFO = 0x40
_SA_RESTART = 0x2
_SA_ONSTACK = 0x1
_FD_CLOEXEC = 0x1
)
-type machbody struct {
- msgh_descriptor_count uint32
-}
-
-type machheader struct {
- msgh_bits uint32
- msgh_size uint32
- msgh_remote_port uint32
- msgh_local_port uint32
- msgh_reserved uint32
- msgh_id int32
-}
-
-type machndr struct {
- mig_vers uint8
- if_vers uint8
- reserved1 uint8
- mig_encoding uint8
- int_rep uint8
- char_rep uint8
- float_rep uint8
- reserved2 uint8
-}
-
-type machport struct {
- name uint32
- pad1 uint32
- pad2 uint16
- disposition uint8
- _type uint8
-}
-
type stackt struct {
ss_sp *byte
ss_size uintptr
tv_nsec int32
}
+//go:nosplit
+func (t *timespec) set_nsec(ns int64) {
+ t.tv_sec = int32(ns / 1000000000)
+ t.tv_nsec = int32(ns % 1000000000)
+}
+
type fpcontrol struct {
pad_cgo_0 [2]byte
}
X__sig int32
X__opaque [36]int8
}
+type pthreadmutex struct {
+ X__sig int32
+ X__opaque [40]int8
+}
+type pthreadmutexattr struct {
+ X__sig int32
+ X__opaque [8]int8
+}
+type pthreadcond struct {
+ X__sig int32
+ X__opaque [24]int8
+}
+type pthreadcondattr struct {
+ X__sig int32
+ X__opaque [4]int8
+}
type machTimebaseInfo struct {
numer uint32
denom uint32
import "unsafe"
const (
- _EINTR = 0x4
- _EFAULT = 0xe
+ _EINTR = 0x4
+ _EFAULT = 0xe
+ _ETIMEDOUT = 0x3c
_PROT_NONE = 0x0
_PROT_READ = 0x1
_MADV_DONTNEED = 0x4
_MADV_FREE = 0x5
- _MACH_MSG_TYPE_MOVE_RECEIVE = 0x10
- _MACH_MSG_TYPE_MOVE_SEND = 0x11
- _MACH_MSG_TYPE_MOVE_SEND_ONCE = 0x12
- _MACH_MSG_TYPE_COPY_SEND = 0x13
- _MACH_MSG_TYPE_MAKE_SEND = 0x14
- _MACH_MSG_TYPE_MAKE_SEND_ONCE = 0x15
- _MACH_MSG_TYPE_COPY_RECEIVE = 0x16
-
- _MACH_MSG_PORT_DESCRIPTOR = 0x0
- _MACH_MSG_OOL_DESCRIPTOR = 0x1
- _MACH_MSG_OOL_PORTS_DESCRIPTOR = 0x2
- _MACH_MSG_OOL_VOLATILE_DESCRIPTOR = 0x3
-
- _MACH_MSGH_BITS_COMPLEX = 0x80000000
-
- _MACH_SEND_MSG = 0x1
- _MACH_RCV_MSG = 0x2
- _MACH_RCV_LARGE = 0x4
-
- _MACH_SEND_TIMEOUT = 0x10
- _MACH_SEND_INTERRUPT = 0x40
- _MACH_SEND_ALWAYS = 0x10000
- _MACH_SEND_TRAILER = 0x20000
- _MACH_RCV_TIMEOUT = 0x100
- _MACH_RCV_NOTIFY = 0x200
- _MACH_RCV_INTERRUPT = 0x400
- _MACH_RCV_OVERWRITE = 0x1000
-
- _NDR_PROTOCOL_2_0 = 0x0
- _NDR_INT_BIG_ENDIAN = 0x0
- _NDR_INT_LITTLE_ENDIAN = 0x1
- _NDR_FLOAT_IEEE = 0x0
- _NDR_CHAR_ASCII = 0x0
-
_SA_SIGINFO = 0x40
_SA_RESTART = 0x2
_SA_ONSTACK = 0x1
_FD_CLOEXEC = 0x1
)
-type machbody struct {
- msgh_descriptor_count uint32
-}
-
-type machheader struct {
- msgh_bits uint32
- msgh_size uint32
- msgh_remote_port uint32
- msgh_local_port uint32
- msgh_reserved uint32
- msgh_id int32
-}
-
-type machndr struct {
- mig_vers uint8
- if_vers uint8
- reserved1 uint8
- mig_encoding uint8
- int_rep uint8
- char_rep uint8
- float_rep uint8
- reserved2 uint8
-}
-
-type machport struct {
- name uint32
- pad1 uint32
- pad2 uint16
- disposition uint8
- _type uint8
-}
-
type stackt struct {
ss_sp *byte
ss_size uintptr
tv_nsec int64
}
+//go:nosplit
+func (t *timespec) set_nsec(ns int64) {
+ t.tv_sec = ns / 1000000000
+ t.tv_nsec = ns % 1000000000
+}
+
type fpcontrol struct {
pad_cgo_0 [2]byte
}
X__sig int64
X__opaque [56]int8
}
+type pthreadmutex struct {
+ X__sig int64
+ X__opaque [56]int8
+}
+type pthreadmutexattr struct {
+ X__sig int64
+ X__opaque [8]int8
+}
+type pthreadcond struct {
+ X__sig int64
+ X__opaque [40]int8
+}
+type pthreadcondattr struct {
+ X__sig int64
+ X__opaque [8]int8
+}
+
type machTimebaseInfo struct {
numer uint32
denom uint32
import "unsafe"
type mOS struct {
- machport uint32 // return address for mach ipc
- waitsema uint32 // semaphore for parking on locks
+ initialized bool
+ mutex pthreadmutex
+ cond pthreadcond
+ count int
}
-//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
-
func unimplemented(name string) {
println(name, "not implemented")
*(*int)(unsafe.Pointer(uintptr(1231))) = 1231
}
//go:nosplit
-func semawakeup(mp *m) {
- mach_semrelease(mp.waitsema)
+func semacreate(mp *m) {
+ if mp.initialized {
+ return
+ }
+ mp.initialized = true
+ if err := pthread_mutex_init(&mp.mutex, nil); err != 0 {
+ throw("pthread_mutex_init")
+ }
+ if err := pthread_cond_init(&mp.cond, nil); err != 0 {
+ throw("pthread_cond_init")
+ }
}
//go:nosplit
-func semacreate(mp *m) {
- if mp.waitsema != 0 {
- return
+func semasleep(ns int64) int32 {
+ mp := getg().m
+ pthread_mutex_lock(&mp.mutex)
+ for {
+ if mp.count > 0 {
+ mp.count--
+ pthread_mutex_unlock(&mp.mutex)
+ return 0
+ }
+ if ns >= 0 {
+ var t timespec
+ t.set_nsec(ns)
+ err := pthread_cond_timedwait(&mp.cond, &mp.mutex, &t)
+ if err == _ETIMEDOUT {
+ pthread_mutex_unlock(&mp.mutex)
+ return -1
+ }
+ } else {
+ pthread_cond_wait(&mp.cond, &mp.mutex)
+ }
}
- systemstack(func() {
- mp.waitsema = mach_semcreate()
- })
+}
+
+//go:nosplit
+func semawakeup(mp *m) {
+ pthread_mutex_lock(&mp.mutex)
+ mp.count++
+ if mp.count > 0 {
+ pthread_cond_signal(&mp.cond)
+ }
+ pthread_mutex_unlock(&mp.mutex)
}
// BSD interface for threading.
}
}
-// 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)
//go:nosplit
//go:cgo_unsafe_args
func sigaction(sig uint32, new *usigactiont, old *usigactiont) {
- asmcgocall(unsafe.Pointer(funcPC(sigaction_trampoline)), unsafe.Pointer(&sig))
+ 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) {
- asmcgocall(unsafe.Pointer(funcPC(sigprocmask_trampoline)), unsafe.Pointer(&how))
+ libcCall(unsafe.Pointer(funcPC(sigprocmask_trampoline)), unsafe.Pointer(&how))
}
func sigprocmask_trampoline()
// ref: http://lists.llvm.org/pipermail/llvm-commits/Week-of-Mon-20140421/214296.html
new.ss_size = 32768
}
- asmcgocall(unsafe.Pointer(funcPC(sigaltstack_trampoline)), unsafe.Pointer(&new))
+ libcCall(unsafe.Pointer(funcPC(sigaltstack_trampoline)), unsafe.Pointer(&new))
}
func sigaltstack_trampoline()
//go:nosplit
//go:cgo_unsafe_args
func raiseproc(sig uint32) {
- asmcgocall(unsafe.Pointer(funcPC(raiseproc_trampoline)), unsafe.Pointer(&sig))
+ 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) {
- asmcgocall(unsafe.Pointer(funcPC(setitimer_trampoline)), unsafe.Pointer(&mode))
+ 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 asmcgocall(unsafe.Pointer(funcPC(sysctl_trampoline)), unsafe.Pointer(&mib))
+ 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 asmcgocall(unsafe.Pointer(funcPC(fcntl_trampoline)), unsafe.Pointer(&fd))
+ return libcCall(unsafe.Pointer(funcPC(fcntl_trampoline)), unsafe.Pointer(&fd))
}
func fcntl_trampoline()
//go:nosplit
//go:cgo_unsafe_args
func kqueue() int32 {
- v := asmcgocall(unsafe.Pointer(funcPC(kqueue_trampoline)), nil)
+ 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 asmcgocall(unsafe.Pointer(funcPC(kevent_trampoline)), unsafe.Pointer(&kq))
+ 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(c *pthreadcond, m *pthreadmutex, t *timespec) int32 {
+ return libcCall(unsafe.Pointer(funcPC(pthread_cond_timedwait_trampoline)), unsafe.Pointer(&c))
+}
+func pthread_cond_timedwait_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: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 pthread_cond_timedwait "/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/compile/internal/ld/go.go:210
//go:cgo_import_dynamic _ _ "/usr/lib/libSystem.B.dylib"
// license that can be found in the LICENSE file.
// System calls and other sys.stuff for 386, Darwin
-// See http://fxr.watson.org/fxr/source/bsd/kern/syscalls.c?v=xnu-1228
-// or /usr/include/sys/syscall.h (on a Mac) for system call numbers.
+// System calls are implemented in libSystem, this file contains
+// trampolines that convert from Go to C calling convention.
#include "go_asm.h"
#include "go_tls.h"
POPL BP
RET
-// Invoke Mach system call.
-// Assumes system call number in AX,
-// caller PC on stack, caller's caller PC next,
-// and then the system call arguments.
-//
-// Can be used for BSD too, but we don't,
-// because if you use this interface the BSD
-// system call numbers need an extra field
-// in the high 16 bits that seems to be the
-// argument count in bytes but is not always.
-// INT $0x80 works fine for those.
-TEXT runtime·sysenter(SB),NOSPLIT,$0
- POPL DX
- MOVL SP, CX
- SYSENTER
- // returns to DX with SP set to CX
-
-TEXT runtime·mach_msg_trap(SB),NOSPLIT,$0
- MOVL $-31, AX
- CALL runtime·sysenter(SB)
- MOVL AX, ret+28(FP)
- RET
-
-TEXT runtime·mach_reply_port(SB),NOSPLIT,$0
- MOVL $-26, AX
- CALL runtime·sysenter(SB)
- MOVL AX, ret+0(FP)
- RET
-
-TEXT runtime·mach_task_self(SB),NOSPLIT,$0
- MOVL $-28, AX
- CALL runtime·sysenter(SB)
- MOVL AX, ret+0(FP)
- RET
-
-// Mach provides trap versions of the semaphore ops,
-// instead of requiring the use of RPC.
-
-// func mach_semaphore_wait(sema uint32) int32
-TEXT runtime·mach_semaphore_wait(SB),NOSPLIT,$0
- MOVL $-36, AX
- CALL runtime·sysenter(SB)
- MOVL AX, ret+4(FP)
- RET
-
-// func mach_semaphore_timedwait(sema, sec, nsec uint32) int32
-TEXT runtime·mach_semaphore_timedwait(SB),NOSPLIT,$0
- MOVL $-38, AX
- CALL runtime·sysenter(SB)
- MOVL AX, ret+12(FP)
- RET
-
-// func mach_semaphore_signal(sema uint32) int32
-TEXT runtime·mach_semaphore_signal(SB),NOSPLIT,$0
- MOVL $-33, AX
- CALL runtime·sysenter(SB)
- MOVL AX, ret+4(FP)
- RET
-
-// func mach_semaphore_signal_all(sema uint32) int32
-TEXT runtime·mach_semaphore_signal_all(SB),NOSPLIT,$0
- MOVL $-34, AX
- CALL runtime·sysenter(SB)
- MOVL AX, ret+4(FP)
- RET
-
// func setldt(entry int, address int, limit int)
TEXT runtime·setldt(SB),NOSPLIT,$32
// Nothing to do on Darwin, pthread already set thread-local storage up.
MOVL BP, SP
POPL BP
RET
+
+TEXT runtime·pthread_mutex_init_trampoline(SB),NOSPLIT,$0
+ PUSHL BP
+ MOVL SP, BP
+ SUBL $8, SP
+ MOVL 16(SP), CX
+ MOVL 0(CX), AX // arg 1 mutex
+ MOVL AX, 0(SP)
+ MOVL 4(CX), AX // arg 2 attr
+ MOVL AX, 4(SP)
+ CALL libc_pthread_mutex_init(SB)
+ MOVL BP, SP
+ POPL BP
+ RET
+
+TEXT runtime·pthread_mutex_lock_trampoline(SB),NOSPLIT,$0
+ PUSHL BP
+ MOVL SP, BP
+ SUBL $8, SP
+ MOVL 16(SP), CX
+ MOVL 0(CX), AX // arg 1 mutex
+ MOVL AX, 0(SP)
+ CALL libc_pthread_mutex_lock(SB)
+ MOVL BP, SP
+ POPL BP
+ RET
+
+TEXT runtime·pthread_mutex_unlock_trampoline(SB),NOSPLIT,$0
+ PUSHL BP
+ MOVL SP, BP
+ SUBL $8, SP
+ MOVL 16(SP), CX
+ MOVL 0(CX), AX // arg 1 mutex
+ MOVL AX, 0(SP)
+ CALL libc_pthread_mutex_unlock(SB)
+ MOVL BP, SP
+ POPL BP
+ RET
+
+TEXT runtime·pthread_cond_init_trampoline(SB),NOSPLIT,$0
+ PUSHL BP
+ MOVL SP, BP
+ SUBL $8, SP
+ MOVL 16(SP), CX
+ MOVL 0(CX), AX // arg 1 cond
+ MOVL AX, 0(SP)
+ MOVL 4(CX), AX // arg 2 attr
+ MOVL AX, 4(SP)
+ CALL libc_pthread_cond_init(SB)
+ MOVL BP, SP
+ POPL BP
+ RET
+
+TEXT runtime·pthread_cond_wait_trampoline(SB),NOSPLIT,$0
+ PUSHL BP
+ MOVL SP, BP
+ SUBL $8, SP
+ MOVL 16(SP), CX
+ MOVL 0(CX), AX // arg 1 cond
+ MOVL AX, 0(SP)
+ MOVL 4(CX), AX // arg 2 mutex
+ MOVL AX, 4(SP)
+ CALL libc_pthread_cond_wait(SB)
+ MOVL BP, SP
+ POPL BP
+ RET
+
+TEXT runtime·pthread_cond_timedwait_trampoline(SB),NOSPLIT,$0
+ PUSHL BP
+ MOVL SP, BP
+ SUBL $24, SP
+ MOVL 32(SP), CX
+ MOVL 0(CX), AX // arg 1 cond
+ MOVL AX, 0(SP)
+ MOVL 4(CX), AX // arg 2 mutex
+ MOVL AX, 4(SP)
+ MOVL 8(CX), AX // arg 3 timeout
+ MOVL AX, 8(SP)
+ CALL libc_pthread_cond_timedwait(SB)
+ MOVL BP, SP
+ POPL BP
+ RET
+
+TEXT runtime·pthread_cond_signal_trampoline(SB),NOSPLIT,$0
+ PUSHL BP
+ MOVL SP, BP
+ SUBL $8, SP
+ MOVL 16(SP), CX
+ MOVL 0(CX), AX // arg 1 cond
+ MOVL AX, 0(SP)
+ CALL libc_pthread_cond_signal(SB)
+ MOVL BP, SP
+ POPL BP
+ RET
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//
// System calls and other sys.stuff for AMD64, Darwin
-// See http://fxr.watson.org/fxr/source/bsd/kern/syscalls.c?v=xnu-1228
-// or /usr/include/sys/syscall.h (on a Mac) for system call numbers.
-//
-// The low 24 bits are the system call number.
-// The high 8 bits specify the kind of system call: 1=Mach, 2=BSD, 3=Machine-Dependent.
-//
+// System calls are implemented in libSystem, this file contains
+// trampolines that convert from Go to C calling convention.
#include "go_asm.h"
#include "go_tls.h"
POPQ BP
RET
-// Mach system calls use 0x1000000 instead of the BSD's 0x2000000.
-
-// func mach_msg_trap(h unsafe.Pointer, op int32, send_size, rcv_size, rcv_name, timeout, notify uint32) int32
-TEXT runtime·mach_msg_trap(SB),NOSPLIT,$0
- MOVQ h+0(FP), DI
- MOVL op+8(FP), SI
- MOVL send_size+12(FP), DX
- MOVL rcv_size+16(FP), R10
- MOVL rcv_name+20(FP), R8
- MOVL timeout+24(FP), R9
- MOVL notify+28(FP), R11
- PUSHQ R11 // seventh arg, on stack
- MOVL $(0x1000000+31), AX // mach_msg_trap
- SYSCALL
- POPQ R11
- MOVL AX, ret+32(FP)
- RET
-
-TEXT runtime·mach_task_self(SB),NOSPLIT,$0
- MOVL $(0x1000000+28), AX // task_self_trap
- SYSCALL
- MOVL AX, ret+0(FP)
- RET
-
-TEXT runtime·mach_thread_self(SB),NOSPLIT,$0
- MOVL $(0x1000000+27), AX // thread_self_trap
- SYSCALL
- MOVL AX, ret+0(FP)
- RET
-
-TEXT runtime·mach_reply_port(SB),NOSPLIT,$0
- MOVL $(0x1000000+26), AX // mach_reply_port
- SYSCALL
- MOVL AX, ret+0(FP)
- RET
-
-// Mach provides trap versions of the semaphore ops,
-// instead of requiring the use of RPC.
-
-// func mach_semaphore_wait(sema uint32) int32
-TEXT runtime·mach_semaphore_wait(SB),NOSPLIT,$0
- MOVL sema+0(FP), DI
- MOVL $(0x1000000+36), AX // semaphore_wait_trap
- SYSCALL
- MOVL AX, ret+8(FP)
- RET
-
-// func mach_semaphore_timedwait(sema, sec, nsec uint32) int32
-TEXT runtime·mach_semaphore_timedwait(SB),NOSPLIT,$0
- MOVL sema+0(FP), DI
- MOVL sec+4(FP), SI
- MOVL nsec+8(FP), DX
- MOVL $(0x1000000+38), AX // semaphore_timedwait_trap
- SYSCALL
- MOVL AX, ret+16(FP)
- RET
-
-// func mach_semaphore_signal(sema uint32) int32
-TEXT runtime·mach_semaphore_signal(SB),NOSPLIT,$0
- MOVL sema+0(FP), DI
- MOVL $(0x1000000+33), AX // semaphore_signal_trap
- SYSCALL
- MOVL AX, ret+8(FP)
- RET
-
-// func mach_semaphore_signal_all(sema uint32) int32
-TEXT runtime·mach_semaphore_signal_all(SB),NOSPLIT,$0
- MOVL sema+0(FP), DI
- MOVL $(0x1000000+34), AX // semaphore_signal_all_trap
- SYSCALL
- MOVL AX, ret+8(FP)
- RET
-
TEXT runtime·settls(SB),NOSPLIT,$32
// Nothing to do on Darwin, pthread already set thread-local storage up.
RET
CALL libc_raise(SB)
POPQ BP
RET
+
+TEXT runtime·pthread_mutex_init_trampoline(SB),NOSPLIT,$0
+ PUSHQ BP
+ MOVQ SP, BP
+ MOVQ 8(DI), SI // arg 2 attr
+ MOVQ 0(DI), DI // arg 1 mutex
+ CALL libc_pthread_mutex_init(SB)
+ POPQ BP
+ RET
+
+TEXT runtime·pthread_mutex_lock_trampoline(SB),NOSPLIT,$0
+ PUSHQ BP
+ MOVQ SP, BP
+ MOVQ 0(DI), DI // arg 1 mutex
+ CALL libc_pthread_mutex_lock(SB)
+ POPQ BP
+ RET
+
+TEXT runtime·pthread_mutex_unlock_trampoline(SB),NOSPLIT,$0
+ PUSHQ BP
+ MOVQ SP, BP
+ MOVQ 0(DI), DI // arg 1 mutex
+ CALL libc_pthread_mutex_unlock(SB)
+ POPQ BP
+ RET
+
+TEXT runtime·pthread_cond_init_trampoline(SB),NOSPLIT,$0
+ PUSHQ BP
+ MOVQ SP, BP
+ MOVQ 8(DI), SI // arg 2 attr
+ MOVQ 0(DI), DI // arg 1 cond
+ CALL libc_pthread_cond_init(SB)
+ POPQ BP
+ RET
+
+TEXT runtime·pthread_cond_wait_trampoline(SB),NOSPLIT,$0
+ PUSHQ BP
+ MOVQ SP, BP
+ MOVQ 8(DI), SI // arg 2 mutex
+ MOVQ 0(DI), DI // arg 1 cond
+ CALL libc_pthread_cond_wait(SB)
+ POPQ BP
+ RET
+
+TEXT runtime·pthread_cond_timedwait_trampoline(SB),NOSPLIT,$0
+ PUSHQ BP
+ MOVQ SP, BP
+ MOVQ 8(DI), SI // arg 2 mutex
+ MOVQ 16(DI), DX // arg 3 timeout
+ MOVQ 0(DI), DI // arg 1 cond
+ CALL libc_pthread_cond_timedwait(SB)
+ POPQ BP
+ RET
+
+TEXT runtime·pthread_cond_signal_trampoline(SB),NOSPLIT,$0
+ PUSHQ BP
+ MOVQ SP, BP
+ MOVQ 0(DI), DI // arg 1 cond
+ CALL libc_pthread_cond_signal(SB)
+ POPQ BP
+ RET
return q
}
+//go:nosplit
func int64mod(n, d int64) int64 {
// Check for 32 bit operands
if int64(int32(n)) == n && int64(int32(d)) == d {