Skip to content

Commit 9e9ff56

Browse files
labogerbradfitz
authored andcommitted
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 <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Bryan C. Mills <[email protected]> Reviewed-by: Brad Fitzpatrick <[email protected]>
1 parent 1de0dcf commit 9e9ff56

File tree

13 files changed

+622
-27
lines changed

13 files changed

+622
-27
lines changed

src/cmd/compile/internal/gc/builtin.go

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/cmd/compile/internal/gc/builtin/runtime.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,7 @@ func complex128div(num complex128, den complex128) (quo complex128)
183183

184184
// race detection
185185
func racefuncenter(uintptr)
186+
func racefuncenterfp()
186187
func racefuncexit()
187188
func raceread(uintptr)
188189
func racewrite(uintptr)

src/cmd/compile/internal/gc/racewalk.go

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package gc
77
import (
88
"cmd/compile/internal/types"
99
"cmd/internal/src"
10+
"cmd/internal/sys"
1011
)
1112

1213
// The racewalk pass is currently handled in two parts.
@@ -58,17 +59,23 @@ func instrument(fn *Node) {
5859
lno := lineno
5960
lineno = src.NoXPos
6061

61-
// nodpc is the PC of the caller as extracted by
62-
// getcallerpc. We use -widthptr(FP) for x86.
63-
// BUG: this will not work on arm.
64-
nodpc := nodfp.copy()
65-
nodpc.Type = types.Types[TUINTPTR]
66-
nodpc.Xoffset = int64(-Widthptr)
67-
fn.Func.Dcl = append(fn.Func.Dcl, nodpc)
68-
69-
fn.Func.Enter.Prepend(mkcall("racefuncenter", nil, nil, nodpc))
70-
fn.Func.Exit.Append(mkcall("racefuncexit", nil, nil))
62+
if thearch.LinkArch.Arch == sys.ArchPPC64LE {
63+
fn.Func.Enter.Prepend(mkcall("racefuncenterfp", nil, nil))
64+
fn.Func.Exit.Append(mkcall("racefuncexit", nil, nil))
65+
} else {
7166

67+
// nodpc is the PC of the caller as extracted by
68+
// getcallerpc. We use -widthptr(FP) for x86.
69+
// BUG: This only works for amd64. This will not
70+
// work on arm or others that might support
71+
// race in the future.
72+
nodpc := nodfp.copy()
73+
nodpc.Type = types.Types[TUINTPTR]
74+
nodpc.Xoffset = int64(-Widthptr)
75+
fn.Func.Dcl = append(fn.Func.Dcl, nodpc)
76+
fn.Func.Enter.Prepend(mkcall("racefuncenter", nil, nil, nodpc))
77+
fn.Func.Exit.Append(mkcall("racefuncexit", nil, nil))
78+
}
7279
lineno = lno
7380
}
7481
}

src/cmd/dist/test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,6 @@ func (t *tester) registerStdTest(pkg string) {
312312
break
313313
}
314314
}
315-
316315
args := []string{
317316
"test",
318317
short(),
@@ -355,7 +354,8 @@ func (t *tester) registerRaceBenchTest(pkg string) {
355354
"test",
356355
short(),
357356
"-race",
358-
"-run=^$", // nothing. only benchmarks.
357+
t.timeout(1200), // longer timeout for race with benchmarks
358+
"-run=^$", // nothing. only benchmarks.
359359
"-benchtime=.1s",
360360
"-cpu=4",
361361
}
@@ -1318,7 +1318,7 @@ func (t *tester) raceDetectorSupported() bool {
13181318
case "linux", "darwin", "freebsd", "windows":
13191319
// The race detector doesn't work on Alpine Linux:
13201320
// golang.org/issue/14481
1321-
return t.cgoEnabled && goarch == "amd64" && gohostos == goos && !isAlpineLinux()
1321+
return t.cgoEnabled && (goarch == "amd64" || goarch == "ppc64le") && gohostos == goos && !isAlpineLinux()
13221322
}
13231323
return false
13241324
}

src/cmd/go/internal/work/init.go

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,16 @@ func instrumentInit() {
4343
fmt.Fprintf(os.Stderr, "-msan is not supported on %s/%s\n", cfg.Goos, cfg.Goarch)
4444
os.Exit(2)
4545
}
46-
if cfg.BuildRace && (cfg.Goarch != "amd64" || cfg.Goos != "linux" && cfg.Goos != "freebsd" && cfg.Goos != "darwin" && cfg.Goos != "windows") {
47-
fmt.Fprintf(os.Stderr, "go %s: -race is only supported on linux/amd64, freebsd/amd64, darwin/amd64 and windows/amd64\n", flag.Args()[0])
48-
os.Exit(2)
46+
if cfg.BuildRace {
47+
platform := cfg.Goos + "/" + cfg.Goarch
48+
switch platform {
49+
default:
50+
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])
51+
os.Exit(2)
52+
case "linux/amd64", "linux/ppc64le", "freebsd/amd64", "darwin/amd64", "windows/amd64":
53+
// race supported on these platforms
54+
}
4955
}
50-
5156
mode := "race"
5257
if cfg.BuildMSan {
5358
mode = "msan"

src/cmd/internal/obj/ppc64/obj9.go

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -502,7 +502,10 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
502502
q = c.stacksplit(q, autosize) // emit split check
503503
}
504504

505-
if autosize != 0 {
505+
// Special handling of the racecall thunk. Assume that its asm code will
506+
// save the link register and update the stack, since that code is
507+
// called directly from C/C++ and can't clobber REGTMP (R31).
508+
if autosize != 0 && c.cursym.Name != "runtime.racecallbackthunk" {
506509
// Save the link register and update the SP. MOVDU is used unless
507510
// the frame size is too large. The link register must be saved
508511
// 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) {
678681
retTarget := p.To.Sym
679682

680683
if c.cursym.Func.Text.Mark&LEAF != 0 {
681-
if autosize == 0 {
684+
if autosize == 0 || c.cursym.Name == "runtime.racecallbackthunk" {
682685
p.As = ABR
683686
p.From = obj.Addr{}
684687
if retTarget == nil {
@@ -747,8 +750,8 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
747750
p.Link = q
748751
p = q
749752
}
750-
751-
if autosize != 0 {
753+
prev := p
754+
if autosize != 0 && c.cursym.Name != "runtime.racecallbackthunk" {
752755
q = c.newprog()
753756
q.As = AADD
754757
q.Pos = p.Pos
@@ -759,7 +762,8 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
759762
q.Spadj = -autosize
760763

761764
q.Link = p.Link
762-
p.Link = q
765+
prev.Link = q
766+
prev = q
763767
}
764768

765769
q1 = c.newprog()
@@ -776,7 +780,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
776780
q1.Spadj = +autosize
777781

778782
q1.Link = q.Link
779-
q.Link = q1
783+
prev.Link = q1
780784
case AADD:
781785
if p.To.Type == obj.TYPE_REG && p.To.Reg == REGSP && p.From.Type == obj.TYPE_CONST {
782786
p.Spadj = int32(-p.From.Offset)

src/cmd/link/internal/ld/config.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,13 @@ func mustLinkExternal(ctxt *Link) (res bool, reason string) {
196196
return true, objabi.GOARCH + " does not support internal cgo"
197197
}
198198

199+
// When the race flag is set, the LLVM tsan relocatable file is linked
200+
// into the final binary, which means external linking is required because
201+
// internal linking does not support it.
202+
if *flagRace && ctxt.Arch.InFamily(sys.PPC64) {
203+
return true, "race on ppc64le"
204+
}
205+
199206
// Some build modes require work the internal linker cannot do (yet).
200207
switch ctxt.BuildMode {
201208
case BuildModeCArchive:

src/race.bash

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
set -e
1010

1111
function usage {
12-
echo 'race detector is only supported on linux/amd64, freebsd/amd64 and darwin/amd64' 1>&2
12+
echo 'race detector is only supported on linux/amd64, linux/ppc64le, freebsd/amd64 and darwin/amd64' 1>&2
1313
exit 1
1414
}
1515

@@ -21,7 +21,7 @@ case $(uname) in
2121
fi
2222
;;
2323
"Linux")
24-
if [ $(uname -m) != "x86_64" ]; then
24+
if [ $(uname -m) != "x86_64" ] && [ $(uname -m) != "ppc64le" ]; then
2525
usage
2626
fi
2727
;;

src/runtime/asm_ppc64x.s

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ TEXT runtime·rt0_go(SB),NOSPLIT,$0
2424
// create istack out of the given (operating system) stack.
2525
// _cgo_init may update stackguard.
2626
MOVD $runtime·g0(SB), g
27+
BL runtime·save_g(SB)
2728
MOVD $(-64*1024), R31
2829
ADD R31, R1, R3
2930
MOVD R3, g_stackguard0(g)

src/runtime/race.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,7 @@ var racearenastart uintptr
292292
var racearenaend uintptr
293293

294294
func racefuncenter(uintptr)
295+
func racefuncenterfp()
295296
func racefuncexit()
296297
func racereadrangepc1(uintptr, uintptr, uintptr)
297298
func racewriterangepc1(uintptr, uintptr, uintptr)

src/runtime/race/race.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// Use of this source code is governed by a BSD-style
33
// license that can be found in the LICENSE file.
44

5-
// +build race,linux,amd64 race,freebsd,amd64 race,darwin,amd64 race,windows,amd64
5+
// +build race,linux,amd64 race,freebsd,amd64 race,darwin,amd64 race,windows,amd64 race,linux,ppc64le
66

77
package race
88

0 commit comments

Comments
 (0)