]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: better stack traces in race reports
authorDmitriy Vyukov <dvyukov@google.com>
Fri, 30 Nov 2012 06:29:41 +0000 (10:29 +0400)
committerDmitriy Vyukov <dvyukov@google.com>
Fri, 30 Nov 2012 06:29:41 +0000 (10:29 +0400)
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

src/pkg/runtime/chan.c
src/pkg/runtime/hashmap.c
src/pkg/runtime/race.c
src/pkg/runtime/race.h
src/pkg/runtime/race0.c
src/pkg/runtime/slice.c

index 0aa0b43c56fd50d220ab0b91be8e4ed5ed042545..9b915cef013f1df00e476ae1fe362217c85e6a96 100644 (file)
@@ -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);
        }
 
index 4869669b6e5bde22a4345e52520f8d910194fcda..60c592184e06665c82fcf9713726ff8d659a53df 100644 (file)
@@ -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);
 }
index aae43852a3b6f195e562708ef4d28335cd5e27e6..3cff49d7f96301a51e8f5ef8be2c10e34afbd3e8 100644 (file)
@@ -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;
-               runtime∕race·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);
+                       runtime∕race·FuncEnter(goid, (void*)callpc);
+               }
+               if(write)
+                       runtime∕race·Write(goid, addr, (void*)pc);
+               else
+                       runtime∕race·Read(goid, addr, (void*)pc);
+               if(callpc)
+                       runtime∕race·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;
-               runtime∕race·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()
index 9ebb9d3738e73f6d3a5f09f8c81228d58d7d81da..6ae962941126899f111e63821101f7e1ef68a4b0 100644 (file)
@@ -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);
index 82ebba82298712bb279e58186fa71880edec3afd..0553e170932f400546c97de631768089f23ccd9d 100644 (file)
@@ -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);
 }
 
index 2f62c4c02d5208164d186988e87c815af8f29e32..e2c76eb8e72918d27bc3257ebda3cdcd04a6de80 100644 (file)
@@ -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);
                }
        }