summaryrefslogtreecommitdiffstats
path: root/src/cmd/compile/internal/gc/racewalk.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/compile/internal/gc/racewalk.go')
-rw-r--r--src/cmd/compile/internal/gc/racewalk.go93
1 files changed, 93 insertions, 0 deletions
diff --git a/src/cmd/compile/internal/gc/racewalk.go b/src/cmd/compile/internal/gc/racewalk.go
new file mode 100644
index 0000000..3552617
--- /dev/null
+++ b/src/cmd/compile/internal/gc/racewalk.go
@@ -0,0 +1,93 @@
+// Copyright 2012 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 gc
+
+import (
+ "cmd/compile/internal/types"
+ "cmd/internal/src"
+ "cmd/internal/sys"
+)
+
+// The racewalk pass is currently handled in three parts.
+//
+// First, for flag_race, it inserts calls to racefuncenter and
+// racefuncexit at the start and end (respectively) of each
+// function. This is handled below.
+//
+// Second, during buildssa, it inserts appropriate instrumentation
+// calls immediately before each memory load or store. This is handled
+// by the (*state).instrument method in ssa.go, so here we just set
+// the Func.InstrumentBody flag as needed. For background on why this
+// is done during SSA construction rather than a separate SSA pass,
+// see issue #19054.
+//
+// Third we remove calls to racefuncenter and racefuncexit, for leaf
+// functions without instrumented operations. This is done as part of
+// ssa opt pass via special rule.
+
+// TODO(dvyukov): do not instrument initialization as writes:
+// a := make([]int, 10)
+
+// Do not instrument the following packages at all,
+// at best instrumentation would cause infinite recursion.
+var omit_pkgs = []string{
+ "runtime/internal/atomic",
+ "runtime/internal/sys",
+ "runtime/internal/math",
+ "runtime",
+ "runtime/race",
+ "runtime/msan",
+ "internal/cpu",
+}
+
+// Don't insert racefuncenterfp/racefuncexit into the following packages.
+// Memory accesses in the packages are either uninteresting or will cause false positives.
+var norace_inst_pkgs = []string{"sync", "sync/atomic"}
+
+func ispkgin(pkgs []string) bool {
+ if myimportpath != "" {
+ for _, p := range pkgs {
+ if myimportpath == p {
+ return true
+ }
+ }
+ }
+
+ return false
+}
+
+func instrument(fn *Node) {
+ if fn.Func.Pragma&Norace != 0 {
+ return
+ }
+
+ if !flag_race || !ispkgin(norace_inst_pkgs) {
+ fn.Func.SetInstrumentBody(true)
+ }
+
+ if flag_race {
+ lno := lineno
+ lineno = src.NoXPos
+
+ if thearch.LinkArch.Arch.Family != sys.AMD64 {
+ 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.
+ // 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
+ }
+}