]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: fix darwin 386/amd64 stack switches
authorKeith Randall <khr@golang.org>
Thu, 3 May 2018 17:30:31 +0000 (10:30 -0700)
committerKeith Randall <khr@golang.org>
Sat, 19 May 2018 17:38:01 +0000 (17:38 +0000)
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/111258
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>

src/cmd/link/internal/ld/dwarf_test.go
src/runtime/asm_386.s
src/runtime/mmap.go
src/runtime/os_darwin.go
src/runtime/stubs2.go
src/runtime/sys_darwin.go
src/runtime/sys_darwin_386.s
src/runtime/sys_darwin_amd64.s

index 710a796cc0444a0b43703612b07c73a764c844ef..17deec1735eb7f11e3505d31b741fdd589b2e41c 100644 (file)
@@ -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")
index 63fa17af62faf5ad704344eb32758a7855e3255c..54d5eaa014f13a8cf96995234e51c4cd00b6dd5f 100644 (file)
@@ -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
index 649b4ab1ecf15b9624b0234433b25c4ce2f16ee3..80b89d2ef1cb7d5e9b8acf15e10e2ed0ed582299 100644 (file)
@@ -9,6 +9,8 @@
 // +build !linux !amd64
 // +build !linux !arm64
 // +build !js
+// +build !darwin !amd64
+// +build !darwin !386
 
 package runtime
 
index 613725115d5e752ab310d709b919470d50b182df..4df1fba17d4dcfa9de3bcaf813d2b34c49f498ed 100644 (file)
@@ -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)))
index b25815b3ae3f8f28430f6c89bd190c51107b72bd..2ebcd82cfd587c9da381d6bf7eb481bb446dd884 100644 (file)
@@ -7,6 +7,8 @@
 // +build !windows
 // +build !nacl
 // +build !js
+// +build !darwin !amd64
+// +build !darwin !386
 
 package runtime
 
index 6af52cbab32c54e3cc46e363d8092b5806d3ae12..8757486e220a8b245e0e828bb04b96bd575cbf96 100644 (file)
@@ -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.
index ea6116eb0aa46689d6ef27571ab944488a990a79..16ca3e06ae825db83b3c78b02bd26e924c37ce93 100644 (file)
 #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
index bf5a34a15e3a4f37a99c6682b1a5725d526df4b1..e48145a45090ff5e024a324c95052481eddbf735 100644 (file)
 #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