[compiler-rt] r177508 - [ASan] Move malloc stats collection away from AsanThreadRegistry class.

Alexey Samsonov samsonov at google.com
Wed Mar 20 03:11:24 PDT 2013


Author: samsonov
Date: Wed Mar 20 05:11:24 2013
New Revision: 177508

URL: http://llvm.org/viewvc/llvm-project?rev=177508&view=rev
Log:
[ASan] Move malloc stats collection away from AsanThreadRegistry class.

Modified:
    compiler-rt/trunk/lib/asan/asan_allocator.cc
    compiler-rt/trunk/lib/asan/asan_allocator2.cc
    compiler-rt/trunk/lib/asan/asan_mac.cc
    compiler-rt/trunk/lib/asan/asan_malloc_mac.cc
    compiler-rt/trunk/lib/asan/asan_stats.cc
    compiler-rt/trunk/lib/asan/asan_stats.h
    compiler-rt/trunk/lib/asan/asan_thread_registry.cc
    compiler-rt/trunk/lib/asan/asan_thread_registry.h

Modified: compiler-rt/trunk/lib/asan/asan_allocator.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_allocator.cc?rev=177508&r1=177507&r2=177508&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_allocator.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_allocator.cc Wed Mar 20 05:11:24 2013
@@ -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
   }
 
   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, StackTra
   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
   CHECK(old_ptr && new_size);
 
   // Statistics.
-  AsanStats &thread_stats = asanThreadRegistry().GetCurrentThreadStats();
+  AsanStats &thread_stats = GetCurrentThreadStats();
   thread_stats.reallocs++;
   thread_stats.realloced += new_size;
 

Modified: compiler-rt/trunk/lib/asan/asan_allocator2.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_allocator2.cc?rev=177508&r1=177507&r2=177508&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_allocator2.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_allocator2.cc Wed Mar 20 05:11:24 2013
@@ -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 al
     *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, StackT
                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, u
   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;
 

Modified: compiler-rt/trunk/lib/asan/asan_mac.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_mac.cc?rev=177508&r1=177507&r2=177508&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_mac.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_mac.cc Wed Mar 20 05:11:24 2013
@@ -237,7 +237,7 @@ void GetStackTrace(StackTrace *stack, up
   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
       (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(d
 
 #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); \

Modified: compiler-rt/trunk/lib/asan/asan_malloc_mac.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_malloc_mac.cc?rev=177508&r1=177507&r2=177508&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_malloc_mac.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_malloc_mac.cc Wed Mar 20 05:11:24 2013
@@ -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));
 }

Modified: compiler-rt/trunk/lib/asan/asan_stats.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_stats.cc?rev=177508&r1=177507&r2=177508&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_stats.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_stats.cc Wed Mar 20 05:11:24 2013
@@ -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_I
 
 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() {

Modified: compiler-rt/trunk/lib/asan/asan_stats.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_stats.h?rev=177508&r1=177507&r2=177508&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_stats.h (original)
+++ compiler-rt/trunk/lib/asan/asan_stats.h Wed Mar 20 05:11:24 2013
@@ -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

Modified: compiler-rt/trunk/lib/asan/asan_thread_registry.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_thread_registry.cc?rev=177508&r1=177507&r2=177508&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_thread_registry.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_thread_registry.cc Wed Mar 20 05:11:24 2013
@@ -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(
 
 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::FindThre
   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

Modified: compiler-rt/trunk/lib/asan/asan_thread_registry.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_thread_registry.h?rev=177508&r1=177507&r2=177508&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_thread_registry.h (original)
+++ compiler-rt/trunk/lib/asan/asan_thread_registry.h Wed Mar 20 05:11:24 2013
@@ -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_;





More information about the llvm-commits mailing list