diff options
author | Keith Randall <khr@golang.org> | 2013-12-30 12:03:56 -0800 |
---|---|---|
committer | Keith Randall <khr@golang.org> | 2013-12-30 12:03:56 -0800 |
commit | f365787a2def763ed4d98d4b5cbb97023a4fbf13 (patch) | |
tree | e82693d94bbd08f8df3bbcc29c83e4efd30c824c | |
parent | 82026136dea9dd53274b5cfe259b872cebccb0ba (diff) | |
download | go-f365787a2def763ed4d98d4b5cbb97023a4fbf13.tar.gz |
runtime: use readrange instead of read to check for races
on map keys and values which are now passed by reference.
R=dvyukov, khr
CC=golang-codereviews
https://codereview.appspot.com/43490044
-rw-r--r-- | src/pkg/runtime/hashmap.c | 48 | ||||
-rw-r--r-- | src/pkg/runtime/race/testdata/map_test.go | 61 |
2 files changed, 99 insertions, 10 deletions
diff --git a/src/pkg/runtime/hashmap.c b/src/pkg/runtime/hashmap.c index 5d625c15a..410ce53c7 100644 --- a/src/pkg/runtime/hashmap.c +++ b/src/pkg/runtime/hashmap.c @@ -7,6 +7,7 @@ #include "malloc.h" #include "type.h" #include "race.h" +#include "typekind.h" #include "../../cmd/ld/textflag.h" // This file contains the implementation of Go's map type. @@ -997,7 +998,10 @@ runtime·mapaccess1(MapType *t, Hmap *h, byte *ak, byte *av) { if(raceenabled && h != nil) { runtime·racereadpc(h, runtime·getcallerpc(&t), runtime·mapaccess1); - runtime·racereadpc(ak, runtime·getcallerpc(&t), runtime·mapaccess1); + if(t->key->kind == KindArray || t->key->kind == KindStruct) + runtime·racereadrangepc(ak, t->key->size, runtime·getcallerpc(&t), runtime·mapaccess1); + else + runtime·racereadpc(ak, runtime·getcallerpc(&t), runtime·mapaccess1); } if(h == nil || h->count == 0) { av = t->elem->zero; @@ -1028,7 +1032,10 @@ runtime·mapaccess2(MapType *t, Hmap *h, byte *ak, byte *av, bool pres) { if(raceenabled && h != nil) { runtime·racereadpc(h, runtime·getcallerpc(&t), runtime·mapaccess2); - runtime·racereadpc(ak, runtime·getcallerpc(&t), runtime·mapaccess2); + if(t->key->kind == KindArray || t->key->kind == KindStruct) + runtime·racereadrangepc(ak, t->key->size, runtime·getcallerpc(&t), runtime·mapaccess2); + else + runtime·racereadpc(ak, runtime·getcallerpc(&t), runtime·mapaccess2); } if(h == nil || h->count == 0) { @@ -1066,7 +1073,10 @@ reflect·mapaccess(MapType *t, Hmap *h, byte *key, byte *val) { if(raceenabled && h != nil) { runtime·racereadpc(h, runtime·getcallerpc(&t), reflect·mapaccess); - runtime·racereadrangepc(key, t->key->size, runtime·getcallerpc(&t), reflect·mapaccess); + if(t->key->kind == KindArray || t->key->kind == KindStruct) + runtime·racereadrangepc(key, t->key->size, runtime·getcallerpc(&t), reflect·mapaccess); + else + runtime·racereadpc(key, runtime·getcallerpc(&t), reflect·mapaccess); } val = hash_lookup(t, h, &key); FLUSH(&val); @@ -1082,8 +1092,14 @@ runtime·mapassign1(MapType *t, Hmap *h, byte *ak, byte *av) if(raceenabled) { runtime·racewritepc(h, runtime·getcallerpc(&t), runtime·mapassign1); - runtime·racereadpc(ak, runtime·getcallerpc(&t), runtime·mapassign1); - runtime·racereadpc(av, runtime·getcallerpc(&t), runtime·mapassign1); + if(t->key->kind == KindArray || t->key->kind == KindStruct) + runtime·racereadrangepc(ak, t->key->size, runtime·getcallerpc(&t), runtime·mapassign1); + else + runtime·racereadpc(ak, runtime·getcallerpc(&t), runtime·mapassign1); + if(t->elem->kind == KindArray || t->elem->kind == KindStruct) + runtime·racereadrangepc(av, t->elem->size, runtime·getcallerpc(&t), runtime·mapassign1); + else + runtime·racereadpc(av, runtime·getcallerpc(&t), runtime·mapassign1); } hash_insert(t, h, ak, av); @@ -1109,7 +1125,10 @@ runtime·mapdelete(MapType *t, Hmap *h, byte *ak) if(raceenabled) { runtime·racewritepc(h, runtime·getcallerpc(&t), runtime·mapdelete); - runtime·racereadpc(ak, runtime·getcallerpc(&t), runtime·mapdelete); + if(t->key->kind == KindArray || t->key->kind == KindStruct) + runtime·racereadrangepc(ak, t->key->size, runtime·getcallerpc(&t), runtime·mapdelete); + else + runtime·racereadpc(ak, runtime·getcallerpc(&t), runtime·mapdelete); } hash_remove(t, h, ak); @@ -1132,8 +1151,14 @@ reflect·mapassign(MapType *t, Hmap *h, byte *key, byte *val) runtime·panicstring("assignment to entry in nil map"); if(raceenabled) { runtime·racewritepc(h, runtime·getcallerpc(&t), reflect·mapassign); - runtime·racereadrangepc(key, t->key->size, runtime·getcallerpc(&t), reflect·mapassign); - runtime·racereadrangepc(val, t->elem->size, runtime·getcallerpc(&t), reflect·mapassign); + if(t->key->kind == KindArray || t->key->kind == KindStruct) + runtime·racereadrangepc(key, t->key->size, runtime·getcallerpc(&t), reflect·mapassign); + else + runtime·racereadpc(key, runtime·getcallerpc(&t), reflect·mapassign); + if(t->elem->kind == KindArray || t->elem->kind == KindStruct) + runtime·racereadrangepc(val, t->elem->size, runtime·getcallerpc(&t), reflect·mapassign); + else + runtime·racereadpc(val, runtime·getcallerpc(&t), reflect·mapassign); } hash_insert(t, h, key, val); @@ -1157,8 +1182,11 @@ reflect·mapdelete(MapType *t, Hmap *h, byte *key) if(h == nil) runtime·panicstring("delete from nil map"); if(raceenabled) { - runtime·racewritepc(h, runtime·getcallerpc(&t), reflect·mapassign); - runtime·racereadrangepc(key, t->key->size, runtime·getcallerpc(&t), reflect·mapassign); + runtime·racewritepc(h, runtime·getcallerpc(&t), reflect·mapdelete); + if(t->key->kind == KindArray || t->key->kind == KindStruct) + runtime·racereadrangepc(key, t->key->size, runtime·getcallerpc(&t), reflect·mapdelete); + else + runtime·racereadpc(key, runtime·getcallerpc(&t), reflect·mapdelete); } hash_remove(t, h, key); diff --git a/src/pkg/runtime/race/testdata/map_test.go b/src/pkg/runtime/race/testdata/map_test.go index 35db8db69..9ba74b141 100644 --- a/src/pkg/runtime/race/testdata/map_test.go +++ b/src/pkg/runtime/race/testdata/map_test.go @@ -159,3 +159,64 @@ func TestRaceMapVariable3(t *testing.T) { m = make(map[int]int) <-ch } + +type Big struct { + x [17]int32 +} + +func TestRaceMapLookupPartKey(t *testing.T) { + k := &Big{} + m := make(map[Big]bool) + ch := make(chan bool, 1) + go func() { + k.x[8] = 1 + ch <- true + }() + _ = m[*k] + <-ch +} + +func TestRaceMapLookupPartKey2(t *testing.T) { + k := &Big{} + m := make(map[Big]bool) + ch := make(chan bool, 1) + go func() { + k.x[8] = 1 + ch <- true + }() + _, _ = m[*k] + <-ch +} +func TestRaceMapDeletePartKey(t *testing.T) { + k := &Big{} + m := make(map[Big]bool) + ch := make(chan bool, 1) + go func() { + k.x[8] = 1 + ch <- true + }() + delete(m, *k) + <-ch +} +func TestRaceMapInsertPartKey(t *testing.T) { + k := &Big{} + m := make(map[Big]bool) + ch := make(chan bool, 1) + go func() { + k.x[8] = 1 + ch <- true + }() + m[*k] = true + <-ch +} +func TestRaceMapInsertPartVal(t *testing.T) { + v := &Big{} + m := make(map[int]Big) + ch := make(chan bool, 1) + go func() { + v.x[8] = 1 + ch <- true + }() + m[1] = *v + <-ch +} |