Commit 0ce96f9e authored by Dmitriy Vyukov's avatar Dmitriy Vyukov

runtime: better stack traces in race reports

When a race happens inside of runtime (chan, slice, etc),
currently reports contain only user file:line.
If the line contains a complex expression,
it's difficult to figure out where the race exactly.
This change adds one more top frame with exact
runtime function (e.g. runtime.chansend, runtime.mapaccess).

R=golang-dev
CC=golang-dev
https://golang.org/cl/6851125
parent c3c107f6
......@@ -188,7 +188,7 @@ runtime·chansend(ChanType *t, Hchan *c, byte *ep, bool *pres, void *pc)
runtime·lock(c);
// TODO(dvyukov): add similar instrumentation to select.
if(raceenabled)
runtime·racereadpc(c, pc);
runtime·racereadpc(c, pc, runtime·chansend);
if(c->closed)
goto closed;
......@@ -1193,7 +1193,7 @@ runtime·closechan(Hchan *c)
}
if(raceenabled) {
runtime·racewritepc(c, runtime·getcallerpc(&c));
runtime·racewritepc(c, runtime·getcallerpc(&c), runtime·closechan);
runtime·racerelease(c);
}
......
......@@ -842,7 +842,7 @@ runtime·mapaccess1(MapType *t, Hmap *h, ...)
bool pres;
if(raceenabled && h != nil)
runtime·racereadpc(h, runtime·getcallerpc(&t));
runtime·racereadpc(h, runtime·getcallerpc(&t), runtime·mapaccess1);
ak = (byte*)(&h + 1);
av = ak + ROUND(t->key->size, Structrnd);
......@@ -870,7 +870,7 @@ runtime·mapaccess2(MapType *t, Hmap *h, ...)
byte *ak, *av, *ap;
if(raceenabled && h != nil)
runtime·racereadpc(h, runtime·getcallerpc(&t));
runtime·racereadpc(h, runtime·getcallerpc(&t), runtime·mapaccess2);
ak = (byte*)(&h + 1);
av = ak + ROUND(t->key->size, Structrnd);
......@@ -901,7 +901,7 @@ reflect·mapaccess(MapType *t, Hmap *h, uintptr key, uintptr val, bool pres)
byte *ak, *av;
if(raceenabled && h != nil)
runtime·racereadpc(h, runtime·getcallerpc(&t));
runtime·racereadpc(h, runtime·getcallerpc(&t), reflect·mapaccess);
if(t->key->size <= sizeof(key))
ak = (byte*)&key;
......@@ -974,7 +974,7 @@ runtime·mapassign1(MapType *t, Hmap *h, ...)
runtime·panicstring("assignment to entry in nil map");
if(raceenabled)
runtime·racewritepc(h, runtime·getcallerpc(&t));
runtime·racewritepc(h, runtime·getcallerpc(&t), runtime·mapassign1);
ak = (byte*)(&h + 1);
av = ak + ROUND(t->key->size, t->elem->align);
......@@ -992,7 +992,7 @@ runtime·mapdelete(MapType *t, Hmap *h, ...)
runtime·panicstring("deletion of entry in nil map");
if(raceenabled)
runtime·racewritepc(h, runtime·getcallerpc(&t));
runtime·racewritepc(h, runtime·getcallerpc(&t), runtime·mapdelete);
ak = (byte*)(&h + 1);
runtime·mapassign(t, h, ak, nil);
......@@ -1017,7 +1017,7 @@ reflect·mapassign(MapType *t, Hmap *h, uintptr key, uintptr val, bool pres)
if(h == nil)
runtime·panicstring("assignment to entry in nil map");
if(raceenabled)
runtime·racewritepc(h, runtime·getcallerpc(&t));
runtime·racewritepc(h, runtime·getcallerpc(&t), reflect·mapassign);
if(t->key->size <= sizeof(key))
ak = (byte*)&key;
else
......@@ -1040,7 +1040,7 @@ runtime·mapiterinit(MapType *t, Hmap *h, struct hash_iter *it)
return;
}
if(raceenabled)
runtime·racereadpc(h, runtime·getcallerpc(&t));
runtime·racereadpc(h, runtime·getcallerpc(&t), runtime·mapiterinit);
hash_iter_init(t, h, it);
it->data = hash_next(it);
if(debug) {
......@@ -1085,7 +1085,7 @@ void
runtime·mapiternext(struct hash_iter *it)
{
if(raceenabled)
runtime·racereadpc(it->h, runtime·getcallerpc(&it));
runtime·racereadpc(it->h, runtime·getcallerpc(&it), runtime·mapiternext);
if(runtime·gcwaiting)
runtime·gosched();
......@@ -1190,7 +1190,7 @@ reflect·maplen(Hmap *h, intgo len)
else {
len = h->count;
if(raceenabled)
runtime·racereadpc(h, runtime·getcallerpc(&h));
runtime·racereadpc(h, runtime·getcallerpc(&h), reflect·maplen);
}
FLUSH(&len);
}
......
......@@ -152,24 +152,40 @@ runtime·racegoend(int32 goid)
m->racecall = false;
}
void
runtime·racewritepc(void *addr, void *pc)
static void
memoryaccess(void *addr, uintptr callpc, uintptr pc, bool write)
{
int64 goid;
if(!onstack((uintptr)addr)) {
m->racecall = true;
runtimerace·Write(g->goid-1, addr, pc);
goid = g->goid-1;
if(callpc) {
if(callpc == (uintptr)runtime·lessstack ||
(callpc >= (uintptr)runtime·mheap.arena_start && callpc < (uintptr)runtime·mheap.arena_used))
runtime·callers(3, &callpc, 1);
runtimerace·FuncEnter(goid, (void*)callpc);
}
if(write)
runtimerace·Write(goid, addr, (void*)pc);
else
runtimerace·Read(goid, addr, (void*)pc);
if(callpc)
runtimerace·FuncExit(goid);
m->racecall = false;
}
}
void
runtime·racereadpc(void *addr, void *pc)
runtime·racewritepc(void *addr, void *callpc, void *pc)
{
if(!onstack((uintptr)addr)) {
m->racecall = true;
runtimerace·Read(g->goid-1, addr, pc);
m->racecall = false;
}
memoryaccess(addr, (uintptr)callpc, (uintptr)pc, true);
}
void
runtime·racereadpc(void *addr, void *callpc, void *pc)
{
memoryaccess(addr, (uintptr)callpc, (uintptr)pc, false);
}
void
......@@ -266,7 +282,7 @@ void runtime·RaceSemrelease(uint32 *s)
void
runtime·RaceRead(void *addr)
{
runtime·racereadpc(addr, runtime·getcallerpc(&addr));
memoryaccess(addr, 0, (uintptr)runtime·getcallerpc(&addr), false);
}
// func RaceWrite(addr unsafe.Pointer)
......@@ -274,7 +290,7 @@ runtime·RaceRead(void *addr)
void
runtime·RaceWrite(void *addr)
{
runtime·racewritepc(addr, runtime·getcallerpc(&addr));
memoryaccess(addr, 0, (uintptr)runtime·getcallerpc(&addr), true);
}
// func RaceDisable()
......
......@@ -20,8 +20,8 @@ void runtime·racemalloc(void *p, uintptr sz, void *pc);
void runtime·racefree(void *p);
void runtime·racegostart(int32 goid, void *pc);
void runtime·racegoend(int32 goid);
void runtime·racewritepc(void *addr, void *pc);
void runtime·racereadpc(void *addr, void *pc);
void runtime·racewritepc(void *addr, void *callpc, void *pc);
void runtime·racereadpc(void *addr, void *callpc, void *pc);
void runtime·racefingo(void);
void runtime·raceacquire(void *addr);
void runtime·raceacquireg(G *gp, void *addr);
......
......@@ -26,16 +26,18 @@ runtime·racemapshadow(void *addr, uintptr size)
}
void
runtime·racewritepc(void *addr, void *pc)
runtime·racewritepc(void *addr, void *callpc, void *pc)
{
USED(addr);
USED(callpc);
USED(pc);
}
void
runtime·racereadpc(void *addr, void *pc)
runtime·racereadpc(void *addr, void *callpc, void *pc)
{
USED(addr);
USED(callpc);
USED(pc);
}
......
......@@ -83,11 +83,11 @@ runtime·appendslice(SliceType *t, Slice x, Slice y, Slice ret)
if(raceenabled) {
pc = runtime·getcallerpc(&t);
for(i=0; i<x.len; i++)
runtime·racereadpc(x.array + i*t->elem->size, pc);
runtime·racereadpc(x.array + i*t->elem->size, pc, runtime·appendslice);
for(i=x.len; i<x.cap; i++)
runtime·racewritepc(x.array + i*t->elem->size, pc);
runtime·racewritepc(x.array + i*t->elem->size, pc, runtime·appendslice);
for(i=0; i<y.len; i++)
runtime·racereadpc(y.array + i*t->elem->size, pc);
runtime·racereadpc(y.array + i*t->elem->size, pc, runtime·appendslice);
}
if(m > x.cap)
......@@ -118,9 +118,9 @@ runtime·appendstr(SliceType *t, Slice x, String y, Slice ret)
if(raceenabled) {
pc = runtime·getcallerpc(&t);
for(i=0; i<x.len; i++)
runtime·racereadpc(x.array + i*t->elem->size, pc);
runtime·racereadpc(x.array + i*t->elem->size, pc, runtime·appendstr);
for(i=x.len; i<x.cap; i++)
runtime·racewritepc(x.array + i*t->elem->size, pc);
runtime·racewritepc(x.array + i*t->elem->size, pc, runtime·appendstr);
}
if(m > x.cap)
......@@ -153,7 +153,7 @@ runtime·growslice(SliceType *t, Slice old, int64 n, Slice ret)
if(raceenabled) {
pc = runtime·getcallerpc(&t);
for(i=0; i<old.len; i++)
runtime·racewritepc(old.array + i*t->elem->size, pc);
runtime·racewritepc(old.array + i*t->elem->size, pc, runtime·growslice);
}
growslice1(t, old, cap, &ret);
......@@ -213,8 +213,8 @@ runtime·copy(Slice to, Slice fm, uintptr width, intgo ret)
if(raceenabled) {
pc = runtime·getcallerpc(&to);
for(i=0; i<ret; i++) {
runtime·racewritepc(to.array + i*width, pc);
runtime·racereadpc(fm.array + i*width, pc);
runtime·racewritepc(to.array + i*width, pc, runtime·copy);
runtime·racereadpc(fm.array + i*width, pc, runtime·copy);
}
}
......@@ -259,7 +259,7 @@ runtime·slicestringcopy(Slice to, String fm, intgo ret)
if(raceenabled) {
pc = runtime·getcallerpc(&to);
for(i=0; i<ret; i++) {
runtime·racewritepc(to.array + i, pc);
runtime·racewritepc(to.array + i, pc, runtime·slicestringcopy);
}
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment