Commit 9e9ff565 authored by Lynn Boger's avatar Lynn Boger Committed by Brad Fitzpatrick

runtime/race: implement race detector for ppc64le

This adds the support to enable the race detector for ppc64le.

Added runtime/race_ppc64le.s to manage the calls from Go to the
LLVM tsan functions, mostly converting from the Go ABI to the
PPC64 ABI expected by Clang generated code.

Changed racewalk.go to call racefuncenterfp instead of racefuncenter
on ppc64le to allow the caller pc to be obtained in the asm code
before calling the tsan version.

Changed the set up code for racecallbackthunk so it doesn't use
the autogenerated save and restore of the link register since that
sequence uses registers inconsistent with the normal ppc64 ABI.

Made various changes to recognize that race is supported for
ppc64le.

Ensured that tls_g is updated and accessible from race_linux_ppc64le.s
so that the race ctx can be obtained and passed to tsan functions.

This enables the race tests for ppc64le in cmd/dist/test.go and
increases the timeout when running the benchmarks with the -race
option to avoid timing out.

Updates #24354, #23731

Change-Id: Ib97dc7ac313e6313c836dc7d2fb698f9d8fba3ef
Reviewed-on: https://go-review.googlesource.com/107935
Run-TryBot: Lynn Boger <laboger@linux.vnet.ibm.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: 's avatarBryan C. Mills <bcmills@google.com>
Reviewed-by: 's avatarBrad Fitzpatrick <bradfitz@golang.org>
parent 1de0dcfc
......@@ -141,6 +141,7 @@ var runtimeDecls = [...]struct {
{"uint32tofloat64", funcTag, 109},
{"complex128div", funcTag, 110},
{"racefuncenter", funcTag, 111},
{"racefuncenterfp", funcTag, 5},
{"racefuncexit", funcTag, 5},
{"raceread", funcTag, 111},
{"racewrite", funcTag, 111},
......
......@@ -183,6 +183,7 @@ func complex128div(num complex128, den complex128) (quo complex128)
// race detection
func racefuncenter(uintptr)
func racefuncenterfp()
func racefuncexit()
func raceread(uintptr)
func racewrite(uintptr)
......
......@@ -7,6 +7,7 @@ package gc
import (
"cmd/compile/internal/types"
"cmd/internal/src"
"cmd/internal/sys"
)
// The racewalk pass is currently handled in two parts.
......@@ -58,17 +59,23 @@ func instrument(fn *Node) {
lno := lineno
lineno = src.NoXPos
// nodpc is the PC of the caller as extracted by
// getcallerpc. We use -widthptr(FP) for x86.
// BUG: this will not work on arm.
nodpc := nodfp.copy()
nodpc.Type = types.Types[TUINTPTR]
nodpc.Xoffset = int64(-Widthptr)
fn.Func.Dcl = append(fn.Func.Dcl, nodpc)
fn.Func.Enter.Prepend(mkcall("racefuncenter", nil, nil, nodpc))
fn.Func.Exit.Append(mkcall("racefuncexit", nil, nil))
if thearch.LinkArch.Arch == sys.ArchPPC64LE {
fn.Func.Enter.Prepend(mkcall("racefuncenterfp", nil, nil))
fn.Func.Exit.Append(mkcall("racefuncexit", nil, nil))
} else {
// nodpc is the PC of the caller as extracted by
// getcallerpc. We use -widthptr(FP) for x86.
// BUG: This only works for amd64. This will not
// work on arm or others that might support
// race in the future.
nodpc := nodfp.copy()
nodpc.Type = types.Types[TUINTPTR]
nodpc.Xoffset = int64(-Widthptr)
fn.Func.Dcl = append(fn.Func.Dcl, nodpc)
fn.Func.Enter.Prepend(mkcall("racefuncenter", nil, nil, nodpc))
fn.Func.Exit.Append(mkcall("racefuncexit", nil, nil))
}
lineno = lno
}
}
......@@ -312,7 +312,6 @@ func (t *tester) registerStdTest(pkg string) {
break
}
}
args := []string{
"test",
short(),
......@@ -355,7 +354,8 @@ func (t *tester) registerRaceBenchTest(pkg string) {
"test",
short(),
"-race",
"-run=^$", // nothing. only benchmarks.
t.timeout(1200), // longer timeout for race with benchmarks
"-run=^$", // nothing. only benchmarks.
"-benchtime=.1s",
"-cpu=4",
}
......@@ -1318,7 +1318,7 @@ func (t *tester) raceDetectorSupported() bool {
case "linux", "darwin", "freebsd", "windows":
// The race detector doesn't work on Alpine Linux:
// golang.org/issue/14481
return t.cgoEnabled && goarch == "amd64" && gohostos == goos && !isAlpineLinux()
return t.cgoEnabled && (goarch == "amd64" || goarch == "ppc64le") && gohostos == goos && !isAlpineLinux()
}
return false
}
......
......@@ -43,11 +43,16 @@ func instrumentInit() {
fmt.Fprintf(os.Stderr, "-msan is not supported on %s/%s\n", cfg.Goos, cfg.Goarch)
os.Exit(2)
}
if cfg.BuildRace && (cfg.Goarch != "amd64" || cfg.Goos != "linux" && cfg.Goos != "freebsd" && cfg.Goos != "darwin" && cfg.Goos != "windows") {
fmt.Fprintf(os.Stderr, "go %s: -race is only supported on linux/amd64, freebsd/amd64, darwin/amd64 and windows/amd64\n", flag.Args()[0])
os.Exit(2)
if cfg.BuildRace {
platform := cfg.Goos + "/" + cfg.Goarch
switch platform {
default:
fmt.Fprintf(os.Stderr, "go %s: -race is only supported on linux/amd64, linux/ppc64le, freebsd/amd64, darwin/amd64 and windows/amd64\n", flag.Args()[0])
os.Exit(2)
case "linux/amd64", "linux/ppc64le", "freebsd/amd64", "darwin/amd64", "windows/amd64":
// race supported on these platforms
}
}
mode := "race"
if cfg.BuildMSan {
mode = "msan"
......
......@@ -502,7 +502,10 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
q = c.stacksplit(q, autosize) // emit split check
}
if autosize != 0 {
// Special handling of the racecall thunk. Assume that its asm code will
// save the link register and update the stack, since that code is
// called directly from C/C++ and can't clobber REGTMP (R31).
if autosize != 0 && c.cursym.Name != "runtime.racecallbackthunk" {
// Save the link register and update the SP. MOVDU is used unless
// the frame size is too large. The link register must be saved
// even for non-empty leaf functions so that traceback works.
......@@ -678,7 +681,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
retTarget := p.To.Sym
if c.cursym.Func.Text.Mark&LEAF != 0 {
if autosize == 0 {
if autosize == 0 || c.cursym.Name == "runtime.racecallbackthunk" {
p.As = ABR
p.From = obj.Addr{}
if retTarget == nil {
......@@ -747,8 +750,8 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
p.Link = q
p = q
}
if autosize != 0 {
prev := p
if autosize != 0 && c.cursym.Name != "runtime.racecallbackthunk" {
q = c.newprog()
q.As = AADD
q.Pos = p.Pos
......@@ -759,7 +762,8 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
q.Spadj = -autosize
q.Link = p.Link
p.Link = q
prev.Link = q
prev = q
}
q1 = c.newprog()
......@@ -776,7 +780,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
q1.Spadj = +autosize
q1.Link = q.Link
q.Link = q1
prev.Link = q1
case AADD:
if p.To.Type == obj.TYPE_REG && p.To.Reg == REGSP && p.From.Type == obj.TYPE_CONST {
p.Spadj = int32(-p.From.Offset)
......
......@@ -196,6 +196,13 @@ func mustLinkExternal(ctxt *Link) (res bool, reason string) {
return true, objabi.GOARCH + " does not support internal cgo"
}
// When the race flag is set, the LLVM tsan relocatable file is linked
// into the final binary, which means external linking is required because
// internal linking does not support it.
if *flagRace && ctxt.Arch.InFamily(sys.PPC64) {
return true, "race on ppc64le"
}
// Some build modes require work the internal linker cannot do (yet).
switch ctxt.BuildMode {
case BuildModeCArchive:
......
......@@ -9,7 +9,7 @@
set -e
function usage {
echo 'race detector is only supported on linux/amd64, freebsd/amd64 and darwin/amd64' 1>&2
echo 'race detector is only supported on linux/amd64, linux/ppc64le, freebsd/amd64 and darwin/amd64' 1>&2
exit 1
}
......@@ -21,7 +21,7 @@ case $(uname) in
fi
;;
"Linux")
if [ $(uname -m) != "x86_64" ]; then
if [ $(uname -m) != "x86_64" ] && [ $(uname -m) != "ppc64le" ]; then
usage
fi
;;
......
......@@ -24,6 +24,7 @@ TEXT runtime·rt0_go(SB),NOSPLIT,$0
// create istack out of the given (operating system) stack.
// _cgo_init may update stackguard.
MOVD $runtime·g0(SB), g
BL runtime·save_g(SB)
MOVD $(-64*1024), R31
ADD R31, R1, R3
MOVD R3, g_stackguard0(g)
......
......@@ -292,6 +292,7 @@ var racearenastart uintptr
var racearenaend uintptr
func racefuncenter(uintptr)
func racefuncenterfp()
func racefuncexit()
func racereadrangepc1(uintptr, uintptr, uintptr)
func racewriterangepc1(uintptr, uintptr, uintptr)
......
......@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build race,linux,amd64 race,freebsd,amd64 race,darwin,amd64 race,windows,amd64
// +build race,linux,amd64 race,freebsd,amd64 race,darwin,amd64 race,windows,amd64 race,linux,ppc64le
package race
......
This diff is collapsed.
......@@ -46,4 +46,4 @@ TEXT runtime·load_g(SB),NOSPLIT|NOFRAME,$0-0
MOVD 0(R13)(R31*1), g
RET
GLOBL runtime·tls_g+0(SB), TLSBSS, $8
GLOBL runtime·tls_g+0(SB), TLSBSS+DUPOK, $8
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