summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Potapenko <glider@google.com>2012-09-12 15:29:50 +0000
committerAlexander Potapenko <glider@google.com>2012-09-12 15:29:50 +0000
commitca2cdd989076d091d8c4d4c277f8b47d9b5903ad (patch)
tree8f4bc4213fea8c3fea18c2106d4f0c35040e4091
parent0fb4069dd0d0ef4c105105affea821f516a353a5 (diff)
downloadcompiler-rt-ca2cdd989076d091d8c4d4c277f8b47d9b5903ad.tar.gz
Give more accurate malloc statistics to malloc_zone_statistics().
Fix a warning in macros instantiation. git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@163716 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/asan/asan_malloc_mac.cc12
-rw-r--r--lib/asan/asan_stats.h8
-rw-r--r--lib/asan/asan_thread_registry.cc18
-rw-r--r--lib/asan/asan_thread_registry.h4
-rw-r--r--lib/asan/tests/asan_test.cc14
5 files changed, 50 insertions, 6 deletions
diff --git a/lib/asan/asan_malloc_mac.cc b/lib/asan/asan_malloc_mac.cc
index 0243bf991..5cd63304e 100644
--- a/lib/asan/asan_malloc_mac.cc
+++ b/lib/asan/asan_malloc_mac.cc
@@ -25,6 +25,8 @@
#include "asan_mac.h"
#include "asan_report.h"
#include "asan_stack.h"
+#include "asan_stats.h"
+#include "asan_thread_registry.h"
// Similar code is used in Google Perftools,
// http://code.google.com/p/google-perftools.
@@ -276,7 +278,6 @@ void mz_free_definite_size(malloc_zone_t* zone, void *ptr, size_t size) {
#endif
#endif
-// malloc_introspection callbacks. I'm not clear on what all of these do.
kern_return_t mi_enumerator(task_t task, void *,
unsigned type_mask, vm_address_t zone_address,
memory_reader_t reader,
@@ -313,11 +314,10 @@ void mi_force_unlock(malloc_zone_t *zone) {
}
void mi_statistics(malloc_zone_t *zone, malloc_statistics_t *stats) {
- // TODO(glider): fill these correctly.
- stats->blocks_in_use = 0;
- stats->size_in_use = 0;
- stats->max_size_in_use = 0;
- stats->size_allocated = 0;
+ AsanMallocStats malloc_stats;
+ asanThreadRegistry().FillMallocStatistics(&malloc_stats);
+ CHECK(sizeof(malloc_statistics_t) == sizeof(AsanMallocStats));
+ internal_memcpy(stats, &malloc_stats, sizeof(malloc_statistics_t));
}
#if defined(MAC_OS_X_VERSION_10_6) && \
diff --git a/lib/asan/asan_stats.h b/lib/asan/asan_stats.h
index b4c63f44f..0c02b3a59 100644
--- a/lib/asan/asan_stats.h
+++ b/lib/asan/asan_stats.h
@@ -54,6 +54,14 @@ struct AsanStats {
void Print();
};
+// A cross-platform equivalent of malloc_statistics_t on Mac OS.
+struct AsanMallocStats {
+ uptr blocks_in_use;
+ uptr size_in_use;
+ uptr max_size_in_use;
+ uptr size_allocated;
+};
+
} // namespace __asan
#endif // ASAN_STATS_H
diff --git a/lib/asan/asan_thread_registry.cc b/lib/asan/asan_thread_registry.cc
index 99552f048..877d32b9a 100644
--- a/lib/asan/asan_thread_registry.cc
+++ b/lib/asan/asan_thread_registry.cc
@@ -30,6 +30,7 @@ AsanThreadRegistry::AsanThreadRegistry(LinkerInitialized x)
: main_thread_(x),
main_thread_summary_(x),
accumulated_stats_(x),
+ max_malloced_memory_(x),
mu_(x) { }
void AsanThreadRegistry::Init() {
@@ -131,6 +132,17 @@ uptr AsanThreadRegistry::GetFreeBytes() {
+ accumulated_stats_.really_freed_redzones;
}
+// Return several stats counters with a single call to
+// UpdateAccumulatedStatsUnlocked().
+void AsanThreadRegistry::FillMallocStatistics(AsanMallocStats *malloc_stats) {
+ ScopedLock 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;
+}
+
AsanThreadSummary *AsanThreadRegistry::FindByTid(u32 tid) {
CHECK(tid < n_threads_);
CHECK(thread_summaries_[tid]);
@@ -156,6 +168,12 @@ void AsanThreadRegistry::UpdateAccumulatedStatsUnlocked() {
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) {
diff --git a/lib/asan/asan_thread_registry.h b/lib/asan/asan_thread_registry.h
index 7037b9edc..3ad55f5d5 100644
--- a/lib/asan/asan_thread_registry.h
+++ b/lib/asan/asan_thread_registry.h
@@ -53,6 +53,7 @@ class AsanThreadRegistry {
uptr GetCurrentAllocatedBytes();
uptr GetHeapSize();
uptr GetFreeBytes();
+ void FillMallocStatistics(AsanMallocStats *malloc_stats);
AsanThreadSummary *FindByTid(u32 tid);
AsanThread *FindThreadByStackAddress(uptr addr);
@@ -68,6 +69,9 @@ class AsanThreadRegistry {
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_;
AsanLock mu_;
bool inited_;
diff --git a/lib/asan/tests/asan_test.cc b/lib/asan/tests/asan_test.cc
index 16ca2ecd0..e34c240aa 100644
--- a/lib/asan/tests/asan_test.cc
+++ b/lib/asan/tests/asan_test.cc
@@ -30,6 +30,7 @@
#ifndef __APPLE__
#include <malloc.h>
#else
+#include <malloc/malloc.h>
#include <AvailabilityMacros.h> // For MAC_OS_X_VERSION_*
#include <CoreFoundation/CFString.h>
#endif // __APPLE__
@@ -2093,6 +2094,19 @@ TEST(AddressSanitizerMac, NSObjectOOB) {
TEST(AddressSanitizerMac, NSURLDeallocation) {
TestNSURLDeallocation();
}
+
+// See http://code.google.com/p/address-sanitizer/issues/detail?id=109.
+TEST(AddressSanitizerMac, Mstats) {
+ malloc_statistics_t stats1, stats2;
+ malloc_zone_statistics(/*all zones*/NULL, &stats1);
+ const int kMallocSize = 100000;
+ void *alloc = Ident(malloc(kMallocSize));
+ malloc_zone_statistics(/*all zones*/NULL, &stats2);
+ EXPECT_GT(stats2.blocks_in_use, stats1.blocks_in_use);
+ EXPECT_GE(stats2.size_in_use - stats1.size_in_use, kMallocSize);
+ free(alloc);
+ // Even the default OSX allocator may not change the stats after free().
+}
#endif // __APPLE__
// Test that instrumentation of stack allocations takes into account