summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexey Samsonov <samsonov@google.com>2013-03-20 10:11:24 +0000
committerAlexey Samsonov <samsonov@google.com>2013-03-20 10:11:24 +0000
commitc25e62b0cdbca855e7611583b0ff7013c31db21d (patch)
treecd41e575364532b35796f48d548d2cd38865a3ef
parent4b450f46cac42d473ffa4ff2d8d1395706b9c934 (diff)
downloadcompiler-rt-c25e62b0cdbca855e7611583b0ff7013c31db21d.tar.gz
compiler-rt-c25e62b0cdbca855e7611583b0ff7013c31db21d.tar.bz2
compiler-rt-c25e62b0cdbca855e7611583b0ff7013c31db21d.tar.xz
[ASan] Move malloc stats collection away from AsanThreadRegistry class.
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@177508 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/asan/asan_allocator.cc10
-rw-r--r--lib/asan/asan_allocator2.cc12
-rw-r--r--lib/asan/asan_mac.cc10
-rw-r--r--lib/asan/asan_malloc_mac.cc2
-rw-r--r--lib/asan/asan_stats.cc82
-rw-r--r--lib/asan/asan_stats.h13
-rw-r--r--lib/asan/asan_thread_registry.cc86
-rw-r--r--lib/asan/asan_thread_registry.h21
8 files changed, 117 insertions, 119 deletions
diff --git a/lib/asan/asan_allocator.cc b/lib/asan/asan_allocator.cc
index 9df741fb..49c1f73e 100644
--- a/lib/asan/asan_allocator.cc
+++ b/lib/asan/asan_allocator.cc
@@ -427,7 +427,7 @@ class MallocInfo {
free_lists_[size_class] = m;
// Statistics.
- AsanStats &thread_stats = asanThreadRegistry().GetCurrentThreadStats();
+ AsanStats &thread_stats = GetCurrentThreadStats();
thread_stats.real_frees++;
thread_stats.really_freed += m->used_size;
thread_stats.really_freed_redzones += m->Size() - m->used_size;
@@ -454,7 +454,7 @@ class MallocInfo {
u8 *mem = MmapNewPagesAndPoisonShadow(mmap_size);
// Statistics.
- AsanStats &thread_stats = asanThreadRegistry().GetCurrentThreadStats();
+ AsanStats &thread_stats = GetCurrentThreadStats();
thread_stats.mmaps++;
thread_stats.mmaped += mmap_size;
thread_stats.mmaped_by_size[size_class] += n_chunks;
@@ -530,7 +530,7 @@ static u8 *Allocate(uptr alignment, uptr size, StackTrace *stack,
}
AsanThread *t = GetCurrentThread();
- AsanStats &thread_stats = asanThreadRegistry().GetCurrentThreadStats();
+ AsanStats &thread_stats = GetCurrentThreadStats();
// Statistics
thread_stats.mallocs++;
thread_stats.malloced += size;
@@ -627,7 +627,7 @@ static void Deallocate(u8 *ptr, StackTrace *stack, AllocType alloc_type) {
PoisonShadow((uptr)ptr, rounded_size, kAsanHeapFreeMagic);
// Statistics.
- AsanStats &thread_stats = asanThreadRegistry().GetCurrentThreadStats();
+ AsanStats &thread_stats = GetCurrentThreadStats();
thread_stats.frees++;
thread_stats.freed += m->used_size;
thread_stats.freed_by_size[m->SizeClass()]++;
@@ -651,7 +651,7 @@ static u8 *Reallocate(u8 *old_ptr, uptr new_size,
CHECK(old_ptr && new_size);
// Statistics.
- AsanStats &thread_stats = asanThreadRegistry().GetCurrentThreadStats();
+ AsanStats &thread_stats = GetCurrentThreadStats();
thread_stats.reallocs++;
thread_stats.realloced += new_size;
diff --git a/lib/asan/asan_allocator2.cc b/lib/asan/asan_allocator2.cc
index 77cc87bc..63076c72 100644
--- a/lib/asan/asan_allocator2.cc
+++ b/lib/asan/asan_allocator2.cc
@@ -34,7 +34,7 @@ struct AsanMapUnmapCallback {
void OnMap(uptr p, uptr size) const {
PoisonShadow(p, size, kAsanHeapLeftRedzoneMagic);
// Statistics.
- AsanStats &thread_stats = asanThreadRegistry().GetCurrentThreadStats();
+ AsanStats &thread_stats = GetCurrentThreadStats();
thread_stats.mmaps++;
thread_stats.mmaped += size;
}
@@ -49,7 +49,7 @@ struct AsanMapUnmapCallback {
uptr shadow_end = RoundDownTo(MemToShadow(p + size), page_size);
FlushUnneededShadowMemory(shadow_beg, shadow_end - shadow_beg);
// Statistics.
- AsanStats &thread_stats = asanThreadRegistry().GetCurrentThreadStats();
+ AsanStats &thread_stats = GetCurrentThreadStats();
thread_stats.munmaps++;
thread_stats.munmaped += size;
}
@@ -274,7 +274,7 @@ struct QuarantineCallback {
}
// Statistics.
- AsanStats &thread_stats = asanThreadRegistry().GetCurrentThreadStats();
+ AsanStats &thread_stats = GetCurrentThreadStats();
thread_stats.real_frees++;
thread_stats.really_freed += m->UsedSize();
@@ -401,7 +401,7 @@ static void *Allocate(uptr size, uptr alignment, StackTrace *stack,
*shadow = size & (SHADOW_GRANULARITY - 1);
}
- AsanStats &thread_stats = asanThreadRegistry().GetCurrentThreadStats();
+ AsanStats &thread_stats = GetCurrentThreadStats();
thread_stats.mallocs++;
thread_stats.malloced += size;
thread_stats.malloced_redzones += needed_size - size;
@@ -452,7 +452,7 @@ static void Deallocate(void *ptr, StackTrace *stack, AllocType alloc_type) {
RoundUpTo(m->UsedSize(), SHADOW_GRANULARITY),
kAsanHeapFreeMagic);
- AsanStats &thread_stats = asanThreadRegistry().GetCurrentThreadStats();
+ AsanStats &thread_stats = GetCurrentThreadStats();
thread_stats.frees++;
thread_stats.freed += m->UsedSize();
@@ -476,7 +476,7 @@ static void *Reallocate(void *old_ptr, uptr new_size, StackTrace *stack) {
uptr chunk_beg = p - kChunkHeaderSize;
AsanChunk *m = reinterpret_cast<AsanChunk *>(chunk_beg);
- AsanStats &thread_stats = asanThreadRegistry().GetCurrentThreadStats();
+ AsanStats &thread_stats = GetCurrentThreadStats();
thread_stats.reallocs++;
thread_stats.realloced += new_size;
diff --git a/lib/asan/asan_mac.cc b/lib/asan/asan_mac.cc
index 80dc0f6b..e88aa6a7 100644
--- a/lib/asan/asan_mac.cc
+++ b/lib/asan/asan_mac.cc
@@ -237,7 +237,7 @@ void GetStackTrace(StackTrace *stack, uptr max_s, uptr pc, uptr bp, bool fast) {
if ((max_s) > 1) {
stack->max_size = max_s;
if (!asan_inited) return;
- if (AsanThread *t = asanThreadRegistry().GetCurrent())
+ if (AsanThread *t = GetCurrentThread())
stack->FastUnwindStack(pc, bp, t->stack_top(), t->stack_bottom());
}
}
@@ -291,12 +291,12 @@ typedef struct {
static ALWAYS_INLINE
void asan_register_worker_thread(int parent_tid, StackTrace *stack) {
- AsanThread *t = asanThreadRegistry().GetCurrent();
+ AsanThread *t = GetCurrentThread();
if (!t) {
t = AsanThread::Create(parent_tid, 0, 0, stack);
asanThreadRegistry().RegisterThread(t);
t->Init();
- asanThreadRegistry().SetCurrent(t);
+ SetCurrentThread(t);
}
}
@@ -330,7 +330,7 @@ asan_block_context_t *alloc_asan_context(void *ctxt, dispatch_function_t func,
(asan_block_context_t*) asan_malloc(sizeof(asan_block_context_t), stack);
asan_ctxt->block = ctxt;
asan_ctxt->func = func;
- asan_ctxt->parent_tid = asanThreadRegistry().GetCurrentTidOrInvalid();
+ asan_ctxt->parent_tid = GetCurrentTidOrInvalid();
return asan_ctxt;
}
@@ -396,7 +396,7 @@ void dispatch_source_set_event_handler(dispatch_source_t ds, void(^work)(void));
#define GET_ASAN_BLOCK(work) \
void (^asan_block)(void); \
- int parent_tid = asanThreadRegistry().GetCurrentTidOrInvalid(); \
+ int parent_tid = GetCurrentTidOrInvalid(); \
asan_block = ^(void) { \
GET_STACK_TRACE_THREAD; \
asan_register_worker_thread(parent_tid, &stack); \
diff --git a/lib/asan/asan_malloc_mac.cc b/lib/asan/asan_malloc_mac.cc
index 618dd258..eb66ddab 100644
--- a/lib/asan/asan_malloc_mac.cc
+++ b/lib/asan/asan_malloc_mac.cc
@@ -285,7 +285,7 @@ void mi_force_unlock(malloc_zone_t *zone) {
void mi_statistics(malloc_zone_t *zone, malloc_statistics_t *stats) {
AsanMallocStats malloc_stats;
- asanThreadRegistry().FillMallocStatistics(&malloc_stats);
+ FillMallocStatistics(&malloc_stats);
CHECK(sizeof(malloc_statistics_t) == sizeof(AsanMallocStats));
internal_memcpy(stats, &malloc_stats, sizeof(malloc_statistics_t));
}
diff --git a/lib/asan/asan_stats.cc b/lib/asan/asan_stats.cc
index ba67c820..b1fe7bc4 100644
--- a/lib/asan/asan_stats.cc
+++ b/lib/asan/asan_stats.cc
@@ -15,6 +15,7 @@
#include "asan_internal.h"
#include "asan_stats.h"
#include "asan_thread_registry.h"
+#include "sanitizer_common/sanitizer_mutex.h"
#include "sanitizer_common/sanitizer_stackdepot.h"
namespace __asan {
@@ -57,7 +58,7 @@ static BlockingMutex print_lock(LINKER_INITIALIZED);
static void PrintAccumulatedStats() {
AsanStats stats;
- asanThreadRegistry().GetAccumulatedStats(&stats);
+ GetAccumulatedStats(&stats);
// Use lock to keep reports from mixing up.
BlockingMutexLock lock(&print_lock);
stats.Print();
@@ -67,21 +68,94 @@ static void PrintAccumulatedStats() {
PrintInternalAllocatorStats();
}
+static AsanStats unknown_thread_stats(LINKER_INITIALIZED);
+static AsanStats accumulated_stats(LINKER_INITIALIZED);
+// Required for malloc_zone_statistics() on OS X. This can't be stored in
+// per-thread AsanStats.
+static uptr max_malloced_memory;
+static BlockingMutex acc_stats_lock(LINKER_INITIALIZED);
+
+void FlushToAccumulatedStatsUnlocked(AsanStats *stats) {
+ acc_stats_lock.CheckLocked();
+ uptr *dst = (uptr*)&accumulated_stats;
+ uptr *src = (uptr*)stats;
+ uptr num_fields = sizeof(*stats) / sizeof(uptr);
+ for (uptr i = 0; i < num_fields; i++) {
+ dst[i] += src[i];
+ src[i] = 0;
+ }
+}
+
+static void UpdateAccumulatedStatsUnlocked() {
+ acc_stats_lock.CheckLocked();
+ asanThreadRegistry().FlushAllStats();
+ FlushToAccumulatedStatsUnlocked(&unknown_thread_stats);
+ // This is not very accurate: we may miss allocation peaks that happen
+ // between two updates of accumulated_stats_. For more accurate bookkeeping
+ // the maximum should be updated on every malloc(), which is unacceptable.
+ if (max_malloced_memory < accumulated_stats.malloced) {
+ max_malloced_memory = accumulated_stats.malloced;
+ }
+}
+
+void FlushToAccumulatedStats(AsanStats *stats) {
+ BlockingMutexLock lock(&acc_stats_lock);
+ FlushToAccumulatedStatsUnlocked(stats);
+}
+
+void GetAccumulatedStats(AsanStats *stats) {
+ BlockingMutexLock lock(&acc_stats_lock);
+ UpdateAccumulatedStatsUnlocked();
+ internal_memcpy(stats, &accumulated_stats, sizeof(accumulated_stats));
+}
+
+void FillMallocStatistics(AsanMallocStats *malloc_stats) {
+ BlockingMutexLock lock(&acc_stats_lock);
+ UpdateAccumulatedStatsUnlocked();
+ malloc_stats->blocks_in_use = accumulated_stats.mallocs;
+ malloc_stats->size_in_use = accumulated_stats.malloced;
+ malloc_stats->max_size_in_use = max_malloced_memory;
+ malloc_stats->size_allocated = accumulated_stats.mmaped;
+}
+
+AsanStats &GetCurrentThreadStats() {
+ AsanThread *t = GetCurrentThread();
+ return (t) ? t->stats() : unknown_thread_stats;
+}
+
} // namespace __asan
// ---------------------- Interface ---------------- {{{1
using namespace __asan; // NOLINT
uptr __asan_get_current_allocated_bytes() {
- return asanThreadRegistry().GetCurrentAllocatedBytes();
+ BlockingMutexLock lock(&acc_stats_lock);
+ UpdateAccumulatedStatsUnlocked();
+ uptr malloced = accumulated_stats.malloced;
+ uptr freed = accumulated_stats.freed;
+ // Return sane value if malloced < freed due to racy
+ // way we update accumulated stats.
+ return (malloced > freed) ? malloced - freed : 1;
}
uptr __asan_get_heap_size() {
- return asanThreadRegistry().GetHeapSize();
+ BlockingMutexLock lock(&acc_stats_lock);
+ UpdateAccumulatedStatsUnlocked();
+ return accumulated_stats.mmaped - accumulated_stats.munmaped;
}
uptr __asan_get_free_bytes() {
- return asanThreadRegistry().GetFreeBytes();
+ BlockingMutexLock lock(&acc_stats_lock);
+ UpdateAccumulatedStatsUnlocked();
+ uptr total_free = accumulated_stats.mmaped
+ - accumulated_stats.munmaped
+ + accumulated_stats.really_freed
+ + accumulated_stats.really_freed_redzones;
+ uptr total_used = accumulated_stats.malloced
+ + accumulated_stats.malloced_redzones;
+ // Return sane value if total_free < total_used due to racy
+ // way we update accumulated stats.
+ return (total_free > total_used) ? total_free - total_used : 1;
}
uptr __asan_get_unmapped_bytes() {
diff --git a/lib/asan/asan_stats.h b/lib/asan/asan_stats.h
index 37846bc9..920ac050 100644
--- a/lib/asan/asan_stats.h
+++ b/lib/asan/asan_stats.h
@@ -56,6 +56,17 @@ struct AsanStats {
void Print();
};
+// Returns stats for GetCurrentThread(), or stats for fake "unknown thread"
+// if GetCurrentThread() returns 0.
+AsanStats &GetCurrentThreadStats();
+// Flushes all thread-local stats to accumulated stats, and makes
+// a copy of accumulated stats.
+void GetAccumulatedStats(AsanStats *stats);
+// Flushes a given stats into accumulated stats.
+void FlushToAccumulatedStats(AsanStats *stats);
+// FIXME: Hide this method when AsanThreadRegistry is removed.
+void FlushToAccumulatedStatsUnlocked(AsanStats *stats);
+
// A cross-platform equivalent of malloc_statistics_t on Mac OS.
struct AsanMallocStats {
uptr blocks_in_use;
@@ -64,6 +75,8 @@ struct AsanMallocStats {
uptr size_allocated;
};
+void FillMallocStatistics(AsanMallocStats *malloc_stats);
+
} // namespace __asan
#endif // ASAN_STATS_H
diff --git a/lib/asan/asan_thread_registry.cc b/lib/asan/asan_thread_registry.cc
index 5e875a44..82ee34dc 100644
--- a/lib/asan/asan_thread_registry.cc
+++ b/lib/asan/asan_thread_registry.cc
@@ -29,8 +29,6 @@ AsanThreadRegistry &asanThreadRegistry() {
AsanThreadRegistry::AsanThreadRegistry(LinkerInitialized x)
: main_thread_(x),
main_thread_summary_(x),
- accumulated_stats_(x),
- max_malloced_memory_(x),
mu_(x) { }
void AsanThreadRegistry::Init() {
@@ -57,7 +55,7 @@ void AsanThreadRegistry::RegisterThread(AsanThread *thread) {
void AsanThreadRegistry::UnregisterThread(AsanThread *thread) {
BlockingMutexLock lock(&mu_);
- FlushToAccumulatedStatsUnlocked(&thread->stats());
+ FlushToAccumulatedStats(&thread->stats());
AsanThreadSummary *summary = thread->summary();
CHECK(summary);
summary->set_thread(0);
@@ -67,56 +65,14 @@ AsanThread *AsanThreadRegistry::GetMain() {
return &main_thread_;
}
-AsanStats &AsanThreadRegistry::GetCurrentThreadStats() {
- AsanThread *t = GetCurrentThread();
- return (t) ? t->stats() : main_thread_.stats();
-}
-
-void AsanThreadRegistry::GetAccumulatedStats(AsanStats *stats) {
- BlockingMutexLock lock(&mu_);
- UpdateAccumulatedStatsUnlocked();
- internal_memcpy(stats, &accumulated_stats_, sizeof(accumulated_stats_));
-}
-
-uptr AsanThreadRegistry::GetCurrentAllocatedBytes() {
- BlockingMutexLock lock(&mu_);
- UpdateAccumulatedStatsUnlocked();
- uptr malloced = accumulated_stats_.malloced;
- uptr freed = accumulated_stats_.freed;
- // Return sane value if malloced < freed due to racy
- // way we update accumulated stats.
- return (malloced > freed) ? malloced - freed : 1;
-}
-
-uptr AsanThreadRegistry::GetHeapSize() {
+void AsanThreadRegistry::FlushAllStats() {
BlockingMutexLock lock(&mu_);
- UpdateAccumulatedStatsUnlocked();
- return accumulated_stats_.mmaped - accumulated_stats_.munmaped;
-}
-
-uptr AsanThreadRegistry::GetFreeBytes() {
- BlockingMutexLock lock(&mu_);
- UpdateAccumulatedStatsUnlocked();
- uptr total_free = accumulated_stats_.mmaped
- - accumulated_stats_.munmaped
- + accumulated_stats_.really_freed
- + accumulated_stats_.really_freed_redzones;
- uptr total_used = accumulated_stats_.malloced
- + accumulated_stats_.malloced_redzones;
- // Return sane value if total_free < total_used due to racy
- // way we update accumulated stats.
- return (total_free > total_used) ? total_free - total_used : 1;
-}
-
-// Return several stats counters with a single call to
-// UpdateAccumulatedStatsUnlocked().
-void AsanThreadRegistry::FillMallocStatistics(AsanMallocStats *malloc_stats) {
- BlockingMutexLock lock(&mu_);
- UpdateAccumulatedStatsUnlocked();
- malloc_stats->blocks_in_use = accumulated_stats_.mallocs;
- malloc_stats->size_in_use = accumulated_stats_.malloced;
- malloc_stats->max_size_in_use = max_malloced_memory_;
- malloc_stats->size_allocated = accumulated_stats_.mmaped;
+ for (u32 tid = 0; tid < n_threads_; tid++) {
+ AsanThread *t = thread_summaries_[tid]->thread();
+ if (t != 0) {
+ FlushToAccumulatedStatsUnlocked(&t->stats());
+ }
+ }
}
AsanThreadSummary *AsanThreadRegistry::FindByTid(u32 tid) {
@@ -137,30 +93,4 @@ AsanThread *AsanThreadRegistry::FindThreadByStackAddress(uptr addr) {
return 0;
}
-void AsanThreadRegistry::UpdateAccumulatedStatsUnlocked() {
- for (u32 tid = 0; tid < n_threads_; tid++) {
- AsanThread *t = thread_summaries_[tid]->thread();
- if (t != 0) {
- FlushToAccumulatedStatsUnlocked(&t->stats());
- }
- }
- // This is not very accurate: we may miss allocation peaks that happen
- // between two updates of accumulated_stats_. For more accurate bookkeeping
- // the maximum should be updated on every malloc(), which is unacceptable.
- if (max_malloced_memory_ < accumulated_stats_.malloced) {
- max_malloced_memory_ = accumulated_stats_.malloced;
- }
-}
-
-void AsanThreadRegistry::FlushToAccumulatedStatsUnlocked(AsanStats *stats) {
- // AsanStats consists of variables of type uptr only.
- uptr *dst = (uptr*)&accumulated_stats_;
- uptr *src = (uptr*)stats;
- uptr num_fields = sizeof(AsanStats) / sizeof(uptr);
- for (uptr i = 0; i < num_fields; i++) {
- dst[i] += src[i];
- src[i] = 0;
- }
-}
-
} // namespace __asan
diff --git a/lib/asan/asan_thread_registry.h b/lib/asan/asan_thread_registry.h
index 112f412d..cfa8b668 100644
--- a/lib/asan/asan_thread_registry.h
+++ b/lib/asan/asan_thread_registry.h
@@ -34,35 +34,16 @@ class AsanThreadRegistry {
void UnregisterThread(AsanThread *thread);
AsanThread *GetMain();
-
- // Returns stats for GetCurrentThread(), or stats for
- // T0 if GetCurrentThread() returns 0.
- AsanStats &GetCurrentThreadStats();
- // Flushes all thread-local stats to accumulated stats, and makes
- // a copy of accumulated stats.
- void GetAccumulatedStats(AsanStats *stats);
- uptr GetCurrentAllocatedBytes();
- uptr GetHeapSize();
- uptr GetFreeBytes();
- void FillMallocStatistics(AsanMallocStats *malloc_stats);
+ void FlushAllStats();
AsanThreadSummary *FindByTid(u32 tid);
AsanThread *FindThreadByStackAddress(uptr addr);
private:
- void UpdateAccumulatedStatsUnlocked();
- // Adds values of all counters in "stats" to accumulated stats,
- // and fills "stats" with zeroes.
- void FlushToAccumulatedStatsUnlocked(AsanStats *stats);
-
static const u32 kMaxNumberOfThreads = (1 << 22); // 4M
AsanThreadSummary *thread_summaries_[kMaxNumberOfThreads];
AsanThread main_thread_;
AsanThreadSummary main_thread_summary_;
- AsanStats accumulated_stats_;
- // Required for malloc_zone_statistics() on OS X. This can't be stored in
- // per-thread AsanStats.
- uptr max_malloced_memory_;
u32 n_threads_;
BlockingMutex mu_;
bool inited_;