summaryrefslogtreecommitdiff
path: root/lib/sanitizer_common/sanitizer_addrhashmap.h
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2014-03-18 12:52:11 +0000
committerDmitry Vyukov <dvyukov@google.com>2014-03-18 12:52:11 +0000
commit86dc858403e5d177ef6b6b0ad18ebb05d5639902 (patch)
tree95f7706e742be3a267e984ca70459cd45787907c /lib/sanitizer_common/sanitizer_addrhashmap.h
parentf73c290ccab7a9da388530c7778aa0eb85eb8766 (diff)
tsan: addrhashmap: fix bug with initialization of addresses in add array
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@204148 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/sanitizer_common/sanitizer_addrhashmap.h')
-rw-r--r--lib/sanitizer_common/sanitizer_addrhashmap.h13
1 files changed, 10 insertions, 3 deletions
diff --git a/lib/sanitizer_common/sanitizer_addrhashmap.h b/lib/sanitizer_common/sanitizer_addrhashmap.h
index 02af54974..c50fb1e33 100644
--- a/lib/sanitizer_common/sanitizer_addrhashmap.h
+++ b/lib/sanitizer_common/sanitizer_addrhashmap.h
@@ -229,6 +229,7 @@ void AddrHashMap<T, kSize>::acquire(Handle *h) {
// Allocate a new add array.
const uptr kInitSize = 64;
add = (AddBucket*)InternalAlloc(kInitSize);
+ internal_memset(add, 0, kInitSize);
add->cap = (kInitSize - sizeof(*add)) / sizeof(add->cells[0]) + 1;
add->size = 0;
atomic_store(&b->add, (uptr)add, memory_order_relaxed);
@@ -237,7 +238,8 @@ void AddrHashMap<T, kSize>::acquire(Handle *h) {
// Grow existing add array.
uptr oldsize = sizeof(*add) + (add->cap - 1) * sizeof(add->cells[0]);
uptr newsize = oldsize * 2;
- AddBucket *add1 = (AddBucket*)InternalAlloc(oldsize * 2);
+ AddBucket *add1 = (AddBucket*)InternalAlloc(newsize);
+ internal_memset(add1, 0, newsize);
add1->cap = (newsize - sizeof(*add)) / sizeof(add->cells[0]) + 1;
add1->size = add->size;
internal_memcpy(add1->cells, add->cells, add->size * sizeof(add->cells[0]));
@@ -248,6 +250,7 @@ void AddrHashMap<T, kSize>::acquire(Handle *h) {
// Store.
uptr i = add->size++;
Cell *c = &add->cells[i];
+ CHECK_EQ(atomic_load(&c->addr, memory_order_relaxed), 0);
h->addidx_ = i;
h->cell_ = c;
}
@@ -274,18 +277,22 @@ void AddrHashMap<T, kSize>::release(Handle *h) {
AddBucket *add = (AddBucket*)atomic_load(&b->add, memory_order_relaxed);
if (h->addidx_ == -1U) {
// Removed from embed array, move an add element into the freed cell.
- if (add) {
+ if (add && add->size != 0) {
uptr last = --add->size;
Cell *c1 = &add->cells[last];
c->val = c1->val;
uptr addr1 = atomic_load(&c1->addr, memory_order_relaxed);
atomic_store(&c->addr, addr1, memory_order_release);
+ atomic_store(&c1->addr, 0, memory_order_release);
}
} else {
// Removed from add array, compact it.
uptr last = --add->size;
Cell *c1 = &add->cells[last];
- *c = *c1;
+ if (c != c1) {
+ *c = *c1;
+ atomic_store(&c1->addr, 0, memory_order_relaxed);
+ }
}
if (add && add->size == 0) {
// FIXME(dvyukov): free add?