mirror of
https://github.com/golang/go.git
synced 2025-05-30 19:52:53 +00:00
runtime: fix arm/arm64/ppc64/mips64 to dropm when necessary
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>
This commit is contained in:
parent
9439fa1078
commit
c02aa463db
@ -556,7 +556,13 @@ TEXT ·cgocallback_gofunc(SB),NOSPLIT,$8-12
|
|||||||
// lots of space, but the linker doesn't know. Hide the call from
|
// lots of space, but the linker doesn't know. Hide the call from
|
||||||
// the linker analysis by using an indirect call.
|
// the linker analysis by using an indirect call.
|
||||||
CMP $0, g
|
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 g, savedm-4(SP) // g is zero, so is m.
|
||||||
MOVW $runtime·needm(SB), R0
|
MOVW $runtime·needm(SB), R0
|
||||||
BL (R0)
|
BL (R0)
|
||||||
@ -577,8 +583,6 @@ TEXT ·cgocallback_gofunc(SB),NOSPLIT,$8-12
|
|||||||
MOVW R13, (g_sched+gobuf_sp)(R3)
|
MOVW R13, (g_sched+gobuf_sp)(R3)
|
||||||
|
|
||||||
havem:
|
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.
|
// 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 m->g0->sched.sp on stack and then set it to SP.
|
||||||
// Save current sp in m->g0->sched.sp in preparation for
|
// Save current sp in m->g0->sched.sp in preparation for
|
||||||
|
@ -586,7 +586,13 @@ nocgo:
|
|||||||
// lots of space, but the linker doesn't know. Hide the call from
|
// lots of space, but the linker doesn't know. Hide the call from
|
||||||
// the linker analysis by using an indirect call.
|
// the linker analysis by using an indirect call.
|
||||||
CMP $0, g
|
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 g, savedm-8(SP) // g is zero, so is m.
|
||||||
MOVD $runtime·needm(SB), R0
|
MOVD $runtime·needm(SB), R0
|
||||||
BL (R0)
|
BL (R0)
|
||||||
@ -608,8 +614,6 @@ nocgo:
|
|||||||
MOVD R0, (g_sched+gobuf_sp)(R3)
|
MOVD R0, (g_sched+gobuf_sp)(R3)
|
||||||
|
|
||||||
havem:
|
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.
|
// 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 m->g0->sched.sp on stack and then set it to SP.
|
||||||
// Save current sp in m->g0->sched.sp in preparation for
|
// Save current sp in m->g0->sched.sp in preparation for
|
||||||
|
@ -486,7 +486,13 @@ nocgo:
|
|||||||
// In this case, we're running on the thread stack, so there's
|
// 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
|
// lots of space, but the linker doesn't know. Hide the call from
|
||||||
// the linker analysis by using an indirect call.
|
// 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 g, savedm-8(SP) // g is zero, so is m.
|
||||||
MOVV $runtime·needm(SB), R4
|
MOVV $runtime·needm(SB), R4
|
||||||
JAL (R4)
|
JAL (R4)
|
||||||
@ -507,8 +513,6 @@ nocgo:
|
|||||||
MOVV R29, (g_sched+gobuf_sp)(R1)
|
MOVV R29, (g_sched+gobuf_sp)(R1)
|
||||||
|
|
||||||
havem:
|
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.
|
// 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 m->g0->sched.sp on stack and then set it to SP.
|
||||||
// Save current sp in m->g0->sched.sp in preparation for
|
// Save current sp in m->g0->sched.sp in preparation for
|
||||||
|
@ -602,7 +602,13 @@ nocgo:
|
|||||||
// lots of space, but the linker doesn't know. Hide the call from
|
// lots of space, but the linker doesn't know. Hide the call from
|
||||||
// the linker analysis by using an indirect call.
|
// the linker analysis by using an indirect call.
|
||||||
CMP g, $0
|
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 g, savedm-8(SP) // g is zero, so is m.
|
||||||
MOVD $runtime·needm(SB), R12
|
MOVD $runtime·needm(SB), R12
|
||||||
MOVD R12, CTR
|
MOVD R12, CTR
|
||||||
@ -624,8 +630,6 @@ nocgo:
|
|||||||
MOVD R1, (g_sched+gobuf_sp)(R3)
|
MOVD R1, (g_sched+gobuf_sp)(R3)
|
||||||
|
|
||||||
havem:
|
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.
|
// 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 m->g0->sched.sp on stack and then set it to SP.
|
||||||
// Save current sp in m->g0->sched.sp in preparation for
|
// Save current sp in m->g0->sched.sp in preparation for
|
||||||
|
@ -134,3 +134,12 @@ func TestCgoExecSignalMask(t *testing.T) {
|
|||||||
t.Errorf("expected %q, got %v", want, got)
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1443,6 +1443,11 @@ func dropm() {
|
|||||||
unlockextra(mp)
|
unlockextra(mp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A helper function for EnsureDropM.
|
||||||
|
func getm() uintptr {
|
||||||
|
return uintptr(unsafe.Pointer(getg().m))
|
||||||
|
}
|
||||||
|
|
||||||
var extram uintptr
|
var extram uintptr
|
||||||
|
|
||||||
// lockextra locks the extra list and returns the list head.
|
// lockextra locks the extra list and returns the list head.
|
||||||
|
57
src/runtime/testdata/testprogcgo/dropm.go
vendored
Normal file
57
src/runtime/testdata/testprogcgo/dropm.go
vendored
Normal file
@ -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")
|
||||||
|
}
|
11
src/runtime/testdata/testprogcgo/dropm_stub.go
vendored
Normal file
11
src/runtime/testdata/testprogcgo/dropm_stub.go
vendored
Normal file
@ -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
|
Loading…
x
Reference in New Issue
Block a user