Skip to content
Snippets Groups Projects
Commit f3a96894 authored by Alexander Potapenko's avatar Alexander Potapenko
Browse files

Give more accurate malloc statistics to malloc_zone_statistics().

Fix a warning in macros instantiation.

llvm-svn: 163716
parent 10a448d4
No related branches found
No related tags found
No related merge requests found
...@@ -25,6 +25,8 @@ ...@@ -25,6 +25,8 @@
#include "asan_mac.h" #include "asan_mac.h"
#include "asan_report.h" #include "asan_report.h"
#include "asan_stack.h" #include "asan_stack.h"
#include "asan_stats.h"
#include "asan_thread_registry.h"
// Similar code is used in Google Perftools, // Similar code is used in Google Perftools,
// http://code.google.com/p/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) { ...@@ -276,7 +278,6 @@ void mz_free_definite_size(malloc_zone_t* zone, void *ptr, size_t size) {
#endif #endif
#endif #endif
// malloc_introspection callbacks. I'm not clear on what all of these do.
kern_return_t mi_enumerator(task_t task, void *, kern_return_t mi_enumerator(task_t task, void *,
unsigned type_mask, vm_address_t zone_address, unsigned type_mask, vm_address_t zone_address,
memory_reader_t reader, memory_reader_t reader,
...@@ -313,11 +314,10 @@ void mi_force_unlock(malloc_zone_t *zone) { ...@@ -313,11 +314,10 @@ void mi_force_unlock(malloc_zone_t *zone) {
} }
void mi_statistics(malloc_zone_t *zone, malloc_statistics_t *stats) { void mi_statistics(malloc_zone_t *zone, malloc_statistics_t *stats) {
// TODO(glider): fill these correctly. AsanMallocStats malloc_stats;
stats->blocks_in_use = 0; asanThreadRegistry().FillMallocStatistics(&malloc_stats);
stats->size_in_use = 0; CHECK(sizeof(malloc_statistics_t) == sizeof(AsanMallocStats));
stats->max_size_in_use = 0; internal_memcpy(stats, &malloc_stats, sizeof(malloc_statistics_t));
stats->size_allocated = 0;
} }
#if defined(MAC_OS_X_VERSION_10_6) && \ #if defined(MAC_OS_X_VERSION_10_6) && \
......
...@@ -54,6 +54,14 @@ struct AsanStats { ...@@ -54,6 +54,14 @@ struct AsanStats {
void Print(); 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 } // namespace __asan
#endif // ASAN_STATS_H #endif // ASAN_STATS_H
...@@ -30,6 +30,7 @@ AsanThreadRegistry::AsanThreadRegistry(LinkerInitialized x) ...@@ -30,6 +30,7 @@ AsanThreadRegistry::AsanThreadRegistry(LinkerInitialized x)
: main_thread_(x), : main_thread_(x),
main_thread_summary_(x), main_thread_summary_(x),
accumulated_stats_(x), accumulated_stats_(x),
max_malloced_memory_(x),
mu_(x) { } mu_(x) { }
void AsanThreadRegistry::Init() { void AsanThreadRegistry::Init() {
...@@ -131,6 +132,17 @@ uptr AsanThreadRegistry::GetFreeBytes() { ...@@ -131,6 +132,17 @@ uptr AsanThreadRegistry::GetFreeBytes() {
+ accumulated_stats_.really_freed_redzones; + 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) { AsanThreadSummary *AsanThreadRegistry::FindByTid(u32 tid) {
CHECK(tid < n_threads_); CHECK(tid < n_threads_);
CHECK(thread_summaries_[tid]); CHECK(thread_summaries_[tid]);
...@@ -156,6 +168,12 @@ void AsanThreadRegistry::UpdateAccumulatedStatsUnlocked() { ...@@ -156,6 +168,12 @@ void AsanThreadRegistry::UpdateAccumulatedStatsUnlocked() {
FlushToAccumulatedStatsUnlocked(&t->stats()); 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) { void AsanThreadRegistry::FlushToAccumulatedStatsUnlocked(AsanStats *stats) {
......
...@@ -53,6 +53,7 @@ class AsanThreadRegistry { ...@@ -53,6 +53,7 @@ class AsanThreadRegistry {
uptr GetCurrentAllocatedBytes(); uptr GetCurrentAllocatedBytes();
uptr GetHeapSize(); uptr GetHeapSize();
uptr GetFreeBytes(); uptr GetFreeBytes();
void FillMallocStatistics(AsanMallocStats *malloc_stats);
AsanThreadSummary *FindByTid(u32 tid); AsanThreadSummary *FindByTid(u32 tid);
AsanThread *FindThreadByStackAddress(uptr addr); AsanThread *FindThreadByStackAddress(uptr addr);
...@@ -68,6 +69,9 @@ class AsanThreadRegistry { ...@@ -68,6 +69,9 @@ class AsanThreadRegistry {
AsanThread main_thread_; AsanThread main_thread_;
AsanThreadSummary main_thread_summary_; AsanThreadSummary main_thread_summary_;
AsanStats accumulated_stats_; 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_; u32 n_threads_;
AsanLock mu_; AsanLock mu_;
bool inited_; bool inited_;
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#ifndef __APPLE__ #ifndef __APPLE__
#include <malloc.h> #include <malloc.h>
#else #else
#include <malloc/malloc.h>
#include <AvailabilityMacros.h> // For MAC_OS_X_VERSION_* #include <AvailabilityMacros.h> // For MAC_OS_X_VERSION_*
#include <CoreFoundation/CFString.h> #include <CoreFoundation/CFString.h>
#endif // __APPLE__ #endif // __APPLE__
...@@ -2093,6 +2094,19 @@ TEST(AddressSanitizerMac, NSObjectOOB) { ...@@ -2093,6 +2094,19 @@ TEST(AddressSanitizerMac, NSObjectOOB) {
TEST(AddressSanitizerMac, NSURLDeallocation) { TEST(AddressSanitizerMac, NSURLDeallocation) {
TestNSURLDeallocation(); 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__ #endif // __APPLE__
// Test that instrumentation of stack allocations takes into account // Test that instrumentation of stack allocations takes into account
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment