github.com/gagliardetto/golang-go@v0.0.0-20201020153340-53909ea70814/cmd/compile/internal/gc/racewalk.go (about)

     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  	"github.com/gagliardetto/golang-go/cmd/compile/internal/types"
     9  	"github.com/gagliardetto/golang-go/cmd/internal/src"
    10  	"github.com/gagliardetto/golang-go/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  	"github.com/gagliardetto/golang-go/not-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  }