Commit e86c2678 authored by Keith Randall's avatar Keith Randall

runtime: fix darwin 386/amd64 stack switches

A few libc_ calls were missing stack switches.

Unfortunately, adding the stack switches revealed a deeper problem.
systemstack() is fundamentally flawed because when you do

    systemstack(func() { ... })

There's no way to mark the anonymous function as nosplit.  At first I
thought it didn't matter, as that function runs on the g0 stack.  But
nosplit is still required, because some syscalls are done when stack
bounds are not set up correctly (e.g. in a signal handler, which runs
on the g0 stack, but g is still pointing at the g stack).  Instead use
asmcgocall and funcPC, so we can be nosplit all the way down.

Mid-stack inlining now pushes darwin over the nosplit limit also.
Leaving that as a TODO.
Update #23168

This might fix the cause of occasional darwin hangs.
Update #25181

Update #17490

Change-Id: If9c3ef052822c7679f5a1dd192443f714483327e
Reviewed-on: https://go-review.googlesource.com/111258Reviewed-by: default avatarIan Lance Taylor <iant@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent e9137299
......@@ -547,8 +547,8 @@ func TestInlinedRoutineRecords(t *testing.T) {
if runtime.GOOS == "plan9" {
t.Skip("skipping on plan9; no DWARF symbol table in executables")
}
if runtime.GOOS == "solaris" {
t.Skip("skipping on solaris, pending resolution of issue #23168")
if runtime.GOOS == "solaris" || runtime.GOOS == "darwin" {
t.Skip("skipping on solaris and darwin, pending resolution of issue #23168")
}
const prog = `
......@@ -685,7 +685,6 @@ func main() {
}
func abstractOriginSanity(t *testing.T, flags string) {
// Nothing special about net/http here, this is just a convenient
// way to pull in a lot of code.
const prog = `
......@@ -731,7 +730,6 @@ func main() {
// references.
abscount := 0
for i, die := range ex.dies {
// Does it have an abstract origin?
ooff, originOK := die.Val(dwarf.AttrAbstractOrigin).(dwarf.Offset)
if !originOK {
......@@ -788,8 +786,8 @@ func TestAbstractOriginSanity(t *testing.T) {
if runtime.GOOS == "plan9" {
t.Skip("skipping on plan9; no DWARF symbol table in executables")
}
if runtime.GOOS == "solaris" {
t.Skip("skipping on solaris, pending resolution of issue #23168")
if runtime.GOOS == "solaris" || runtime.GOOS == "darwin" {
t.Skip("skipping on solaris and darwin, pending resolution of issue #23168")
}
abstractOriginSanity(t, OptInl4)
......@@ -801,8 +799,8 @@ func TestAbstractOriginSanityWithLocationLists(t *testing.T) {
if runtime.GOOS == "plan9" {
t.Skip("skipping on plan9; no DWARF symbol table in executables")
}
if runtime.GOOS == "solaris" {
t.Skip("skipping on solaris, pending resolution of issue #23168")
if runtime.GOOS == "solaris" || runtime.GOOS == "darwin" {
t.Skip("skipping on solaris and darwin, pending resolution of issue #23168")
}
if runtime.GOARCH != "amd64" && runtime.GOARCH != "x86" {
t.Skip("skipping on not-amd64 not-x86; location lists not supported")
......
......@@ -697,6 +697,8 @@ TEXT ·asmcgocall(SB),NOSPLIT,$0-12
// come in on the m->g0 stack already.
get_tls(CX)
MOVL g(CX), BP
CMPL BP, $0
JEQ nosave // Don't even have a G yet.
MOVL g_m(BP), BP
MOVL m_g0(BP), SI
MOVL g(CX), DI
......@@ -728,6 +730,18 @@ noswitch:
MOVL AX, ret+8(FP)
RET
nosave:
// Now on a scheduling stack (a pthread-created stack).
SUBL $32, SP
ANDL $~15, SP // alignment, perhaps unnecessary
MOVL DX, 4(SP) // save original stack pointer
MOVL BX, 0(SP) // first argument in x86-32 ABI
CALL AX
MOVL 4(SP), CX // restore original stack pointer
MOVL CX, SP
MOVL AX, ret+8(FP)
RET
// cgocallback(void (*fn)(void*), void *frame, uintptr framesize, uintptr ctxt)
// Turn the fn into a Go func (by taking its address) and call
......
......@@ -9,6 +9,8 @@
// +build !linux !amd64
// +build !linux !arm64
// +build !js
// +build !darwin !amd64
// +build !darwin !386
package runtime
......
......@@ -154,7 +154,7 @@ func newosproc(mp *m) {
// setup and then calls mstart.
var oset sigset
sigprocmask(_SIG_SETMASK, &sigset_all, &oset)
_, err = pthread_create(&attr, funcPC(mstart_stub), unsafe.Pointer(mp))
err = pthread_create(&attr, funcPC(mstart_stub), unsafe.Pointer(mp))
sigprocmask(_SIG_SETMASK, &oset, nil)
if err != 0 {
write(2, unsafe.Pointer(&failthreadcreate[0]), int32(len(failthreadcreate)))
......@@ -175,21 +175,21 @@ func newosproc0(stacksize uintptr, fn uintptr) {
// Initialize an attribute object.
var attr pthreadattr
var err int32
err = pthread_attr_init_trampoline(&attr)
err = pthread_attr_init(&attr)
if err != 0 {
write(2, unsafe.Pointer(&failthreadcreate[0]), int32(len(failthreadcreate)))
exit(1)
}
// Set the stack we want to use.
if pthread_attr_setstacksize_trampoline(&attr, stacksize) != 0 {
if pthread_attr_setstacksize(&attr, stacksize) != 0 {
write(2, unsafe.Pointer(&failthreadcreate[0]), int32(len(failthreadcreate)))
exit(1)
}
mSysStatInc(&memstats.stacks_sys, stacksize)
// Tell the pthread library we won't join with this thread.
if pthread_attr_setdetachstate_trampoline(&attr, _PTHREAD_CREATE_DETACHED) != 0 {
if pthread_attr_setdetachstate(&attr, _PTHREAD_CREATE_DETACHED) != 0 {
write(2, unsafe.Pointer(&failthreadcreate[0]), int32(len(failthreadcreate)))
exit(1)
}
......@@ -198,8 +198,7 @@ func newosproc0(stacksize uintptr, fn uintptr) {
// setup and then calls mstart.
var oset sigset
sigprocmask(_SIG_SETMASK, &sigset_all, &oset)
var t pthread
err = pthread_create_trampoline(&t, &attr, fn, nil)
err = pthread_create(&attr, fn, nil)
sigprocmask(_SIG_SETMASK, &oset, nil)
if err != 0 {
write(2, unsafe.Pointer(&failthreadcreate[0]), int32(len(failthreadcreate)))
......
......@@ -7,6 +7,8 @@
// +build !windows
// +build !nacl
// +build !js
// +build !darwin !amd64
// +build !darwin !386
package runtime
......
......@@ -2,6 +2,8 @@
// 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"
......@@ -9,71 +11,122 @@ import "unsafe"
// The *_trampoline functions convert from the Go calling convention to the C calling convention
// and then call the underlying libc function. They are defined in sys_darwin_$ARCH.s.
//go:nowritebarrier
func pthread_attr_init(attr *pthreadattr) (errno int32) {
systemstack(func() {
errno = pthread_attr_init_trampoline(attr)
})
return
//go:nosplit
//go:cgo_unsafe_args
func pthread_attr_init(attr *pthreadattr) int32 {
return asmcgocall(unsafe.Pointer(funcPC(pthread_attr_init_trampoline)), unsafe.Pointer(&attr))
}
func pthread_attr_init_trampoline()
//go:nosplit
//go:cgo_unsafe_args
func pthread_attr_setstacksize(attr *pthreadattr, size uintptr) int32 {
return asmcgocall(unsafe.Pointer(funcPC(pthread_attr_setstacksize_trampoline)), unsafe.Pointer(&attr))
}
func pthread_attr_setstacksize_trampoline()
//go:noescape
func pthread_attr_init_trampoline(attr *pthreadattr) int32
//go:nosplit
//go:cgo_unsafe_args
func pthread_attr_setdetachstate(attr *pthreadattr, state int) int32 {
return asmcgocall(unsafe.Pointer(funcPC(pthread_attr_setdetachstate_trampoline)), unsafe.Pointer(&attr))
}
func pthread_attr_setdetachstate_trampoline()
//go:nowritebarrier
func pthread_attr_setstacksize(attr *pthreadattr, size uintptr) (errno int32) {
systemstack(func() {
errno = pthread_attr_setstacksize_trampoline(attr, size)
})
return
//go:nosplit
//go:cgo_unsafe_args
func pthread_create(attr *pthreadattr, start uintptr, arg unsafe.Pointer) int32 {
return asmcgocall(unsafe.Pointer(funcPC(pthread_create_trampoline)), unsafe.Pointer(&attr))
}
func pthread_create_trampoline()
//go:noescape
func pthread_attr_setstacksize_trampoline(attr *pthreadattr, size uintptr) int32
//go:nosplit
//go:cgo_unsafe_args
func pthread_kill(thread pthread, sig int) (errno int32) {
return asmcgocall(unsafe.Pointer(funcPC(pthread_kill_trampoline)), unsafe.Pointer(&thread))
}
func pthread_kill_trampoline()
//go:nowritebarrier
func pthread_attr_setdetachstate(attr *pthreadattr, state int) (errno int32) {
systemstack(func() {
errno = pthread_attr_setdetachstate_trampoline(attr, state)
})
//go:nosplit
//go:cgo_unsafe_args
func pthread_self() (t pthread) {
asmcgocall(unsafe.Pointer(funcPC(pthread_self_trampoline)), unsafe.Pointer(&t))
return
}
func pthread_self_trampoline()
func mmap(addr unsafe.Pointer, n uintptr, prot, flags, fd int32, off uint32) (unsafe.Pointer, int) {
args := struct {
addr unsafe.Pointer
n uintptr
prot, flags, fd int32
off uint32
ret1 unsafe.Pointer
ret2 int
}{addr, n, prot, flags, fd, off, nil, 0}
asmcgocall(unsafe.Pointer(funcPC(mmap_trampoline)), unsafe.Pointer(&args))
return args.ret1, args.ret2
}
func mmap_trampoline()
//go:noescape
func pthread_attr_setdetachstate_trampoline(attr *pthreadattr, state int) int32
//go:nosplit
//go:cgo_unsafe_args
func munmap(addr unsafe.Pointer, n uintptr) {
asmcgocall(unsafe.Pointer(funcPC(munmap_trampoline)), unsafe.Pointer(&addr))
}
func munmap_trampoline()
//go:nowritebarrier
func pthread_create(attr *pthreadattr, start uintptr, arg unsafe.Pointer) (t pthread, errno int32) {
systemstack(func() {
errno = pthread_create_trampoline(&t, attr, start, arg)
})
return
//go:nosplit
//go:cgo_unsafe_args
func madvise(addr unsafe.Pointer, n uintptr, flags int32) {
asmcgocall(unsafe.Pointer(funcPC(madvise_trampoline)), unsafe.Pointer(&addr))
}
func madvise_trampoline()
//go:noescape
func pthread_create_trampoline(t *pthread, attr *pthreadattr, start uintptr, arg unsafe.Pointer) int32
//go:nosplit
//go:cgo_unsafe_args
func read(fd int32, p unsafe.Pointer, n int32) int32 {
return asmcgocall(unsafe.Pointer(funcPC(read_trampoline)), unsafe.Pointer(&fd))
}
func read_trampoline()
//go:nowritebarrier
func pthread_kill(thread pthread, sig int) (errno int32) {
systemstack(func() {
errno = pthread_kill_trampoline(thread, sig)
})
return
//go:nosplit
//go:cgo_unsafe_args
func closefd(fd int32) int32 {
return asmcgocall(unsafe.Pointer(funcPC(close_trampoline)), unsafe.Pointer(&fd))
}
func close_trampoline()
//go:noescape
func pthread_kill_trampoline(thread pthread, sig int) int32
//go:nosplit
//go:cgo_unsafe_args
func exit(code int32) {
asmcgocall(unsafe.Pointer(funcPC(exit_trampoline)), unsafe.Pointer(&code))
}
func exit_trampoline()
//go:nowritebarrier
func pthread_self() (t pthread) {
systemstack(func() {
t = pthread_self_trampoline()
})
return
//go:nosplit
//go:cgo_unsafe_args
func usleep(usec uint32) {
asmcgocall(unsafe.Pointer(funcPC(usleep_trampoline)), unsafe.Pointer(&usec))
}
func usleep_trampoline()
//go:noescape
func pthread_self_trampoline() pthread
//go:nosplit
//go:cgo_unsafe_args
func write(fd uintptr, p unsafe.Pointer, n int32) int32 {
return asmcgocall(unsafe.Pointer(funcPC(write_trampoline)), unsafe.Pointer(&fd))
}
func write_trampoline()
//go:nosplit
//go:cgo_unsafe_args
func open(name *byte, mode, perm int32) (ret int32) {
return asmcgocall(unsafe.Pointer(funcPC(open_trampoline)), unsafe.Pointer(&name))
}
func open_trampoline()
// Not used on Darwin, but must be defined.
func exitThread(wait *uint32) {
}
// Tell the linker that the libc_* functions are to be found
// in a system library, with the libc_ prefix missing.
......
......@@ -11,12 +11,12 @@
#include "textflag.h"
// Exit the entire program (like C exit)
TEXT runtime·exit(SB),NOSPLIT,$0-4
MOVL code+0(FP), AX
TEXT runtime·exit_trampoline(SB),NOSPLIT,$0
PUSHL BP
MOVL SP, BP
SUBL $4, SP // allocate space for callee args
ANDL $~15, SP // align stack
SUBL $8, SP // allocate space for callee args (must be 8 mod 16)
MOVL 16(SP), CX // arg ptr
MOVL 0(CX), AX // arg 1 exit status
MOVL AX, 0(SP)
CALL libc_exit(SB)
MOVL $0xf1, 0xf1 // crash
......@@ -24,73 +24,64 @@ TEXT runtime·exit(SB),NOSPLIT,$0-4
POPL BP
RET
// Not used on Darwin.
TEXT runtime·exitThread(SB),NOSPLIT,$0-4
MOVL $0xf1, 0xf1 // crash
RET
TEXT runtime·open(SB),NOSPLIT,$0-16
MOVL name+0(FP), AX // arg 1 name
MOVL mode+4(FP), CX // arg 2 mode
MOVL perm+8(FP), DX // arg 3 perm
TEXT runtime·open_trampoline(SB),NOSPLIT,$0
PUSHL BP
MOVL SP, BP
SUBL $12, SP
ANDL $~15, SP
SUBL $24, SP
MOVL 32(SP), CX
MOVL 0(CX), AX // arg 1 name
MOVL AX, 0(SP)
MOVL CX, 4(SP)
MOVL DX, 8(SP)
MOVL 4(CX), AX // arg 2 mode
MOVL AX, 4(SP)
MOVL 8(CX), AX // arg 3 perm
MOVL AX, 8(SP)
CALL libc_open(SB)
MOVL BP, SP
POPL BP
MOVL AX, ret+12(FP)
RET
TEXT runtime·closefd(SB),NOSPLIT,$0-8
MOVL fd+0(FP), AX // arg 1 fd
TEXT runtime·close_trampoline(SB),NOSPLIT,$0
PUSHL BP
MOVL SP, BP
SUBL $4, SP
ANDL $~15, SP
SUBL $8, SP
MOVL 16(SP), CX
MOVL 0(CX), AX // arg 1 fd
MOVL AX, 0(SP)
CALL libc_close(SB)
MOVL BP, SP
POPL BP
MOVL AX, ret+4(FP)
RET
TEXT runtime·read(SB),NOSPLIT,$0-16
MOVL fd+0(FP), AX // arg 1 fd
MOVL p+4(FP), CX // arg 2 buf
MOVL n+8(FP), DX // arg 3 count
TEXT runtime·read_trampoline(SB),NOSPLIT,$0
PUSHL BP
MOVL SP, BP
SUBL $12, SP
ANDL $~15, SP
SUBL $24, SP
MOVL 32(SP), CX
MOVL 0(CX), AX // arg 1 fd
MOVL AX, 0(SP)
MOVL CX, 4(SP)
MOVL DX, 8(SP)
MOVL 4(CX), AX // arg 2 buf
MOVL AX, 4(SP)
MOVL 8(CX), AX // arg 3 count
MOVL AX, 8(SP)
CALL libc_read(SB)
MOVL BP, SP
POPL BP
MOVL AX, ret+12(FP)
RET
TEXT runtime·write(SB),NOSPLIT,$0-16
MOVL fd+0(FP), AX // arg 1 fd
MOVL p+4(FP), CX // arg 2 buf
MOVL n+8(FP), DX // arg 3 count
TEXT runtime·write_trampoline(SB),NOSPLIT,$0
PUSHL BP
MOVL SP, BP
SUBL $12, SP
ANDL $~15, SP
SUBL $24, SP
MOVL 32(SP), CX
MOVL 0(CX), AX // arg 1 fd
MOVL AX, 0(SP)
MOVL CX, 4(SP)
MOVL DX, 8(SP)
MOVL 4(CX), AX // arg 2 buf
MOVL AX, 4(SP)
MOVL 8(CX), AX // arg 3 count
MOVL AX, 8(SP)
CALL libc_write(SB)
MOVL BP, SP
POPL BP
MOVL AX, ret+12(FP)
RET
TEXT runtime·raiseproc(SB),NOSPLIT,$16
......@@ -104,23 +95,23 @@ TEXT runtime·raiseproc(SB),NOSPLIT,$16
INT $0x80
RET
TEXT runtime·mmap(SB),NOSPLIT,$0-32
MOVL addr+0(FP), AX // arg 1 addr
MOVL n+4(FP), CX // arg 2 len
MOVL prot+8(FP), DX // arg 3 prot
MOVL flags+12(FP), BX // arg 4 flags
MOVL fd+16(FP), DI // arg 5 fid
MOVL off+20(FP), SI // arg 6 offset
TEXT runtime·mmap_trampoline(SB),NOSPLIT,$0
PUSHL BP
MOVL SP, BP
SUBL $24, SP
ANDL $~15, SP
MOVL 32(SP), CX
MOVL 0(CX), AX // arg 1 addr
MOVL AX, 0(SP)
MOVL CX, 4(SP)
MOVL DX, 8(SP)
MOVL BX, 12(SP)
MOVL DI, 16(SP)
MOVL SI, 20(SP)
MOVL 4(CX), AX // arg 2 len
MOVL AX, 4(SP)
MOVL 8(CX), AX // arg 3 prot
MOVL AX, 8(SP)
MOVL 12(CX), AX // arg 4 flags
MOVL AX, 12(SP)
MOVL 16(CX), AX // arg 5 fid
MOVL AX, 16(SP)
MOVL 20(CX), AX // arg 6 offset
MOVL AX, 20(SP)
CALL libc_mmap(SB)
XORL DX, DX
CMPL AX, $-1
......@@ -129,38 +120,39 @@ TEXT runtime·mmap(SB),NOSPLIT,$0-32
MOVL (AX), DX // errno
XORL AX, AX
ok:
MOVL 32(SP), CX
MOVL AX, 24(CX) // result pointer
MOVL DX, 28(CX) // errno
MOVL BP, SP
POPL BP
MOVL AX, p+24(FP)
MOVL DX, err+28(FP)
RET
TEXT runtime·madvise(SB),NOSPLIT,$0-12
MOVL addr+0(FP), AX // arg 1 addr
MOVL n+4(FP), CX // arg 2 len
MOVL flags+8(FP), DX // arg 3 advice
TEXT runtime·madvise_trampoline(SB),NOSPLIT,$0
PUSHL BP
MOVL SP, BP
SUBL $12, SP
ANDL $~15, SP
SUBL $24, SP
MOVL 32(SP), CX
MOVL 0(CX), AX // arg 1 addr
MOVL AX, 0(SP)
MOVL CX, 4(SP)
MOVL DX, 8(SP)
MOVL 4(CX), AX // arg 2 len
MOVL AX, 4(SP)
MOVL 8(CX), AX // arg 3 advice
MOVL AX, 8(SP)
CALL libc_madvise(SB)
// ignore failure - maybe pages are locked
MOVL BP, SP
POPL BP
RET
TEXT runtime·munmap(SB),NOSPLIT,$0-8
MOVL addr+0(FP), AX // arg 1 addr
MOVL n+4(FP), CX // arg 2 len
TEXT runtime·munmap_trampoline(SB),NOSPLIT,$0
PUSHL BP
MOVL SP, BP
SUBL $8, SP
ANDL $~15, SP
MOVL 16(SP), CX
MOVL 0(CX), AX // arg 1 addr
MOVL AX, 0(SP)
MOVL CX, 4(SP)
MOVL 4(CX), AX // arg 2 len
MOVL AX, 4(SP)
CALL libc_munmap(SB)
TESTL AX, AX
JEQ 2(PC)
......@@ -394,12 +386,12 @@ TEXT runtime·sigaltstack(SB),NOSPLIT,$0
MOVL $0xf1, 0xf1 // crash
RET
TEXT runtime·usleep(SB),NOSPLIT,$0-4
MOVL usec+0(FP), AX
TEXT runtime·usleep_trampoline(SB),NOSPLIT,$0
PUSHL BP
MOVL SP, BP
SUBL $4, SP
ANDL $~15, SP
SUBL $8, SP
MOVL 16(SP), CX
MOVL 0(CX), AX // arg 1 usec
MOVL AX, 0(SP)
CALL libc_usleep(SB)
MOVL BP, SP
......@@ -545,125 +537,85 @@ TEXT runtime·mstart_stub(SB),NOSPLIT,$0
XORL AX, AX
RET
TEXT runtime·pthread_attr_init_trampoline(SB),NOSPLIT,$0-8
// move args into registers
MOVL attr+0(FP), AX
// save SP, BP
TEXT runtime·pthread_attr_init_trampoline(SB),NOSPLIT,$0
PUSHL BP
MOVL SP, BP
// allocate space for args
SUBL $4, SP
// align stack to 16 bytes
ANDL $~15, SP
// call libc function
SUBL $8, SP
MOVL 16(SP), CX
MOVL 0(CX), AX // arg 1 attr
MOVL AX, 0(SP)
CALL libc_pthread_attr_init(SB)
// restore BP, SP
MOVL BP, SP
POPL BP
// save result.
MOVL AX, ret+4(FP)
RET
TEXT runtime·pthread_attr_setstacksize_trampoline(SB),NOSPLIT,$0-12
MOVL attr+0(FP), AX
MOVL size+4(FP), CX
TEXT runtime·pthread_attr_setstacksize_trampoline(SB),NOSPLIT,$0
PUSHL BP
MOVL SP, BP
SUBL $8, SP
ANDL $~15, SP
MOVL 16(SP), CX
MOVL 0(CX), AX // arg 1 attr
MOVL AX, 0(SP)
MOVL CX, 4(SP)
MOVL 4(CX), AX // arg 2 size
MOVL AX, 4(SP)
CALL libc_pthread_attr_setstacksize(SB)
MOVL BP, SP
POPL BP
MOVL AX, ret+8(FP)
RET
TEXT runtime·pthread_attr_setdetachstate_trampoline(SB),NOSPLIT,$0-12
MOVL attr+0(FP), AX
MOVL state+4(FP), CX
TEXT runtime·pthread_attr_setdetachstate_trampoline(SB),NOSPLIT,$0
PUSHL BP
MOVL SP, BP
SUBL $8, SP
ANDL $~15, SP
MOVL 16(SP), CX
MOVL 0(CX), AX // arg 1 attr
MOVL AX, 0(SP)
MOVL CX, 4(SP)
MOVL 4(CX), AX // arg 2 state
MOVL AX, 4(SP)
CALL libc_pthread_attr_setdetachstate(SB)
MOVL BP, SP
POPL BP
MOVL AX, ret+8(FP)
RET
TEXT runtime·pthread_create_trampoline(SB),NOSPLIT,$0-20
MOVL t+0(FP), AX
MOVL attr+4(FP), CX
MOVL start+8(FP), DX
MOVL arg+12(FP), BX
TEXT runtime·pthread_create_trampoline(SB),NOSPLIT,$0
PUSHL BP
MOVL SP, BP
SUBL $16, SP
ANDL $~15, SP
SUBL $24, SP
MOVL 32(SP), CX
LEAL 16(SP), AX // arg "0" &threadid (which we throw away)
MOVL AX, 0(SP)
MOVL CX, 4(SP)
MOVL DX, 8(SP)
MOVL BX, 12(SP)
MOVL 0(CX), AX // arg 1 attr
MOVL AX, 4(SP)
MOVL 4(CX), AX // arg 2 start
MOVL AX, 8(SP)
MOVL 8(CX), AX // arg 3 arg
MOVL AX, 12(SP)
CALL libc_pthread_create(SB)
MOVL BP, SP
POPL BP
MOVL AX, ret+16(FP)
RET
TEXT runtime·pthread_self_trampoline(SB),NOSPLIT,$0-4
TEXT runtime·pthread_self_trampoline(SB),NOSPLIT,$0
PUSHL BP
MOVL SP, BP
ANDL $~15, SP
SUBL $8, SP
CALL libc_pthread_self(SB)
MOVL 16(SP), CX
MOVL AX, (CX) // Save result.
MOVL BP, SP
POPL BP
MOVL AX, ret+0(FP)
RET
TEXT runtime·pthread_kill_trampoline(SB),NOSPLIT,$0-12
MOVL thread+0(FP), AX
MOVL sig+4(FP), CX
TEXT runtime·pthread_kill_trampoline(SB),NOSPLIT,$0
PUSHL BP
MOVL SP, BP
SUBL $8, SP
ANDL $~15, SP
MOVL 16(SP), CX
MOVL 0(CX), AX // arg 1 thread ID
MOVL AX, 0(SP)
MOVL CX, 4(SP)
MOVL 4(CX), AX // arg 2 sig
MOVL AX, 4(SP)
CALL libc_pthread_kill(SB)
MOVL BP, SP
POPL BP
MOVL AX, ret+8(FP)
RET
......@@ -16,70 +16,51 @@
#include "textflag.h"
// Exit the entire program (like C exit)
TEXT runtime·exit(SB),NOSPLIT,$0-4
MOVL code+0(FP), DI // arg 1 exit status
TEXT runtime·exit_trampoline(SB),NOSPLIT,$0
PUSHQ BP
MOVQ SP, BP
ANDQ $~15, SP // align stack
MOVL 0(DI), DI // arg 1 exit status
CALL libc_exit(SB)
MOVL $0xf1, 0xf1 // crash
MOVQ BP, SP
POPQ BP
RET
// Not used on Darwin.
TEXT runtime·exitThread(SB),NOSPLIT,$0-8
MOVL $0xf1, 0xf1 // crash
RET
TEXT runtime·open(SB),NOSPLIT,$0-20
MOVQ name+0(FP), DI // arg 1 pathname
MOVL mode+8(FP), SI // arg 2 flags
MOVL perm+12(FP), DX // arg 3 mode
TEXT runtime·open_trampoline(SB),NOSPLIT,$0
PUSHQ BP
MOVQ SP, BP
ANDQ $~15, SP // align stack
MOVL 8(DI), SI // arg 2 flags
MOVL 12(DI), DX // arg 3 mode
MOVQ 0(DI), DI // arg 1 pathname
CALL libc_open(SB)
MOVQ BP, SP
POPQ BP
MOVL AX, ret+16(FP)
RET
TEXT runtime·closefd(SB),NOSPLIT,$0-12
MOVL fd+0(FP), DI // arg 1 fd
TEXT runtime·close_trampoline(SB),NOSPLIT,$0
PUSHQ BP
MOVQ SP, BP
ANDQ $~15, SP // align stack
MOVL 0(DI), DI // arg 1 fd
CALL libc_close(SB)
MOVQ BP, SP
POPQ BP
MOVL AX, ret+8(FP)
RET
TEXT runtime·read(SB),NOSPLIT,$0-28
MOVL fd+0(FP), DI // arg 1 fd
MOVQ p+8(FP), SI // arg 2 buf
MOVL n+16(FP), DX // arg 3 count
TEXT runtime·read_trampoline(SB),NOSPLIT,$0
PUSHQ BP
MOVQ SP, BP
ANDQ $~15, SP // align stack
MOVQ 8(DI), SI // arg 2 buf
MOVL 16(DI), DX // arg 3 count
MOVL 0(DI), DI // arg 1 fd
CALL libc_read(SB)
MOVQ BP, SP
POPQ BP
MOVL AX, ret+24(FP)
RET
TEXT runtime·write(SB),NOSPLIT,$0-28
MOVQ fd+0(FP), DI // arg 1 fd
MOVQ p+8(FP), SI // arg 2 buf
MOVL n+16(FP), DX // arg 3 count
TEXT runtime·write_trampoline(SB),NOSPLIT,$0
PUSHQ BP
MOVQ SP, BP
ANDQ $~15, SP // align stack
MOVQ 8(DI), SI // arg 2 buf
MOVL 16(DI), DX // arg 3 count
MOVQ 0(DI), DI // arg 1 fd
CALL libc_write(SB)
MOVQ BP, SP
POPQ BP
MOVL AX, ret+24(FP)
RET
TEXT runtime·raiseproc(SB),NOSPLIT,$24
......@@ -100,16 +81,14 @@ TEXT runtime·setitimer(SB), NOSPLIT, $0
SYSCALL
RET
TEXT runtime·madvise(SB), NOSPLIT, $0-20
MOVQ addr+0(FP), DI // arg 1 addr
MOVQ n+8(FP), SI // arg 2 len
MOVL flags+16(FP), DX // arg 3 advice
TEXT runtime·madvise_trampoline(SB), NOSPLIT, $0
PUSHQ BP
MOVQ SP, BP
ANDQ $~15, SP
MOVQ 8(DI), SI // arg 2 len
MOVL 16(DI), DX // arg 3 advice
MOVQ 0(DI), DI // arg 1 addr
CALL libc_madvise(SB)
// ignore failure - maybe pages are locked
MOVQ BP, SP
POPQ BP
RET
......@@ -357,16 +336,18 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$40
SYSCALL
INT $3 // not reached
TEXT runtime·mmap(SB),NOSPLIT,$0-48
MOVQ addr+0(FP), DI // arg 1 addr
MOVQ n+8(FP), SI // arg 2 len
MOVL prot+16(FP), DX // arg 3 prot
MOVL flags+20(FP), CX // arg 4 flags
MOVL fd+24(FP), R8 // arg 5 fid
MOVL off+28(FP), R9 // arg 6 offset
PUSHQ BP
TEXT runtime·mmap_trampoline(SB),NOSPLIT,$0
PUSHQ BP // make a frame; keep stack aligned
MOVQ SP, BP
ANDQ $~15, SP
MOVQ DI, BX
MOVQ 0(BX), DI // arg 1 addr
MOVQ 8(BX), SI // arg 2 len
MOVL 16(BX), DX // arg 3 prot
MOVL 20(BX), CX // arg 4 flags
MOVL 24(BX), R8 // arg 5 fid
MOVL 28(BX), R9 // arg 6 offset
CALL libc_mmap(SB)
XORL DX, DX
CMPQ AX, $-1
......@@ -375,23 +356,20 @@ TEXT runtime·mmap(SB),NOSPLIT,$0-48
MOVQ (AX), DX // errno
XORL AX, AX
ok:
MOVQ BP, SP
MOVQ AX, 32(BX)
MOVQ DX, 40(BX)
POPQ BP
MOVQ AX, p+32(FP)
MOVQ DX, err+40(FP)
RET
TEXT runtime·munmap(SB),NOSPLIT,$0-16
MOVQ addr+0(FP), DI // arg 1 addr
MOVQ n+8(FP), SI // arg 2 len
TEXT runtime·munmap_trampoline(SB),NOSPLIT,$0
PUSHQ BP
MOVQ SP, BP
ANDQ $~15, SP
MOVQ 8(DI), SI // arg 2 len
MOVQ 0(DI), DI // arg 1 addr
CALL libc_munmap(SB)
TESTQ AX, AX
JEQ 2(PC)
MOVL $0xf1, 0xf1 // crash
MOVQ BP, SP
POPQ BP
RET
......@@ -404,13 +382,11 @@ TEXT runtime·sigaltstack(SB),NOSPLIT,$0
MOVL $0xf1, 0xf1 // crash
RET
TEXT runtime·usleep(SB),NOSPLIT,$0-4
MOVL usec+0(FP), DI
TEXT runtime·usleep_trampoline(SB),NOSPLIT,$0
PUSHQ BP
MOVQ SP, BP
ANDQ $~15, SP
MOVL 0(DI), DI // arg 1 usec
CALL libc_usleep(SB)
MOVQ BP, SP
POPQ BP
RET
......@@ -568,74 +544,64 @@ TEXT runtime·mstart_stub(SB),NOSPLIT,$0
XORL AX, AX
RET
// These trampolines convert from Go calling convention to C calling convention.
TEXT runtime·pthread_attr_init_trampoline(SB),NOSPLIT,$0-12
MOVQ attr+0(FP), DI
PUSHQ BP // save BP
MOVQ SP, BP // save SP
ANDQ $~15, SP // align stack to 16 bytes
// These trampolines help convert from Go calling convention to C calling convention.
// They should be called with asmcgocall.
// A pointer to the arguments is passed in DI.
// A single int32 result is returned in AX.
// (For more results, make an args/results structure.)
TEXT runtime·pthread_attr_init_trampoline(SB),NOSPLIT,$0
PUSHQ BP // make frame, keep stack 16-byte aligned.
MOVQ SP, BP
MOVQ 0(DI), DI // arg 1 attr
CALL libc_pthread_attr_init(SB)
MOVQ BP, SP // restore SP
POPQ BP // restore BP
MOVL AX, ret+8(FP)
POPQ BP
RET
TEXT runtime·pthread_attr_setstacksize_trampoline(SB),NOSPLIT,$0-20
MOVQ attr+0(FP), DI
MOVQ size+8(FP), SI
TEXT runtime·pthread_attr_setstacksize_trampoline(SB),NOSPLIT,$0
PUSHQ BP
MOVQ SP, BP
ANDQ $~15, SP
MOVQ 8(DI), SI // arg 2 size
MOVQ 0(DI), DI // arg 1 attr
CALL libc_pthread_attr_setstacksize(SB)
MOVQ BP, SP
POPQ BP
MOVL AX, ret+16(FP)
RET
TEXT runtime·pthread_attr_setdetachstate_trampoline(SB),NOSPLIT,$0-20
MOVQ attr+0(FP), DI
MOVQ state+8(FP), SI
TEXT runtime·pthread_attr_setdetachstate_trampoline(SB),NOSPLIT,$0
PUSHQ BP
MOVQ SP, BP
ANDQ $~15, SP
MOVQ 8(DI), SI // arg 2 state
MOVQ 0(DI), DI // arg 1 attr
CALL libc_pthread_attr_setdetachstate(SB)
MOVQ BP, SP
POPQ BP
MOVL AX, ret+16(FP)
RET
TEXT runtime·pthread_create_trampoline(SB),NOSPLIT,$0-36
MOVQ t+0(FP), DI
MOVQ attr+8(FP), SI
MOVQ start+16(FP), DX
MOVQ arg+24(FP), CX
TEXT runtime·pthread_create_trampoline(SB),NOSPLIT,$0
PUSHQ BP
MOVQ SP, BP
ANDQ $~15, SP
SUBQ $16, SP
MOVQ 0(DI), SI // arg 2 attr
MOVQ 8(DI), DX // arg 3 start
MOVQ 16(DI), CX // arg 4 arg
MOVQ SP, DI // arg 1 &threadid (which we throw away)
CALL libc_pthread_create(SB)
MOVQ BP, SP
POPQ BP
MOVL AX, ret+32(FP)
RET
TEXT runtime·pthread_self_trampoline(SB),NOSPLIT,$0-8
TEXT runtime·pthread_self_trampoline(SB),NOSPLIT,$0
PUSHQ BP
MOVQ SP, BP
ANDQ $~15, SP
MOVQ DI, BX // Note: asmcgocall doesn't save anything in BX, so it is ok to clobber it here.
CALL libc_pthread_self(SB)
MOVQ BP, SP
MOVQ AX, 0(BX) // Save result.
POPQ BP
MOVQ AX, ret+0(FP)
RET
TEXT runtime·pthread_kill_trampoline(SB),NOSPLIT,$0-20
MOVQ thread+0(FP), DI
MOVQ sig+8(FP), SI
TEXT runtime·pthread_kill_trampoline(SB),NOSPLIT,$0
PUSHQ BP
MOVQ SP, BP
ANDQ $~15, SP
MOVQ 8(DI), SI // arg 2 signal
MOVQ 0(DI), DI // arg 1 thread
CALL libc_pthread_kill(SB)
MOVQ BP, SP
POPQ BP
MOVL AX, ret+16(FP)
RET
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment