diff options
author | Dmitry Vyukov <dvyukov@google.com> | 2014-03-18 12:52:11 +0000 |
---|---|---|
committer | Dmitry Vyukov <dvyukov@google.com> | 2014-03-18 12:52:11 +0000 |
commit | 86dc858403e5d177ef6b6b0ad18ebb05d5639902 (patch) | |
tree | 95f7706e742be3a267e984ca70459cd45787907c /lib/sanitizer_common/sanitizer_addrhashmap.h | |
parent | f73c290ccab7a9da388530c7778aa0eb85eb8766 (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.h | 13 |
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? |