diff options
| author | Reid Kleckner <reid@kleckner.net> | 2013-03-06 14:54:08 +0000 |
|---|---|---|
| committer | Reid Kleckner <reid@kleckner.net> | 2013-03-06 14:54:08 +0000 |
| commit | 66c26e5e9621e4e07f92898c6d988b46b89df00c (patch) | |
| tree | 464c2f63c709a592f82457d0fa00fc2ead5c895b /compiler-rt/lib/sanitizer_common/sanitizer_allocator.h | |
| parent | 105963d17ca84733f5f4d3052a916d18f302b080 (diff) | |
| download | bcm5719-llvm-66c26e5e9621e4e07f92898c6d988b46b89df00c.tar.gz bcm5719-llvm-66c26e5e9621e4e07f92898c6d988b46b89df00c.zip | |
[sanitizers] Fix check failure on dealloc from new thread
Summary:
Adds a test for this case, which was reduced from a chromium build of
WebKit's DumpRenderTree.
Reviewers: eugenis
CC: glider
Differential Revision: http://llvm-reviews.chandlerc.com/D495
llvm-svn: 176552
Diffstat (limited to 'compiler-rt/lib/sanitizer_common/sanitizer_allocator.h')
| -rw-r--r-- | compiler-rt/lib/sanitizer_common/sanitizer_allocator.h | 15 |
1 files changed, 13 insertions, 2 deletions
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_allocator.h b/compiler-rt/lib/sanitizer_common/sanitizer_allocator.h index 48b299aa3ff..e1f06f3b6ae 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_allocator.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_allocator.h @@ -342,6 +342,7 @@ class SizeClassAllocator64 { NOINLINE void DeallocateBatch(AllocatorStats *stat, uptr class_id, Batch *b) { RegionInfo *region = GetRegionInfo(class_id); + CHECK_GT(b->count, 0); region->free_list.Push(b); region->n_freed += b->count; } @@ -535,6 +536,7 @@ class SizeClassAllocator64 { beg_idx += count * size; if (beg_idx + count * size + size > region->mapped_user) break; + CHECK_GT(b->count, 0); region->free_list.Push(b); } return b; @@ -620,6 +622,7 @@ class SizeClassAllocator32 { CHECK_LT(class_id, kNumClasses); SizeClassInfo *sci = GetSizeClassInfo(class_id); SpinMutexLock l(&sci->mutex); + CHECK_GT(b->count, 0); sci->free_list.push_front(b); } @@ -741,12 +744,15 @@ class SizeClassAllocator32 { } b->batch[b->count++] = (void*)i; if (b->count == max_count) { + CHECK_GT(b->count, 0); sci->free_list.push_back(b); b = 0; } } - if (b) + if (b) { + CHECK_GT(b->count, 0); sci->free_list.push_back(b); + } } struct State { @@ -791,8 +797,12 @@ struct SizeClassAllocatorLocalCache { void Deallocate(SizeClassAllocator *allocator, uptr class_id, void *p) { CHECK_NE(class_id, 0UL); CHECK_LT(class_id, kNumClasses); + // If the first allocator call on a new thread is a deallocation, then + // max_count will be zero, leading to check failure. + InitCache(); stats_.Add(AllocatorStatFreed, SizeClassMap::Size(class_id)); PerClass *c = &per_class_[class_id]; + CHECK_NE(c->max_count, 0UL); if (UNLIKELY(c->count == c->max_count)) Drain(allocator, class_id); c->batch[c->count++] = p; @@ -818,7 +828,7 @@ struct SizeClassAllocatorLocalCache { AllocatorStats stats_; void InitCache() { - if (per_class_[0].max_count) + if (per_class_[1].max_count) return; for (uptr i = 0; i < kNumClasses; i++) { PerClass *c = &per_class_[i]; @@ -853,6 +863,7 @@ struct SizeClassAllocatorLocalCache { } b->count = cnt; c->count -= cnt; + CHECK_GT(b->count, 0); allocator->DeallocateBatch(&stats_, class_id, b); } }; |

