2012-10-07 12:05:32 -06:00
|
|
|
|
// Copyright 2011 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.
|
|
|
|
|
|
|
|
|
|
// Implementation of the race detector API.
|
|
|
|
|
// +build race
|
|
|
|
|
|
|
|
|
|
#include "runtime.h"
|
|
|
|
|
#include "arch_GOARCH.h"
|
|
|
|
|
#include "malloc.h"
|
|
|
|
|
#include "race.h"
|
|
|
|
|
|
2013-02-06 00:40:54 -07:00
|
|
|
|
void runtime∕race·Initialize(uintptr *racectx);
|
2012-11-07 01:48:58 -07:00
|
|
|
|
void runtime∕race·MapShadow(void *addr, uintptr size);
|
2012-10-07 12:05:32 -06:00
|
|
|
|
void runtime∕race·Finalize(void);
|
2013-02-06 00:40:54 -07:00
|
|
|
|
void runtime∕race·FinalizerGoroutine(uintptr racectx);
|
|
|
|
|
void runtime∕race·Read(uintptr racectx, void *addr, void *pc);
|
|
|
|
|
void runtime∕race·Write(uintptr racectx, void *addr, void *pc);
|
2013-06-13 06:38:44 -06:00
|
|
|
|
void runtime∕race·ReadRange(uintptr racectx, void *addr, uintptr sz, void *pc);
|
|
|
|
|
void runtime∕race·WriteRange(uintptr racectx, void *addr, uintptr sz, void *pc);
|
2013-02-06 00:40:54 -07:00
|
|
|
|
void runtime∕race·FuncEnter(uintptr racectx, void *pc);
|
|
|
|
|
void runtime∕race·FuncExit(uintptr racectx);
|
|
|
|
|
void runtime∕race·Malloc(uintptr racectx, void *p, uintptr sz, void *pc);
|
2012-10-07 12:05:32 -06:00
|
|
|
|
void runtime∕race·Free(void *p);
|
2013-02-06 00:40:54 -07:00
|
|
|
|
void runtime∕race·GoStart(uintptr racectx, uintptr *chracectx, void *pc);
|
|
|
|
|
void runtime∕race·GoEnd(uintptr racectx);
|
|
|
|
|
void runtime∕race·Acquire(uintptr racectx, void *addr);
|
|
|
|
|
void runtime∕race·Release(uintptr racectx, void *addr);
|
|
|
|
|
void runtime∕race·ReleaseMerge(uintptr racectx, void *addr);
|
2012-10-07 12:05:32 -06:00
|
|
|
|
|
|
|
|
|
extern byte noptrdata[];
|
|
|
|
|
extern byte enoptrbss[];
|
|
|
|
|
|
|
|
|
|
static bool onstack(uintptr argp);
|
|
|
|
|
|
2013-02-06 00:40:54 -07:00
|
|
|
|
uintptr
|
2012-10-07 12:05:32 -06:00
|
|
|
|
runtime·raceinit(void)
|
|
|
|
|
{
|
2013-04-03 16:11:34 -06:00
|
|
|
|
uintptr racectx, start, size;
|
2012-11-16 09:06:11 -07:00
|
|
|
|
|
2012-10-07 12:05:32 -06:00
|
|
|
|
m->racecall = true;
|
2013-02-06 00:40:54 -07:00
|
|
|
|
runtime∕race·Initialize(&racectx);
|
2013-04-03 16:11:34 -06:00
|
|
|
|
// Round data segment to page boundaries, because it's used in mmap().
|
|
|
|
|
start = (uintptr)noptrdata & ~(PageSize-1);
|
|
|
|
|
size = ROUND((uintptr)enoptrbss - start, PageSize);
|
|
|
|
|
runtime∕race·MapShadow((void*)start, size);
|
2012-10-07 12:05:32 -06:00
|
|
|
|
m->racecall = false;
|
2013-02-06 00:40:54 -07:00
|
|
|
|
return racectx;
|
2012-10-07 12:05:32 -06:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
runtime·racefini(void)
|
|
|
|
|
{
|
|
|
|
|
m->racecall = true;
|
|
|
|
|
runtime∕race·Finalize();
|
|
|
|
|
m->racecall = false;
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-07 01:48:58 -07:00
|
|
|
|
void
|
|
|
|
|
runtime·racemapshadow(void *addr, uintptr size)
|
|
|
|
|
{
|
|
|
|
|
m->racecall = true;
|
|
|
|
|
runtime∕race·MapShadow(addr, size);
|
|
|
|
|
m->racecall = false;
|
|
|
|
|
}
|
|
|
|
|
|
2012-10-07 12:05:32 -06:00
|
|
|
|
// Called from instrumented code.
|
2012-11-06 09:54:22 -07:00
|
|
|
|
// If we split stack, getcallerpc() can return runtime·lessstack().
|
|
|
|
|
#pragma textflag 7
|
2012-10-07 12:05:32 -06:00
|
|
|
|
void
|
|
|
|
|
runtime·racewrite(uintptr addr)
|
|
|
|
|
{
|
|
|
|
|
if(!onstack(addr)) {
|
|
|
|
|
m->racecall = true;
|
2013-02-06 00:40:54 -07:00
|
|
|
|
runtime∕race·Write(g->racectx, (void*)addr, runtime·getcallerpc(&addr));
|
2012-10-07 12:05:32 -06:00
|
|
|
|
m->racecall = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-14 03:14:45 -06:00
|
|
|
|
#pragma textflag 7
|
|
|
|
|
void
|
|
|
|
|
runtime·racewriterange(uintptr addr, uintptr sz)
|
|
|
|
|
{
|
|
|
|
|
if(!onstack(addr)) {
|
|
|
|
|
m->racecall = true;
|
|
|
|
|
runtime∕race·WriteRange(g->racectx, (void*)addr, sz, runtime·getcallerpc(&addr));
|
|
|
|
|
m->racecall = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-10-07 12:05:32 -06:00
|
|
|
|
// Called from instrumented code.
|
2012-11-06 09:54:22 -07:00
|
|
|
|
// If we split stack, getcallerpc() can return runtime·lessstack().
|
|
|
|
|
#pragma textflag 7
|
2012-10-07 12:05:32 -06:00
|
|
|
|
void
|
|
|
|
|
runtime·raceread(uintptr addr)
|
|
|
|
|
{
|
|
|
|
|
if(!onstack(addr)) {
|
|
|
|
|
m->racecall = true;
|
2013-02-06 00:40:54 -07:00
|
|
|
|
runtime∕race·Read(g->racectx, (void*)addr, runtime·getcallerpc(&addr));
|
2012-10-07 12:05:32 -06:00
|
|
|
|
m->racecall = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-14 03:14:45 -06:00
|
|
|
|
#pragma textflag 7
|
|
|
|
|
void
|
|
|
|
|
runtime·racereadrange(uintptr addr, uintptr sz)
|
|
|
|
|
{
|
|
|
|
|
if(!onstack(addr)) {
|
|
|
|
|
m->racecall = true;
|
|
|
|
|
runtime∕race·ReadRange(g->racectx, (void*)addr, sz, runtime·getcallerpc(&addr));
|
|
|
|
|
m->racecall = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-02-22 11:06:43 -07:00
|
|
|
|
// Called from runtime·racefuncenter (assembly).
|
2012-11-06 09:54:22 -07:00
|
|
|
|
#pragma textflag 7
|
2012-10-07 12:05:32 -06:00
|
|
|
|
void
|
2013-02-22 11:06:43 -07:00
|
|
|
|
runtime·racefuncenter1(uintptr pc)
|
2012-10-07 12:05:32 -06:00
|
|
|
|
{
|
2012-11-01 12:43:29 -06:00
|
|
|
|
// If the caller PC is lessstack, use slower runtime·callers
|
|
|
|
|
// to walk across the stack split to find the real caller.
|
2013-02-27 23:32:29 -07:00
|
|
|
|
if(pc == (uintptr)runtime·lessstack)
|
2012-11-01 12:43:29 -06:00
|
|
|
|
runtime·callers(2, &pc, 1);
|
2012-10-07 12:05:32 -06:00
|
|
|
|
|
|
|
|
|
m->racecall = true;
|
2013-02-06 00:40:54 -07:00
|
|
|
|
runtime∕race·FuncEnter(g->racectx, (void*)pc);
|
2012-10-07 12:05:32 -06:00
|
|
|
|
m->racecall = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Called from instrumented code.
|
2012-11-06 09:54:22 -07:00
|
|
|
|
#pragma textflag 7
|
2012-10-07 12:05:32 -06:00
|
|
|
|
void
|
|
|
|
|
runtime·racefuncexit(void)
|
|
|
|
|
{
|
|
|
|
|
m->racecall = true;
|
2013-02-06 00:40:54 -07:00
|
|
|
|
runtime∕race·FuncExit(g->racectx);
|
2012-10-07 12:05:32 -06:00
|
|
|
|
m->racecall = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
runtime·racemalloc(void *p, uintptr sz, void *pc)
|
|
|
|
|
{
|
2012-10-10 08:06:29 -06:00
|
|
|
|
// use m->curg because runtime·stackalloc() is called from g0
|
|
|
|
|
if(m->curg == nil)
|
|
|
|
|
return;
|
2012-10-07 12:05:32 -06:00
|
|
|
|
m->racecall = true;
|
2013-02-06 00:40:54 -07:00
|
|
|
|
runtime∕race·Malloc(m->curg->racectx, p, sz, pc);
|
2012-10-07 12:05:32 -06:00
|
|
|
|
m->racecall = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
runtime·racefree(void *p)
|
|
|
|
|
{
|
|
|
|
|
m->racecall = true;
|
|
|
|
|
runtime∕race·Free(p);
|
|
|
|
|
m->racecall = false;
|
|
|
|
|
}
|
|
|
|
|
|
2013-02-06 00:40:54 -07:00
|
|
|
|
uintptr
|
|
|
|
|
runtime·racegostart(void *pc)
|
2012-10-07 12:05:32 -06:00
|
|
|
|
{
|
2013-02-06 00:40:54 -07:00
|
|
|
|
uintptr racectx;
|
|
|
|
|
|
2012-10-07 12:05:32 -06:00
|
|
|
|
m->racecall = true;
|
2013-02-06 00:40:54 -07:00
|
|
|
|
runtime∕race·GoStart(g->racectx, &racectx, pc);
|
2012-10-07 12:05:32 -06:00
|
|
|
|
m->racecall = false;
|
2013-02-06 00:40:54 -07:00
|
|
|
|
return racectx;
|
2012-10-07 12:05:32 -06:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2013-02-06 00:40:54 -07:00
|
|
|
|
runtime·racegoend(void)
|
2012-10-07 12:05:32 -06:00
|
|
|
|
{
|
|
|
|
|
m->racecall = true;
|
2013-02-06 00:40:54 -07:00
|
|
|
|
runtime∕race·GoEnd(g->racectx);
|
2012-10-07 12:05:32 -06:00
|
|
|
|
m->racecall = false;
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-29 23:29:41 -07:00
|
|
|
|
static void
|
|
|
|
|
memoryaccess(void *addr, uintptr callpc, uintptr pc, bool write)
|
2012-10-07 12:05:32 -06:00
|
|
|
|
{
|
2013-02-06 00:40:54 -07:00
|
|
|
|
uintptr racectx;
|
2012-11-29 23:29:41 -07:00
|
|
|
|
|
2012-10-07 12:05:32 -06:00
|
|
|
|
if(!onstack((uintptr)addr)) {
|
|
|
|
|
m->racecall = true;
|
2013-02-06 00:40:54 -07:00
|
|
|
|
racectx = g->racectx;
|
2012-11-29 23:29:41 -07:00
|
|
|
|
if(callpc) {
|
2013-02-27 23:32:29 -07:00
|
|
|
|
if(callpc == (uintptr)runtime·lessstack)
|
2012-11-29 23:29:41 -07:00
|
|
|
|
runtime·callers(3, &callpc, 1);
|
2013-02-06 00:40:54 -07:00
|
|
|
|
runtime∕race·FuncEnter(racectx, (void*)callpc);
|
2012-11-29 23:29:41 -07:00
|
|
|
|
}
|
|
|
|
|
if(write)
|
2013-02-06 00:40:54 -07:00
|
|
|
|
runtime∕race·Write(racectx, addr, (void*)pc);
|
2012-11-29 23:29:41 -07:00
|
|
|
|
else
|
2013-02-06 00:40:54 -07:00
|
|
|
|
runtime∕race·Read(racectx, addr, (void*)pc);
|
2012-11-29 23:29:41 -07:00
|
|
|
|
if(callpc)
|
2013-02-06 00:40:54 -07:00
|
|
|
|
runtime∕race·FuncExit(racectx);
|
2012-10-07 12:05:32 -06:00
|
|
|
|
m->racecall = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2012-11-29 23:29:41 -07:00
|
|
|
|
runtime·racewritepc(void *addr, void *callpc, void *pc)
|
2012-10-07 12:05:32 -06:00
|
|
|
|
{
|
2012-11-29 23:29:41 -07:00
|
|
|
|
memoryaccess(addr, (uintptr)callpc, (uintptr)pc, true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
runtime·racereadpc(void *addr, void *callpc, void *pc)
|
|
|
|
|
{
|
|
|
|
|
memoryaccess(addr, (uintptr)callpc, (uintptr)pc, false);
|
2012-10-07 12:05:32 -06:00
|
|
|
|
}
|
|
|
|
|
|
2013-01-29 17:55:02 -07:00
|
|
|
|
static void
|
2013-06-13 06:38:44 -06:00
|
|
|
|
rangeaccess(void *addr, uintptr size, uintptr callpc, uintptr pc, bool write)
|
2013-01-29 17:55:02 -07:00
|
|
|
|
{
|
2013-02-06 00:40:54 -07:00
|
|
|
|
uintptr racectx;
|
2013-01-29 17:55:02 -07:00
|
|
|
|
|
|
|
|
|
if(!onstack((uintptr)addr)) {
|
|
|
|
|
m->racecall = true;
|
2013-02-06 00:40:54 -07:00
|
|
|
|
racectx = g->racectx;
|
2013-01-29 17:55:02 -07:00
|
|
|
|
if(callpc) {
|
2013-02-27 23:32:29 -07:00
|
|
|
|
if(callpc == (uintptr)runtime·lessstack)
|
2013-01-29 17:55:02 -07:00
|
|
|
|
runtime·callers(3, &callpc, 1);
|
2013-02-06 00:40:54 -07:00
|
|
|
|
runtime∕race·FuncEnter(racectx, (void*)callpc);
|
2013-01-29 17:55:02 -07:00
|
|
|
|
}
|
|
|
|
|
if(write)
|
2013-06-13 06:38:44 -06:00
|
|
|
|
runtime∕race·WriteRange(racectx, addr, size, (void*)pc);
|
2013-01-29 17:55:02 -07:00
|
|
|
|
else
|
2013-06-13 06:38:44 -06:00
|
|
|
|
runtime∕race·ReadRange(racectx, addr, size, (void*)pc);
|
2013-01-29 17:55:02 -07:00
|
|
|
|
if(callpc)
|
2013-02-06 00:40:54 -07:00
|
|
|
|
runtime∕race·FuncExit(racectx);
|
2013-01-29 17:55:02 -07:00
|
|
|
|
m->racecall = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2013-06-13 06:38:44 -06:00
|
|
|
|
runtime·racewriterangepc(void *addr, uintptr sz, void *callpc, void *pc)
|
2013-01-29 17:55:02 -07:00
|
|
|
|
{
|
2013-06-13 06:38:44 -06:00
|
|
|
|
rangeaccess(addr, sz, (uintptr)callpc, (uintptr)pc, true);
|
2013-01-29 17:55:02 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2013-06-13 06:38:44 -06:00
|
|
|
|
runtime·racereadrangepc(void *addr, uintptr sz, void *callpc, void *pc)
|
2013-01-29 17:55:02 -07:00
|
|
|
|
{
|
2013-06-13 06:38:44 -06:00
|
|
|
|
rangeaccess(addr, sz, (uintptr)callpc, (uintptr)pc, false);
|
2013-01-29 17:55:02 -07:00
|
|
|
|
}
|
|
|
|
|
|
2012-10-07 12:05:32 -06:00
|
|
|
|
void
|
|
|
|
|
runtime·raceacquire(void *addr)
|
|
|
|
|
{
|
|
|
|
|
runtime·raceacquireg(g, addr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
runtime·raceacquireg(G *gp, void *addr)
|
|
|
|
|
{
|
|
|
|
|
if(g->raceignore)
|
|
|
|
|
return;
|
|
|
|
|
m->racecall = true;
|
2013-02-06 00:40:54 -07:00
|
|
|
|
runtime∕race·Acquire(gp->racectx, addr);
|
2012-10-07 12:05:32 -06:00
|
|
|
|
m->racecall = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
runtime·racerelease(void *addr)
|
|
|
|
|
{
|
|
|
|
|
runtime·racereleaseg(g, addr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
runtime·racereleaseg(G *gp, void *addr)
|
|
|
|
|
{
|
|
|
|
|
if(g->raceignore)
|
|
|
|
|
return;
|
|
|
|
|
m->racecall = true;
|
2013-02-06 00:40:54 -07:00
|
|
|
|
runtime∕race·Release(gp->racectx, addr);
|
2012-10-07 12:05:32 -06:00
|
|
|
|
m->racecall = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
runtime·racereleasemerge(void *addr)
|
|
|
|
|
{
|
|
|
|
|
runtime·racereleasemergeg(g, addr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
runtime·racereleasemergeg(G *gp, void *addr)
|
|
|
|
|
{
|
|
|
|
|
if(g->raceignore)
|
|
|
|
|
return;
|
|
|
|
|
m->racecall = true;
|
2013-02-06 00:40:54 -07:00
|
|
|
|
runtime∕race·ReleaseMerge(gp->racectx, addr);
|
2012-10-07 12:05:32 -06:00
|
|
|
|
m->racecall = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
runtime·racefingo(void)
|
|
|
|
|
{
|
|
|
|
|
m->racecall = true;
|
2013-02-06 00:40:54 -07:00
|
|
|
|
runtime∕race·FinalizerGoroutine(g->racectx);
|
2012-10-07 12:05:32 -06:00
|
|
|
|
m->racecall = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// func RaceAcquire(addr unsafe.Pointer)
|
|
|
|
|
void
|
|
|
|
|
runtime·RaceAcquire(void *addr)
|
|
|
|
|
{
|
|
|
|
|
runtime·raceacquire(addr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// func RaceRelease(addr unsafe.Pointer)
|
|
|
|
|
void
|
|
|
|
|
runtime·RaceRelease(void *addr)
|
|
|
|
|
{
|
|
|
|
|
runtime·racerelease(addr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// func RaceReleaseMerge(addr unsafe.Pointer)
|
|
|
|
|
void
|
|
|
|
|
runtime·RaceReleaseMerge(void *addr)
|
|
|
|
|
{
|
|
|
|
|
runtime·racereleasemerge(addr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// func RaceSemacquire(s *uint32)
|
2013-05-18 16:49:23 -06:00
|
|
|
|
void
|
|
|
|
|
runtime·RaceSemacquire(uint32 *s)
|
2012-10-07 12:05:32 -06:00
|
|
|
|
{
|
|
|
|
|
runtime·semacquire(s);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// func RaceSemrelease(s *uint32)
|
2013-05-18 16:49:23 -06:00
|
|
|
|
void
|
|
|
|
|
runtime·RaceSemrelease(uint32 *s)
|
2012-10-07 12:05:32 -06:00
|
|
|
|
{
|
|
|
|
|
runtime·semrelease(s);
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-14 05:51:23 -07:00
|
|
|
|
// func RaceRead(addr unsafe.Pointer)
|
|
|
|
|
#pragma textflag 7
|
|
|
|
|
void
|
|
|
|
|
runtime·RaceRead(void *addr)
|
|
|
|
|
{
|
2012-11-29 23:29:41 -07:00
|
|
|
|
memoryaccess(addr, 0, (uintptr)runtime·getcallerpc(&addr), false);
|
2012-11-14 05:51:23 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// func RaceWrite(addr unsafe.Pointer)
|
|
|
|
|
#pragma textflag 7
|
|
|
|
|
void
|
|
|
|
|
runtime·RaceWrite(void *addr)
|
|
|
|
|
{
|
2012-11-29 23:29:41 -07:00
|
|
|
|
memoryaccess(addr, 0, (uintptr)runtime·getcallerpc(&addr), true);
|
2012-11-14 05:51:23 -07:00
|
|
|
|
}
|
|
|
|
|
|
2013-06-10 12:40:35 -06:00
|
|
|
|
// func RaceReadRange(addr unsafe.Pointer, len int)
|
|
|
|
|
#pragma textflag 7
|
|
|
|
|
void
|
|
|
|
|
runtime·RaceReadRange(void *addr, intgo len)
|
|
|
|
|
{
|
2013-06-13 06:38:44 -06:00
|
|
|
|
rangeaccess(addr, len, 0, (uintptr)runtime·getcallerpc(&addr), false);
|
2013-06-10 12:40:35 -06:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// func RaceWriteRange(addr unsafe.Pointer, len int)
|
|
|
|
|
#pragma textflag 7
|
|
|
|
|
void
|
|
|
|
|
runtime·RaceWriteRange(void *addr, intgo len)
|
|
|
|
|
{
|
2013-06-13 06:38:44 -06:00
|
|
|
|
rangeaccess(addr, len, 0, (uintptr)runtime·getcallerpc(&addr), true);
|
2013-06-10 12:40:35 -06:00
|
|
|
|
}
|
|
|
|
|
|
2012-10-07 12:05:32 -06:00
|
|
|
|
// func RaceDisable()
|
2013-05-18 16:49:23 -06:00
|
|
|
|
void
|
|
|
|
|
runtime·RaceDisable(void)
|
2012-10-07 12:05:32 -06:00
|
|
|
|
{
|
|
|
|
|
g->raceignore++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// func RaceEnable()
|
2013-05-18 16:49:23 -06:00
|
|
|
|
void
|
|
|
|
|
runtime·RaceEnable(void)
|
2012-10-07 12:05:32 -06:00
|
|
|
|
{
|
|
|
|
|
g->raceignore--;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool
|
|
|
|
|
onstack(uintptr argp)
|
|
|
|
|
{
|
|
|
|
|
// noptrdata, data, bss, noptrbss
|
|
|
|
|
// the layout is in ../../cmd/ld/data.c
|
|
|
|
|
if((byte*)argp >= noptrdata && (byte*)argp < enoptrbss)
|
|
|
|
|
return false;
|
2013-05-28 12:14:47 -06:00
|
|
|
|
if((byte*)argp >= runtime·mheap.arena_start && (byte*)argp < runtime·mheap.arena_used)
|
2012-10-07 12:05:32 -06:00
|
|
|
|
return false;
|
|
|
|
|
return true;
|
|
|
|
|
}
|