Commit 1cc2ff8f authored by Keith Randall's avatar Keith Randall

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://golang.org/cl/43490044
parent 7ff57e2f
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "malloc.h" #include "malloc.h"
#include "type.h" #include "type.h"
#include "race.h" #include "race.h"
#include "typekind.h"
#include "../../cmd/ld/textflag.h" #include "../../cmd/ld/textflag.h"
// This file contains the implementation of Go's map type. // This file contains the implementation of Go's map type.
...@@ -997,7 +998,10 @@ runtime·mapaccess1(MapType *t, Hmap *h, byte *ak, byte *av) ...@@ -997,7 +998,10 @@ runtime·mapaccess1(MapType *t, Hmap *h, byte *ak, byte *av)
{ {
if(raceenabled && h != nil) { if(raceenabled && h != nil) {
runtime·racereadpc(h, runtime·getcallerpc(&t), runtime·mapaccess1); 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) { if(h == nil || h->count == 0) {
av = t->elem->zero; av = t->elem->zero;
...@@ -1028,7 +1032,10 @@ runtime·mapaccess2(MapType *t, Hmap *h, byte *ak, byte *av, bool pres) ...@@ -1028,7 +1032,10 @@ runtime·mapaccess2(MapType *t, Hmap *h, byte *ak, byte *av, bool pres)
{ {
if(raceenabled && h != nil) { if(raceenabled && h != nil) {
runtime·racereadpc(h, runtime·getcallerpc(&t), runtime·mapaccess2); 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) { if(h == nil || h->count == 0) {
...@@ -1066,7 +1073,10 @@ reflect·mapaccess(MapType *t, Hmap *h, byte *key, byte *val) ...@@ -1066,7 +1073,10 @@ reflect·mapaccess(MapType *t, Hmap *h, byte *key, byte *val)
{ {
if(raceenabled && h != nil) { if(raceenabled && h != nil) {
runtime·racereadpc(h, runtime·getcallerpc(&t), reflect·mapaccess); 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); val = hash_lookup(t, h, &key);
FLUSH(&val); FLUSH(&val);
...@@ -1082,8 +1092,14 @@ runtime·mapassign1(MapType *t, Hmap *h, byte *ak, byte *av) ...@@ -1082,8 +1092,14 @@ runtime·mapassign1(MapType *t, Hmap *h, byte *ak, byte *av)
if(raceenabled) { if(raceenabled) {
runtime·racewritepc(h, runtime·getcallerpc(&t), runtime·mapassign1); runtime·racewritepc(h, runtime·getcallerpc(&t), runtime·mapassign1);
runtime·racereadpc(ak, runtime·getcallerpc(&t), runtime·mapassign1); if(t->key->kind == KindArray || t->key->kind == KindStruct)
runtime·racereadpc(av, runtime·getcallerpc(&t), runtime·mapassign1); 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); hash_insert(t, h, ak, av);
...@@ -1109,7 +1125,10 @@ runtime·mapdelete(MapType *t, Hmap *h, byte *ak) ...@@ -1109,7 +1125,10 @@ runtime·mapdelete(MapType *t, Hmap *h, byte *ak)
if(raceenabled) { if(raceenabled) {
runtime·racewritepc(h, runtime·getcallerpc(&t), runtime·mapdelete); 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); hash_remove(t, h, ak);
...@@ -1132,8 +1151,14 @@ reflect·mapassign(MapType *t, Hmap *h, byte *key, byte *val) ...@@ -1132,8 +1151,14 @@ reflect·mapassign(MapType *t, Hmap *h, byte *key, byte *val)
runtime·panicstring("assignment to entry in nil map"); runtime·panicstring("assignment to entry in nil map");
if(raceenabled) { if(raceenabled) {
runtime·racewritepc(h, runtime·getcallerpc(&t), reflect·mapassign); runtime·racewritepc(h, runtime·getcallerpc(&t), reflect·mapassign);
runtime·racereadrangepc(key, t->key->size, runtime·getcallerpc(&t), reflect·mapassign); if(t->key->kind == KindArray || t->key->kind == KindStruct)
runtime·racereadrangepc(val, t->elem->size, runtime·getcallerpc(&t), reflect·mapassign); 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); hash_insert(t, h, key, val);
...@@ -1157,8 +1182,11 @@ reflect·mapdelete(MapType *t, Hmap *h, byte *key) ...@@ -1157,8 +1182,11 @@ reflect·mapdelete(MapType *t, Hmap *h, byte *key)
if(h == nil) if(h == nil)
runtime·panicstring("delete from nil map"); runtime·panicstring("delete from nil map");
if(raceenabled) { if(raceenabled) {
runtime·racewritepc(h, runtime·getcallerpc(&t), reflect·mapassign); runtime·racewritepc(h, runtime·getcallerpc(&t), reflect·mapdelete);
runtime·racereadrangepc(key, t->key->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·mapdelete);
else
runtime·racereadpc(key, runtime·getcallerpc(&t), reflect·mapdelete);
} }
hash_remove(t, h, key); hash_remove(t, h, key);
......
...@@ -159,3 +159,64 @@ func TestRaceMapVariable3(t *testing.T) { ...@@ -159,3 +159,64 @@ func TestRaceMapVariable3(t *testing.T) {
m = make(map[int]int) m = make(map[int]int)
<-ch <-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
}
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