kqueue, kevent, closeonexec, setitimer, with sysctl and fcntl helpers.
TODO:arm,arm64
Change-Id: I9386f377186d6ac7cb99064c524a67e0c8282eba
Reviewed-on: https://go-review.googlesource.com/118561
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
#include <sys/event.h>
#include <sys/mman.h>
#include <pthread.h>
+#include <fcntl.h>
*/
import "C"
EVFILT_WRITE = C.EVFILT_WRITE
PTHREAD_CREATE_DETACHED = C.PTHREAD_CREATE_DETACHED
+
+ F_SETFD = C.F_SETFD
+ FD_CLOEXEC = C.FD_CLOEXEC
)
type MachBody C.mach_msg_body_t
_EVFILT_WRITE = -0x2
_PTHREAD_CREATE_DETACHED = 0x2
+
+ _F_SETFD = 0x2
+ _FD_CLOEXEC = 0x1
)
type machbody struct {
_EVFILT_WRITE = -0x2
_PTHREAD_CREATE_DETACHED = 0x2
+
+ _F_SETFD = 0x2
+ _FD_CLOEXEC = 0x1
)
type machbody struct {
import "unsafe"
-func kqueue() int32
-
-//go:noescape
-func kevent(kq int32, ch *keventt, nch int32, ev *keventt, nev int32, ts *timespec) int32
-func closeonexec(fd int32)
-
var (
kq int32 = -1
)
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
_SS_DISABLE = 4
)
-//go:noescape
-func setitimer(mode int32, new, old *itimerval)
-
//extern SigTabTT runtime·sigtab[];
type sigset uint32
func osyield()
+func kqueue() int32
+
+//go:noescape
+func kevent(kq int32, ch *keventt, nch int32, ev *keventt, nev int32, ts *timespec) int32
+func closeonexec(fd int32)
+
const stackSystem = 0
// From DragonFly's <sys/sysctl.h>
func osyield()
+func kqueue() int32
+
+//go:noescape
+func kevent(kq int32, ch *keventt, nch int32, ev *keventt, nev int32, ts *timespec) int32
+func closeonexec(fd int32)
+
// From FreeBSD's <sys/sysctl.h>
const (
_CTL_HW = 6
func osyield()
+func kqueue() int32
+
+//go:noescape
+func kevent(kq int32, ch *keventt, nch int32, ev *keventt, nev int32, ts *timespec) int32
+func closeonexec(fd int32)
+
const (
_ESRCH = 3
_ETIMEDOUT = 60
func osyield()
+func kqueue() int32
+
+//go:noescape
+func kevent(kq int32, ch *keventt, nch int32, ev *keventt, nev int32, ts *timespec) int32
+func closeonexec(fd int32)
+
const (
_ESRCH = 3
_EAGAIN = 35
}
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))
+}
+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))
+}
+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))
+}
+func fcntl_trampoline()
+
+//go:nosplit
+//go:cgo_unsafe_args
+func kqueue() int32 {
+ v := asmcgocall(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))
+}
+func kevent_trampoline()
+
// Not used on Darwin, but must be defined.
func exitThread(wait *uint32) {
}
+//go:nosplit
+func closeonexec(fd int32) {
+ fcntl(fd, _F_SETFD, _FD_CLOEXEC)
+}
+
// Tell the linker that the libc_* functions are to be found
// in a system library, with the libc_ prefix missing.
//go:cgo_import_dynamic libc_sigaltstack sigaltstack "/usr/lib/libSystem.B.dylib"
//go:cgo_import_dynamic libc_getpid getpid "/usr/lib/libSystem.B.dylib"
//go:cgo_import_dynamic libc_kill kill "/usr/lib/libSystem.B.dylib"
+//go:cgo_import_dynamic libc_setitimer setitimer "/usr/lib/libSystem.B.dylib"
+//go:cgo_import_dynamic libc_sysctl sysctl "/usr/lib/libSystem.B.dylib"
+//go:cgo_import_dynamic libc_fcntl fcntl "/usr/lib/libSystem.B.dylib"
+//go:cgo_import_dynamic libc_kqueue kqueue "/usr/lib/libSystem.B.dylib"
+//go:cgo_import_dynamic libc_kevent kevent "/usr/lib/libSystem.B.dylib"
// Magic incantation to get libSystem actually dynamically linked.
// TODO: Why does the code require this? See cmd/compile/internal/ld/go.go:210
POPL BP
RET
-TEXT runtime·setitimer(SB),NOSPLIT,$0
- MOVL $83, AX
- INT $0x80
+TEXT runtime·setitimer_trampoline(SB),NOSPLIT,$0
+ PUSHL BP
+ MOVL SP, BP
+ SUBL $24, SP
+ MOVL 32(SP), CX
+ MOVL 0(CX), AX // arg 1 mode
+ MOVL AX, 0(SP)
+ MOVL 4(CX), AX // arg 2 new
+ MOVL AX, 4(SP)
+ MOVL 8(CX), AX // arg 3 old
+ MOVL AX, 8(SP)
+ CALL libc_setitimer(SB)
+ MOVL BP, SP
+ POPL BP
RET
TEXT runtime·walltime_trampoline(SB),NOSPLIT,$0
// Nothing to do on Darwin, pthread already set thread-local storage up.
RET
-TEXT runtime·sysctl(SB),NOSPLIT,$0
- MOVL $202, AX
- INT $0x80
- JAE 4(PC)
- NEGL AX
- MOVL AX, ret+24(FP)
+TEXT runtime·sysctl_trampoline(SB),NOSPLIT,$0
+ PUSHL BP
+ MOVL SP, BP
+ SUBL $24, SP
+ MOVL 32(SP), CX
+ MOVL 0(CX), AX // arg 1 mib
+ MOVL AX, 0(SP)
+ MOVL 4(CX), AX // arg 2 miblen
+ MOVL AX, 4(SP)
+ MOVL 8(CX), AX // arg 3 out
+ MOVL AX, 8(SP)
+ MOVL 12(CX), AX // arg 4 size
+ MOVL AX, 12(SP)
+ MOVL 16(CX), AX // arg 5 dst
+ MOVL AX, 16(SP)
+ MOVL 20(CX), AX // arg 6 ndst
+ MOVL AX, 20(SP)
+ CALL libc_sysctl(SB)
+ MOVL BP, SP
+ POPL BP
RET
- MOVL $0, AX
- MOVL AX, ret+24(FP)
+
+TEXT runtime·kqueue_trampoline(SB),NOSPLIT,$0
+ PUSHL BP
+ MOVL SP, BP
+ SUBL $8, SP
+ CALL libc_kqueue(SB)
+ MOVL BP, SP
+ POPL BP
RET
-// func kqueue() int32
-TEXT runtime·kqueue(SB),NOSPLIT,$0
- MOVL $362, AX
- INT $0x80
- JAE 2(PC)
- NEGL AX
- MOVL AX, ret+0(FP)
+TEXT runtime·kevent_trampoline(SB),NOSPLIT,$0
+ PUSHL BP
+ MOVL SP, BP
+ SUBL $24, SP
+ MOVL 32(SP), CX
+ MOVL 0(CX), AX // arg 1 kq
+ MOVL AX, 0(SP)
+ MOVL 4(CX), AX // arg 2 ch
+ MOVL AX, 4(SP)
+ MOVL 8(CX), AX // arg 3 nch
+ MOVL AX, 8(SP)
+ MOVL 12(CX), AX // arg 4 ev
+ MOVL AX, 12(SP)
+ MOVL 16(CX), AX // arg 5 nev
+ MOVL AX, 16(SP)
+ MOVL 20(CX), AX // arg 6 ts
+ MOVL AX, 20(SP)
+ CALL libc_kevent(SB)
+ CMPL AX, $-1
+ JNE ok
+ CALL libc_error(SB)
+ MOVL (AX), AX // errno
+ NEGL AX // caller wants it as a negative error code
+ok:
+ MOVL BP, SP
+ POPL BP
RET
-// func kevent(kq int32, ch *keventt, nch int32, ev *keventt, nev int32, ts *timespec) int32
-TEXT runtime·kevent(SB),NOSPLIT,$0
- MOVL $363, AX
- INT $0x80
- JAE 2(PC)
- NEGL AX
- MOVL AX, ret+24(FP)
- RET
-
-// func closeonexec(fd int32)
-TEXT runtime·closeonexec(SB),NOSPLIT,$32
- MOVL $92, AX // fcntl
- // 0(SP) is where the caller PC would be; kernel skips it
- MOVL fd+0(FP), BX
- MOVL BX, 4(SP) // fd
- MOVL $2, 8(SP) // F_SETFD
- MOVL $1, 12(SP) // FD_CLOEXEC
- INT $0x80
- JAE 2(PC)
- NEGL AX
+TEXT runtime·fcntl_trampoline(SB),NOSPLIT,$0
+ PUSHL BP
+ MOVL SP, BP
+ SUBL $24, SP
+ MOVL 32(SP), CX
+ MOVL 0(CX), AX // arg 1 fd
+ MOVL AX, 0(SP)
+ MOVL 4(CX), AX // arg 2 cmd
+ MOVL AX, 4(SP)
+ MOVL 8(CX), AX // arg 3 arg
+ MOVL AX, 8(SP)
+ CALL libc_fcntl(SB)
+ MOVL BP, SP
+ POPL BP
RET
// mstart_stub is the first function executed on a new thread started by pthread_create.
POPQ BP
RET
-TEXT runtime·setitimer(SB), NOSPLIT, $0
- MOVL mode+0(FP), DI
- MOVQ new+8(FP), SI
- MOVQ old+16(FP), DX
- MOVL $(0x2000000+83), AX // syscall entry
- SYSCALL
+TEXT runtime·setitimer_trampoline(SB),NOSPLIT,$0
+ PUSHQ BP
+ MOVQ SP, BP
+ MOVQ 8(DI), SI // arg 2 new
+ MOVQ 16(DI), DX // arg 3 old
+ MOVL 0(DI), DI // arg 1 which
+ CALL libc_setitimer(SB)
+ POPQ BP
RET
TEXT runtime·madvise_trampoline(SB), NOSPLIT, $0
// Nothing to do on Darwin, pthread already set thread-local storage up.
RET
-TEXT runtime·sysctl(SB),NOSPLIT,$0
- MOVQ mib+0(FP), DI
- MOVL miblen+8(FP), SI
- MOVQ out+16(FP), DX
- MOVQ size+24(FP), R10
- MOVQ dst+32(FP), R8
- MOVQ ndst+40(FP), R9
- MOVL $(0x2000000+202), AX // syscall entry
- SYSCALL
- JCC 4(PC)
- NEGQ AX
- MOVL AX, ret+48(FP)
- RET
- MOVL $0, AX
- MOVL AX, ret+48(FP)
+TEXT runtime·sysctl_trampoline(SB),NOSPLIT,$0
+ PUSHQ BP
+ MOVQ SP, BP
+ MOVL 8(DI), SI // arg 2 miblen
+ MOVQ 16(DI), DX // arg 3 out
+ MOVQ 24(DI), CX // arg 4 size
+ MOVQ 32(DI), R8 // arg 5 dst
+ MOVQ 40(DI), R9 // arg 6 ndst
+ MOVQ 0(DI), DI // arg 1 mib
+ CALL libc_sysctl(SB)
+ POPQ BP
RET
-// func kqueue() int32
-TEXT runtime·kqueue(SB),NOSPLIT,$0
- MOVQ $0, DI
- MOVQ $0, SI
- MOVQ $0, DX
- MOVL $(0x2000000+362), AX
- SYSCALL
- JCC 2(PC)
- NEGQ AX
- MOVL AX, ret+0(FP)
+TEXT runtime·kqueue_trampoline(SB),NOSPLIT,$0
+ PUSHQ BP
+ MOVQ SP, BP
+ CALL libc_kqueue(SB)
+ POPQ BP
RET
-// func kevent(kq int32, ch *keventt, nch int32, ev *keventt, nev int32, ts *timespec) int32
-TEXT runtime·kevent(SB),NOSPLIT,$0
- MOVL kq+0(FP), DI
- MOVQ ch+8(FP), SI
- MOVL nch+16(FP), DX
- MOVQ ev+24(FP), R10
- MOVL nev+32(FP), R8
- MOVQ ts+40(FP), R9
- MOVL $(0x2000000+363), AX
- SYSCALL
- JCC 2(PC)
- NEGQ AX
- MOVL AX, ret+48(FP)
+TEXT runtime·kevent_trampoline(SB),NOSPLIT,$0
+ PUSHQ BP
+ MOVQ SP, BP
+ MOVQ 8(DI), SI // arg 2 keventt
+ MOVL 16(DI), DX // arg 3 nch
+ MOVQ 24(DI), CX // arg 4 ev
+ MOVL 32(DI), R8 // arg 5 nev
+ MOVQ 40(DI), R9 // arg 6 ts
+ MOVL 0(DI), DI // arg 1 kq
+ CALL libc_kevent(SB)
+ CMPQ AX, $-1
+ JNE ok
+ CALL libc_error(SB)
+ MOVQ (AX), AX // errno
+ NEGQ AX // caller wants it as a negative error code
+ok:
+ POPQ BP
RET
-// func closeonexec(fd int32)
-TEXT runtime·closeonexec(SB),NOSPLIT,$0
- MOVL fd+0(FP), DI // fd
- MOVQ $2, SI // F_SETFD
- MOVQ $1, DX // FD_CLOEXEC
- MOVL $(0x2000000+92), AX // fcntl
- SYSCALL
+TEXT runtime·fcntl_trampoline(SB),NOSPLIT,$0
+ PUSHQ BP
+ MOVQ SP, BP
+ MOVL 4(DI), SI // arg 2 cmd
+ MOVL 8(DI), DX // arg 3 arg
+ MOVL 0(DI), DI // arg 1 fd
+ CALL libc_fcntl(SB)
+ POPQ BP
RET
// mstart_stub is the first function executed on a new thread started by pthread_create.