...

Source file src/pkg/cmd/compile/internal/gc/racewalk.go

     1	// Copyright 2012 The Go Authors. All rights reserved.
     2	// Use of this source code is governed by a BSD-style
     3	// license that can be found in the LICENSE file.
     4	
     5	package gc
     6	
     7	import (
     8		"cmd/compile/internal/types"
     9		"cmd/internal/src"
    10		"cmd/internal/sys"
    11	)
    12	
    13	// The racewalk pass is currently handled in three parts.
    14	//
    15	// First, for flag_race, it inserts calls to racefuncenter and
    16	// racefuncexit at the start and end (respectively) of each
    17	// function. This is handled below.
    18	//
    19	// Second, during buildssa, it inserts appropriate instrumentation
    20	// calls immediately before each memory load or store. This is handled
    21	// by the (*state).instrument method in ssa.go, so here we just set
    22	// the Func.InstrumentBody flag as needed. For background on why this
    23	// is done during SSA construction rather than a separate SSA pass,
    24	// see issue #19054.
    25	//
    26	// Third we remove calls to racefuncenter and racefuncexit, for leaf
    27	// functions without instrumented operations. This is done as part of
    28	// ssa opt pass via special rule.
    29	
    30	// TODO(dvyukov): do not instrument initialization as writes:
    31	// a := make([]int, 10)
    32	
    33	// Do not instrument the following packages at all,
    34	// at best instrumentation would cause infinite recursion.
    35	var omit_pkgs = []string{
    36		"runtime/internal/atomic",
    37		"runtime/internal/sys",
    38		"runtime/internal/math",
    39		"runtime",
    40		"runtime/race",
    41		"runtime/msan",
    42		"internal/cpu",
    43	}
    44	
    45	// Only insert racefuncenterfp/racefuncexit into the following packages.
    46	// Memory accesses in the packages are either uninteresting or will cause false positives.
    47	var norace_inst_pkgs = []string{"sync", "sync/atomic"}
    48	
    49	func ispkgin(pkgs []string) bool {
    50		if myimportpath != "" {
    51			for _, p := range pkgs {
    52				if myimportpath == p {
    53					return true
    54				}
    55			}
    56		}
    57	
    58		return false
    59	}
    60	
    61	func instrument(fn *Node) {
    62		if fn.Func.Pragma&Norace != 0 {
    63			return
    64		}
    65	
    66		if !flag_race || !ispkgin(norace_inst_pkgs) {
    67			fn.Func.SetInstrumentBody(true)
    68		}
    69	
    70		if flag_race {
    71			lno := lineno
    72			lineno = src.NoXPos
    73	
    74			if thearch.LinkArch.Arch.Family != sys.AMD64 {
    75				fn.Func.Enter.Prepend(mkcall("racefuncenterfp", nil, nil))
    76				fn.Func.Exit.Append(mkcall("racefuncexit", nil, nil))
    77			} else {
    78	
    79				// nodpc is the PC of the caller as extracted by
    80				// getcallerpc. We use -widthptr(FP) for x86.
    81				// This only works for amd64. This will not
    82				// work on arm or others that might support
    83				// race in the future.
    84				nodpc := nodfp.copy()
    85				nodpc.Type = types.Types[TUINTPTR]
    86				nodpc.Xoffset = int64(-Widthptr)
    87				fn.Func.Dcl = append(fn.Func.Dcl, nodpc)
    88				fn.Func.Enter.Prepend(mkcall("racefuncenter", nil, nil, nodpc))
    89				fn.Func.Exit.Append(mkcall("racefuncexit", nil, nil))
    90			}
    91			lineno = lno
    92		}
    93	}
    94	

View as plain text