diff options
author | Ed Schouten <ed@FreeBSD.org> | 2013-05-27 18:27:12 +0000 |
---|---|---|
committer | Ed Schouten <ed@FreeBSD.org> | 2013-05-27 18:27:12 +0000 |
commit | 11023dc647fd8f41418da90d59db138400d0f334 (patch) | |
tree | 50f0ab80515576749ef638dd0766b70a65904bfa /lib/asan/asan_stats.cc | |
parent | 58aabf08b77d221489f10e274812ec60917c21a8 (diff) | |
download | src-11023dc647fd8f41418da90d59db138400d0f334.tar.gz src-11023dc647fd8f41418da90d59db138400d0f334.zip |
Import compiler-rt r182741.vendor/compiler-rt/compiler-rt-r182741
Notes
Notes:
svn path=/vendor/compiler-rt/dist/; revision=251034
svn path=/vendor/compiler-rt/compiler-rt-r182741/; revision=251036; tag=vendor/compiler-rt/compiler-rt-r182741
Diffstat (limited to 'lib/asan/asan_stats.cc')
-rw-r--r-- | lib/asan/asan_stats.cc | 96 |
1 files changed, 89 insertions, 7 deletions
diff --git a/lib/asan/asan_stats.cc b/lib/asan/asan_stats.cc index c57c8cc61aed..ba7c1ab6e91a 100644 --- a/lib/asan/asan_stats.cc +++ b/lib/asan/asan_stats.cc @@ -14,14 +14,14 @@ #include "asan_interceptors.h" #include "asan_internal.h" #include "asan_stats.h" -#include "asan_thread_registry.h" -#include "sanitizer/asan_interface.h" +#include "asan_thread.h" +#include "sanitizer_common/sanitizer_mutex.h" #include "sanitizer_common/sanitizer_stackdepot.h" namespace __asan { AsanStats::AsanStats() { - CHECK(REAL(memset) != 0); + CHECK(REAL(memset)); REAL(memset)(this, 0, sizeof(AsanStats)); } @@ -58,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(); @@ -68,21 +68,103 @@ 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); + +static 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 FlushThreadStats(ThreadContextBase *tctx_base, void *arg) { + AsanThreadContext *tctx = static_cast<AsanThreadContext*>(tctx_base); + if (AsanThread *t = tctx->thread) + FlushToAccumulatedStatsUnlocked(&t->stats()); +} + +static void UpdateAccumulatedStatsUnlocked() { + acc_stats_lock.CheckLocked(); + { + ThreadRegistryLock l(&asanThreadRegistry()); + asanThreadRegistry().RunCallbackForEachThreadLocked(FlushThreadStats, 0); + } + 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() { |