github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/pkg/runtime/race.c (about)

     1  // Copyright 2011 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  // Implementation of the race detector API.
     6  // +build race
     7  
     8  #include "runtime.h"
     9  #include "arch_GOARCH.h"
    10  #include "malloc.h"
    11  #include "race.h"
    12  
    13  void runtime∕race·Initialize(uintptr *racectx);
    14  void runtime∕race·MapShadow(void *addr, uintptr size);
    15  void runtime∕race·Finalize(void);
    16  void runtime∕race·FinalizerGoroutine(uintptr racectx);
    17  void runtime∕race·Read(uintptr racectx, void *addr, void *pc);
    18  void runtime∕race·Write(uintptr racectx, void *addr, void *pc);
    19  void runtime∕race·ReadRange(uintptr racectx, void *addr, uintptr sz, uintptr step, void *pc);
    20  void runtime∕race·WriteRange(uintptr racectx, void *addr, uintptr sz, uintptr step, void *pc);
    21  void runtime∕race·FuncEnter(uintptr racectx, void *pc);
    22  void runtime∕race·FuncExit(uintptr racectx);
    23  void runtime∕race·Malloc(uintptr racectx, void *p, uintptr sz, void *pc);
    24  void runtime∕race·Free(void *p);
    25  void runtime∕race·GoStart(uintptr racectx, uintptr *chracectx, void *pc);
    26  void runtime∕race·GoEnd(uintptr racectx);
    27  void runtime∕race·Acquire(uintptr racectx, void *addr);
    28  void runtime∕race·Release(uintptr racectx, void *addr);
    29  void runtime∕race·ReleaseMerge(uintptr racectx, void *addr);
    30  
    31  extern byte noptrdata[];
    32  extern byte enoptrbss[];
    33  
    34  static bool onstack(uintptr argp);
    35  
    36  uintptr
    37  runtime·raceinit(void)
    38  {
    39  	uintptr racectx, start, size;
    40  
    41  	m->racecall = true;
    42  	runtime∕race·Initialize(&racectx);
    43  	// Round data segment to page boundaries, because it's used in mmap().
    44  	start = (uintptr)noptrdata & ~(PageSize-1);
    45  	size = ROUND((uintptr)enoptrbss - start, PageSize);
    46  	runtime∕race·MapShadow((void*)start, size);
    47  	m->racecall = false;
    48  	return racectx;
    49  }
    50  
    51  void
    52  runtime·racefini(void)
    53  {
    54  	m->racecall = true;
    55  	runtime∕race·Finalize();
    56  	m->racecall = false;
    57  }
    58  
    59  void
    60  runtime·racemapshadow(void *addr, uintptr size)
    61  {
    62  	m->racecall = true;
    63  	runtime∕race·MapShadow(addr, size);
    64  	m->racecall = false;
    65  }
    66  
    67  // Called from instrumented code.
    68  // If we split stack, getcallerpc() can return runtime·lessstack().
    69  #pragma textflag 7
    70  void
    71  runtime·racewrite(uintptr addr)
    72  {
    73  	if(!onstack(addr)) {
    74  		m->racecall = true;
    75  		runtime∕race·Write(g->racectx, (void*)addr, runtime·getcallerpc(&addr));
    76  		m->racecall = false;
    77  	}
    78  }
    79  
    80  // Called from instrumented code.
    81  // If we split stack, getcallerpc() can return runtime·lessstack().
    82  #pragma textflag 7
    83  void
    84  runtime·raceread(uintptr addr)
    85  {
    86  	if(!onstack(addr)) {
    87  		m->racecall = true;
    88  		runtime∕race·Read(g->racectx, (void*)addr, runtime·getcallerpc(&addr));
    89  		m->racecall = false;
    90  	}
    91  }
    92  
    93  // Called from runtime·racefuncenter (assembly).
    94  #pragma textflag 7
    95  void
    96  runtime·racefuncenter1(uintptr pc)
    97  {
    98  	// If the caller PC is lessstack, use slower runtime·callers
    99  	// to walk across the stack split to find the real caller.
   100  	if(pc == (uintptr)runtime·lessstack)
   101  		runtime·callers(2, &pc, 1);
   102  
   103  	m->racecall = true;
   104  	runtime∕race·FuncEnter(g->racectx, (void*)pc);
   105  	m->racecall = false;
   106  }
   107  
   108  // Called from instrumented code.
   109  #pragma textflag 7
   110  void
   111  runtime·racefuncexit(void)
   112  {
   113  	m->racecall = true;
   114  	runtime∕race·FuncExit(g->racectx);
   115  	m->racecall = false;
   116  }
   117  
   118  void
   119  runtime·racemalloc(void *p, uintptr sz, void *pc)
   120  {
   121  	// use m->curg because runtime·stackalloc() is called from g0
   122  	if(m->curg == nil)
   123  		return;
   124  	m->racecall = true;
   125  	runtime∕race·Malloc(m->curg->racectx, p, sz, pc);
   126  	m->racecall = false;
   127  }
   128  
   129  void
   130  runtime·racefree(void *p)
   131  {
   132  	m->racecall = true;
   133  	runtime∕race·Free(p);
   134  	m->racecall = false;
   135  }
   136  
   137  uintptr
   138  runtime·racegostart(void *pc)
   139  {
   140  	uintptr racectx;
   141  
   142  	m->racecall = true;
   143  	runtime∕race·GoStart(g->racectx, &racectx, pc);
   144  	m->racecall = false;
   145  	return racectx;
   146  }
   147  
   148  void
   149  runtime·racegoend(void)
   150  {
   151  	m->racecall = true;
   152  	runtime∕race·GoEnd(g->racectx);
   153  	m->racecall = false;
   154  }
   155  
   156  static void
   157  memoryaccess(void *addr, uintptr callpc, uintptr pc, bool write)
   158  {
   159  	uintptr racectx;
   160  
   161  	if(!onstack((uintptr)addr)) {
   162  		m->racecall = true;
   163  		racectx = g->racectx;
   164  		if(callpc) {
   165  			if(callpc == (uintptr)runtime·lessstack)
   166  				runtime·callers(3, &callpc, 1);
   167  			runtime∕race·FuncEnter(racectx, (void*)callpc);
   168  		}
   169  		if(write)
   170  			runtime∕race·Write(racectx, addr, (void*)pc);
   171  		else
   172  			runtime∕race·Read(racectx, addr, (void*)pc);
   173  		if(callpc)
   174  			runtime∕race·FuncExit(racectx);
   175  		m->racecall = false;
   176  	}
   177  }
   178  
   179  void
   180  runtime·racewritepc(void *addr, void *callpc, void *pc)
   181  {
   182  	memoryaccess(addr, (uintptr)callpc, (uintptr)pc, true);
   183  }
   184  
   185  void
   186  runtime·racereadpc(void *addr, void *callpc, void *pc)
   187  {
   188  	memoryaccess(addr, (uintptr)callpc, (uintptr)pc, false);
   189  }
   190  
   191  static void
   192  rangeaccess(void *addr, uintptr size, uintptr step, uintptr callpc, uintptr pc, bool write)
   193  {
   194  	uintptr racectx;
   195  
   196  	if(!onstack((uintptr)addr)) {
   197  		m->racecall = true;
   198  		racectx = g->racectx;
   199  		if(callpc) {
   200  			if(callpc == (uintptr)runtime·lessstack)
   201  				runtime·callers(3, &callpc, 1);
   202  			runtime∕race·FuncEnter(racectx, (void*)callpc);
   203  		}
   204  		if(write)
   205  			runtime∕race·WriteRange(racectx, addr, size, step, (void*)pc);
   206  		else
   207  			runtime∕race·ReadRange(racectx, addr, size, step, (void*)pc);
   208  		if(callpc)
   209  			runtime∕race·FuncExit(racectx);
   210  		m->racecall = false;
   211  	}
   212  }
   213  
   214  void
   215  runtime·racewriterangepc(void *addr, uintptr sz, uintptr step, void *callpc, void *pc)
   216  {
   217  	rangeaccess(addr, sz, step, (uintptr)callpc, (uintptr)pc, true);
   218  }
   219  
   220  void
   221  runtime·racereadrangepc(void *addr, uintptr sz, uintptr step, void *callpc, void *pc)
   222  {
   223  	rangeaccess(addr, sz, step, (uintptr)callpc, (uintptr)pc, false);
   224  }
   225  
   226  void
   227  runtime·raceacquire(void *addr)
   228  {
   229  	runtime·raceacquireg(g, addr);
   230  }
   231  
   232  void
   233  runtime·raceacquireg(G *gp, void *addr)
   234  {
   235  	if(g->raceignore)
   236  		return;
   237  	m->racecall = true;
   238  	runtime∕race·Acquire(gp->racectx, addr);
   239  	m->racecall = false;
   240  }
   241  
   242  void
   243  runtime·racerelease(void *addr)
   244  {
   245  	runtime·racereleaseg(g, addr);
   246  }
   247  
   248  void
   249  runtime·racereleaseg(G *gp, void *addr)
   250  {
   251  	if(g->raceignore)
   252  		return;
   253  	m->racecall = true;
   254  	runtime∕race·Release(gp->racectx, addr);
   255  	m->racecall = false;
   256  }
   257  
   258  void
   259  runtime·racereleasemerge(void *addr)
   260  {
   261  	runtime·racereleasemergeg(g, addr);
   262  }
   263  
   264  void
   265  runtime·racereleasemergeg(G *gp, void *addr)
   266  {
   267  	if(g->raceignore)
   268  		return;
   269  	m->racecall = true;
   270  	runtime∕race·ReleaseMerge(gp->racectx, addr);
   271  	m->racecall = false;
   272  }
   273  
   274  void
   275  runtime·racefingo(void)
   276  {
   277  	m->racecall = true;
   278  	runtime∕race·FinalizerGoroutine(g->racectx);
   279  	m->racecall = false;
   280  }
   281  
   282  // func RaceAcquire(addr unsafe.Pointer)
   283  void
   284  runtime·RaceAcquire(void *addr)
   285  {
   286  	runtime·raceacquire(addr);
   287  }
   288  
   289  // func RaceRelease(addr unsafe.Pointer)
   290  void
   291  runtime·RaceRelease(void *addr)
   292  {
   293  	runtime·racerelease(addr);
   294  }
   295  
   296  // func RaceReleaseMerge(addr unsafe.Pointer)
   297  void
   298  runtime·RaceReleaseMerge(void *addr)
   299  {
   300  	runtime·racereleasemerge(addr);
   301  }
   302  
   303  // func RaceSemacquire(s *uint32)
   304  void runtime·RaceSemacquire(uint32 *s)
   305  {
   306  	runtime·semacquire(s);
   307  }
   308  
   309  // func RaceSemrelease(s *uint32)
   310  void runtime·RaceSemrelease(uint32 *s)
   311  {
   312  	runtime·semrelease(s);
   313  }
   314  
   315  // func RaceRead(addr unsafe.Pointer)
   316  #pragma textflag 7
   317  void
   318  runtime·RaceRead(void *addr)
   319  {
   320  	memoryaccess(addr, 0, (uintptr)runtime·getcallerpc(&addr), false);
   321  }
   322  
   323  // func RaceWrite(addr unsafe.Pointer)
   324  #pragma textflag 7
   325  void
   326  runtime·RaceWrite(void *addr)
   327  {
   328  	memoryaccess(addr, 0, (uintptr)runtime·getcallerpc(&addr), true);
   329  }
   330  
   331  // func RaceDisable()
   332  void runtime·RaceDisable(void)
   333  {
   334  	g->raceignore++;
   335  }
   336  
   337  // func RaceEnable()
   338  void runtime·RaceEnable(void)
   339  {
   340  	g->raceignore--;
   341  }
   342  
   343  static bool
   344  onstack(uintptr argp)
   345  {
   346  	// noptrdata, data, bss, noptrbss
   347  	// the layout is in ../../cmd/ld/data.c
   348  	if((byte*)argp >= noptrdata && (byte*)argp < enoptrbss)
   349  		return false;
   350  	if((byte*)argp >= runtime·mheap->arena_start && (byte*)argp < runtime·mheap->arena_used)
   351  		return false;
   352  	return true;
   353  }