]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: fix arm/arm64/ppc64/mips64 to dropm when necessary
authorIan Lance Taylor <iant@golang.org>
Sat, 9 Jan 2016 00:56:02 +0000 (16:56 -0800)
committerIan Lance Taylor <iant@golang.org>
Mon, 11 Jan 2016 18:46:54 +0000 (18:46 +0000)
Fixes #13881.

Change-Id: Idff77db381640184ddd2b65022133bb226168800
Reviewed-on: https://go-review.googlesource.com/18449
Reviewed-by: David Crawshaw <crawshaw@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>

src/runtime/asm_arm.s
src/runtime/asm_arm64.s
src/runtime/asm_mips64x.s
src/runtime/asm_ppc64x.s
src/runtime/crash_cgo_test.go
src/runtime/proc.go
src/runtime/testdata/testprogcgo/dropm.go [new file with mode: 0644]
src/runtime/testdata/testprogcgo/dropm_stub.go [new file with mode: 0644]

index d8757fd0b91a05ce03dcea9292d7d870ec9d4dd3..09fbc952e09273a9baf6fad86076737128238907 100644 (file)
@@ -556,7 +556,13 @@ TEXT       ·cgocallback_gofunc(SB),NOSPLIT,$8-12
        // lots of space, but the linker doesn't know. Hide the call from
        // the linker analysis by using an indirect call.
        CMP     $0, g
-       B.NE    havem
+       B.EQ    needm
+
+       MOVW    g_m(g), R8
+       MOVW    R8, savedm-4(SP)
+       B       havem
+
+needm:
        MOVW    g, savedm-4(SP) // g is zero, so is m.
        MOVW    $runtime·needm(SB), R0
        BL      (R0)
@@ -577,8 +583,6 @@ TEXT        ·cgocallback_gofunc(SB),NOSPLIT,$8-12
        MOVW    R13, (g_sched+gobuf_sp)(R3)
 
 havem:
-       MOVW    g_m(g), R8
-       MOVW    R8, savedm-4(SP)
        // Now there's a valid m, and we're running on its m->g0.
        // Save current m->g0->sched.sp on stack and then set it to SP.
        // Save current sp in m->g0->sched.sp in preparation for
index 732abe13af1829d2ccb18dd4aa891da56127eee9..ab5d5b5e5f54b2f03b0e4dbacaeeadc6ea4576f6 100644 (file)
@@ -586,7 +586,13 @@ nocgo:
        // lots of space, but the linker doesn't know. Hide the call from
        // the linker analysis by using an indirect call.
        CMP     $0, g
-       BNE     havem
+       BEQ     needm
+
+       MOVD    g_m(g), R8
+       MOVD    R8, savedm-8(SP)
+       B       havem
+
+needm:
        MOVD    g, savedm-8(SP) // g is zero, so is m.
        MOVD    $runtime·needm(SB), R0
        BL      (R0)
@@ -608,8 +614,6 @@ nocgo:
        MOVD    R0, (g_sched+gobuf_sp)(R3)
 
 havem:
-       MOVD    g_m(g), R8
-       MOVD    R8, savedm-8(SP)
        // Now there's a valid m, and we're running on its m->g0.
        // Save current m->g0->sched.sp on stack and then set it to SP.
        // Save current sp in m->g0->sched.sp in preparation for
index 7d3d7c2ae2df8eef34bcc466524e86007b7e98b6..08482fed23e619ee2b388ee81599999eb1ceaf70 100644 (file)
@@ -486,7 +486,13 @@ nocgo:
        // In this case, we're running on the thread stack, so there's
        // lots of space, but the linker doesn't know. Hide the call from
        // the linker analysis by using an indirect call.
-       BNE     g, havem
+       BEQ     g, needm
+
+       MOVV    g_m(g), R3
+       MOVV    R3, savedm-8(SP)
+       JMP     havem
+
+needm:
        MOVV    g, savedm-8(SP) // g is zero, so is m.
        MOVV    $runtime·needm(SB), R4
        JAL     (R4)
@@ -507,8 +513,6 @@ nocgo:
        MOVV    R29, (g_sched+gobuf_sp)(R1)
 
 havem:
-       MOVV    g_m(g), R3
-       MOVV    R3, savedm-8(SP)
        // Now there's a valid m, and we're running on its m->g0.
        // Save current m->g0->sched.sp on stack and then set it to SP.
        // Save current sp in m->g0->sched.sp in preparation for
index f3b193ae314b1f6804cb5fa92243febc424abe87..6d003b04e162888cebd59193456a52d662ce5194 100644 (file)
@@ -602,7 +602,13 @@ nocgo:
        // lots of space, but the linker doesn't know. Hide the call from
        // the linker analysis by using an indirect call.
        CMP     g, $0
-       BNE     havem
+       BEQ     needm
+
+       MOVD    g_m(g), R8
+       MOVD    R8, savedm-8(SP)
+       BR      havem
+
+needm:
        MOVD    g, savedm-8(SP) // g is zero, so is m.
        MOVD    $runtime·needm(SB), R12
        MOVD    R12, CTR
@@ -624,8 +630,6 @@ nocgo:
        MOVD    R1, (g_sched+gobuf_sp)(R3)
 
 havem:
-       MOVD    g_m(g), R8
-       MOVD    R8, savedm-8(SP)
        // Now there's a valid m, and we're running on its m->g0.
        // Save current m->g0->sched.sp on stack and then set it to SP.
        // Save current sp in m->g0->sched.sp in preparation for
index 9422a086205b8b2aacda656b7b2472684d06ce0f..92b4f0ca71c921173df66f02c037e76b0fbe3fa1 100644 (file)
@@ -134,3 +134,12 @@ func TestCgoExecSignalMask(t *testing.T) {
                t.Errorf("expected %q, got %v", want, got)
        }
 }
+
+func TestEnsureDropM(t *testing.T) {
+       // Test for issue 13881.
+       got := runTestProg(t, "testprogcgo", "EnsureDropM")
+       want := "OK\n"
+       if got != want {
+               t.Errorf("expected %q, got %v", want, got)
+       }
+}
index b14aabde3dc6c600dbe4c6eb32a10a5d25cc0c8a..545e134cc2104e637297c3b9882ac072fe420af3 100644 (file)
@@ -1443,6 +1443,11 @@ func dropm() {
        unlockextra(mp)
 }
 
+// A helper function for EnsureDropM.
+func getm() uintptr {
+       return uintptr(unsafe.Pointer(getg().m))
+}
+
 var extram uintptr
 
 // lockextra locks the extra list and returns the list head.
diff --git a/src/runtime/testdata/testprogcgo/dropm.go b/src/runtime/testdata/testprogcgo/dropm.go
new file mode 100644 (file)
index 0000000..80ccdcc
--- /dev/null
@@ -0,0 +1,57 @@
+// Copyright 2016 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test that a sequence of callbacks from C to Go get the same m.
+// This failed to be true on arm and arm64, which was the root cause
+// of issue 13881.
+
+package main
+
+/*
+#include <stddef.h>
+#include <pthread.h>
+
+extern void GoCheckM();
+
+static void* thread(void* arg __attribute__ ((unused))) {
+       GoCheckM();
+       return NULL;
+}
+
+static void CheckM() {
+       pthread_t tid;
+       pthread_create(&tid, NULL, thread, NULL);
+       pthread_join(tid, NULL);
+       pthread_create(&tid, NULL, thread, NULL);
+       pthread_join(tid, NULL);
+}
+*/
+import "C"
+
+import (
+       "fmt"
+       "os"
+)
+
+func init() {
+       register("EnsureDropM", EnsureDropM)
+}
+
+var savedM uintptr
+
+//export GoCheckM
+func GoCheckM() {
+       m := runtime_getm_for_test()
+       if savedM == 0 {
+               savedM = m
+       } else if savedM != m {
+               fmt.Printf("m == %x want %x\n", m, savedM)
+               os.Exit(1)
+       }
+}
+
+func EnsureDropM() {
+       C.CheckM()
+       fmt.Println("OK")
+}
diff --git a/src/runtime/testdata/testprogcgo/dropm_stub.go b/src/runtime/testdata/testprogcgo/dropm_stub.go
new file mode 100644 (file)
index 0000000..4c3f46a
--- /dev/null
@@ -0,0 +1,11 @@
+// Copyright 2016 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import _ "unsafe" // for go:linkname
+
+// Defined in the runtime package.
+//go:linkname runtime_getm_for_test runtime.getm
+func runtime_getm_for_test() uintptr