Skip to content

Commit 920b3b9

Browse files
author
Alexey Samsonov
committed
[ASan] Move malloc stats collection away from AsanThreadRegistry class.
llvm-svn: 177508
1 parent ff367af commit 920b3b9

File tree

8 files changed

+117
-119
lines changed

8 files changed

+117
-119
lines changed

compiler-rt/lib/asan/asan_allocator.cc

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -427,7 +427,7 @@ class MallocInfo {
427427
free_lists_[size_class] = m;
428428

429429
// Statistics.
430-
AsanStats &thread_stats = asanThreadRegistry().GetCurrentThreadStats();
430+
AsanStats &thread_stats = GetCurrentThreadStats();
431431
thread_stats.real_frees++;
432432
thread_stats.really_freed += m->used_size;
433433
thread_stats.really_freed_redzones += m->Size() - m->used_size;
@@ -454,7 +454,7 @@ class MallocInfo {
454454
u8 *mem = MmapNewPagesAndPoisonShadow(mmap_size);
455455

456456
// Statistics.
457-
AsanStats &thread_stats = asanThreadRegistry().GetCurrentThreadStats();
457+
AsanStats &thread_stats = GetCurrentThreadStats();
458458
thread_stats.mmaps++;
459459
thread_stats.mmaped += mmap_size;
460460
thread_stats.mmaped_by_size[size_class] += n_chunks;
@@ -530,7 +530,7 @@ static u8 *Allocate(uptr alignment, uptr size, StackTrace *stack,
530530
}
531531

532532
AsanThread *t = GetCurrentThread();
533-
AsanStats &thread_stats = asanThreadRegistry().GetCurrentThreadStats();
533+
AsanStats &thread_stats = GetCurrentThreadStats();
534534
// Statistics
535535
thread_stats.mallocs++;
536536
thread_stats.malloced += size;
@@ -627,7 +627,7 @@ static void Deallocate(u8 *ptr, StackTrace *stack, AllocType alloc_type) {
627627
PoisonShadow((uptr)ptr, rounded_size, kAsanHeapFreeMagic);
628628

629629
// Statistics.
630-
AsanStats &thread_stats = asanThreadRegistry().GetCurrentThreadStats();
630+
AsanStats &thread_stats = GetCurrentThreadStats();
631631
thread_stats.frees++;
632632
thread_stats.freed += m->used_size;
633633
thread_stats.freed_by_size[m->SizeClass()]++;
@@ -651,7 +651,7 @@ static u8 *Reallocate(u8 *old_ptr, uptr new_size,
651651
CHECK(old_ptr && new_size);
652652

653653
// Statistics.
654-
AsanStats &thread_stats = asanThreadRegistry().GetCurrentThreadStats();
654+
AsanStats &thread_stats = GetCurrentThreadStats();
655655
thread_stats.reallocs++;
656656
thread_stats.realloced += new_size;
657657

compiler-rt/lib/asan/asan_allocator2.cc

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ struct AsanMapUnmapCallback {
3434
void OnMap(uptr p, uptr size) const {
3535
PoisonShadow(p, size, kAsanHeapLeftRedzoneMagic);
3636
// Statistics.
37-
AsanStats &thread_stats = asanThreadRegistry().GetCurrentThreadStats();
37+
AsanStats &thread_stats = GetCurrentThreadStats();
3838
thread_stats.mmaps++;
3939
thread_stats.mmaped += size;
4040
}
@@ -49,7 +49,7 @@ struct AsanMapUnmapCallback {
4949
uptr shadow_end = RoundDownTo(MemToShadow(p + size), page_size);
5050
FlushUnneededShadowMemory(shadow_beg, shadow_end - shadow_beg);
5151
// Statistics.
52-
AsanStats &thread_stats = asanThreadRegistry().GetCurrentThreadStats();
52+
AsanStats &thread_stats = GetCurrentThreadStats();
5353
thread_stats.munmaps++;
5454
thread_stats.munmaped += size;
5555
}
@@ -274,7 +274,7 @@ struct QuarantineCallback {
274274
}
275275

276276
// Statistics.
277-
AsanStats &thread_stats = asanThreadRegistry().GetCurrentThreadStats();
277+
AsanStats &thread_stats = GetCurrentThreadStats();
278278
thread_stats.real_frees++;
279279
thread_stats.really_freed += m->UsedSize();
280280

@@ -401,7 +401,7 @@ static void *Allocate(uptr size, uptr alignment, StackTrace *stack,
401401
*shadow = size & (SHADOW_GRANULARITY - 1);
402402
}
403403

404-
AsanStats &thread_stats = asanThreadRegistry().GetCurrentThreadStats();
404+
AsanStats &thread_stats = GetCurrentThreadStats();
405405
thread_stats.mallocs++;
406406
thread_stats.malloced += size;
407407
thread_stats.malloced_redzones += needed_size - size;
@@ -452,7 +452,7 @@ static void Deallocate(void *ptr, StackTrace *stack, AllocType alloc_type) {
452452
RoundUpTo(m->UsedSize(), SHADOW_GRANULARITY),
453453
kAsanHeapFreeMagic);
454454

455-
AsanStats &thread_stats = asanThreadRegistry().GetCurrentThreadStats();
455+
AsanStats &thread_stats = GetCurrentThreadStats();
456456
thread_stats.frees++;
457457
thread_stats.freed += m->UsedSize();
458458

@@ -476,7 +476,7 @@ static void *Reallocate(void *old_ptr, uptr new_size, StackTrace *stack) {
476476
uptr chunk_beg = p - kChunkHeaderSize;
477477
AsanChunk *m = reinterpret_cast<AsanChunk *>(chunk_beg);
478478

479-
AsanStats &thread_stats = asanThreadRegistry().GetCurrentThreadStats();
479+
AsanStats &thread_stats = GetCurrentThreadStats();
480480
thread_stats.reallocs++;
481481
thread_stats.realloced += new_size;
482482

compiler-rt/lib/asan/asan_mac.cc

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ void GetStackTrace(StackTrace *stack, uptr max_s, uptr pc, uptr bp, bool fast) {
237237
if ((max_s) > 1) {
238238
stack->max_size = max_s;
239239
if (!asan_inited) return;
240-
if (AsanThread *t = asanThreadRegistry().GetCurrent())
240+
if (AsanThread *t = GetCurrentThread())
241241
stack->FastUnwindStack(pc, bp, t->stack_top(), t->stack_bottom());
242242
}
243243
}
@@ -291,12 +291,12 @@ typedef struct {
291291

292292
static ALWAYS_INLINE
293293
void asan_register_worker_thread(int parent_tid, StackTrace *stack) {
294-
AsanThread *t = asanThreadRegistry().GetCurrent();
294+
AsanThread *t = GetCurrentThread();
295295
if (!t) {
296296
t = AsanThread::Create(parent_tid, 0, 0, stack);
297297
asanThreadRegistry().RegisterThread(t);
298298
t->Init();
299-
asanThreadRegistry().SetCurrent(t);
299+
SetCurrentThread(t);
300300
}
301301
}
302302

@@ -330,7 +330,7 @@ asan_block_context_t *alloc_asan_context(void *ctxt, dispatch_function_t func,
330330
(asan_block_context_t*) asan_malloc(sizeof(asan_block_context_t), stack);
331331
asan_ctxt->block = ctxt;
332332
asan_ctxt->func = func;
333-
asan_ctxt->parent_tid = asanThreadRegistry().GetCurrentTidOrInvalid();
333+
asan_ctxt->parent_tid = GetCurrentTidOrInvalid();
334334
return asan_ctxt;
335335
}
336336

@@ -396,7 +396,7 @@ void dispatch_source_set_event_handler(dispatch_source_t ds, void(^work)(void));
396396

397397
#define GET_ASAN_BLOCK(work) \
398398
void (^asan_block)(void); \
399-
int parent_tid = asanThreadRegistry().GetCurrentTidOrInvalid(); \
399+
int parent_tid = GetCurrentTidOrInvalid(); \
400400
asan_block = ^(void) { \
401401
GET_STACK_TRACE_THREAD; \
402402
asan_register_worker_thread(parent_tid, &stack); \

compiler-rt/lib/asan/asan_malloc_mac.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,7 @@ void mi_force_unlock(malloc_zone_t *zone) {
285285

286286
void mi_statistics(malloc_zone_t *zone, malloc_statistics_t *stats) {
287287
AsanMallocStats malloc_stats;
288-
asanThreadRegistry().FillMallocStatistics(&malloc_stats);
288+
FillMallocStatistics(&malloc_stats);
289289
CHECK(sizeof(malloc_statistics_t) == sizeof(AsanMallocStats));
290290
internal_memcpy(stats, &malloc_stats, sizeof(malloc_statistics_t));
291291
}

compiler-rt/lib/asan/asan_stats.cc

Lines changed: 78 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "asan_internal.h"
1616
#include "asan_stats.h"
1717
#include "asan_thread_registry.h"
18+
#include "sanitizer_common/sanitizer_mutex.h"
1819
#include "sanitizer_common/sanitizer_stackdepot.h"
1920

2021
namespace __asan {
@@ -57,7 +58,7 @@ static BlockingMutex print_lock(LINKER_INITIALIZED);
5758

5859
static void PrintAccumulatedStats() {
5960
AsanStats stats;
60-
asanThreadRegistry().GetAccumulatedStats(&stats);
61+
GetAccumulatedStats(&stats);
6162
// Use lock to keep reports from mixing up.
6263
BlockingMutexLock lock(&print_lock);
6364
stats.Print();
@@ -67,21 +68,94 @@ static void PrintAccumulatedStats() {
6768
PrintInternalAllocatorStats();
6869
}
6970

71+
static AsanStats unknown_thread_stats(LINKER_INITIALIZED);
72+
static AsanStats accumulated_stats(LINKER_INITIALIZED);
73+
// Required for malloc_zone_statistics() on OS X. This can't be stored in
74+
// per-thread AsanStats.
75+
static uptr max_malloced_memory;
76+
static BlockingMutex acc_stats_lock(LINKER_INITIALIZED);
77+
78+
void FlushToAccumulatedStatsUnlocked(AsanStats *stats) {
79+
acc_stats_lock.CheckLocked();
80+
uptr *dst = (uptr*)&accumulated_stats;
81+
uptr *src = (uptr*)stats;
82+
uptr num_fields = sizeof(*stats) / sizeof(uptr);
83+
for (uptr i = 0; i < num_fields; i++) {
84+
dst[i] += src[i];
85+
src[i] = 0;
86+
}
87+
}
88+
89+
static void UpdateAccumulatedStatsUnlocked() {
90+
acc_stats_lock.CheckLocked();
91+
asanThreadRegistry().FlushAllStats();
92+
FlushToAccumulatedStatsUnlocked(&unknown_thread_stats);
93+
// This is not very accurate: we may miss allocation peaks that happen
94+
// between two updates of accumulated_stats_. For more accurate bookkeeping
95+
// the maximum should be updated on every malloc(), which is unacceptable.
96+
if (max_malloced_memory < accumulated_stats.malloced) {
97+
max_malloced_memory = accumulated_stats.malloced;
98+
}
99+
}
100+
101+
void FlushToAccumulatedStats(AsanStats *stats) {
102+
BlockingMutexLock lock(&acc_stats_lock);
103+
FlushToAccumulatedStatsUnlocked(stats);
104+
}
105+
106+
void GetAccumulatedStats(AsanStats *stats) {
107+
BlockingMutexLock lock(&acc_stats_lock);
108+
UpdateAccumulatedStatsUnlocked();
109+
internal_memcpy(stats, &accumulated_stats, sizeof(accumulated_stats));
110+
}
111+
112+
void FillMallocStatistics(AsanMallocStats *malloc_stats) {
113+
BlockingMutexLock lock(&acc_stats_lock);
114+
UpdateAccumulatedStatsUnlocked();
115+
malloc_stats->blocks_in_use = accumulated_stats.mallocs;
116+
malloc_stats->size_in_use = accumulated_stats.malloced;
117+
malloc_stats->max_size_in_use = max_malloced_memory;
118+
malloc_stats->size_allocated = accumulated_stats.mmaped;
119+
}
120+
121+
AsanStats &GetCurrentThreadStats() {
122+
AsanThread *t = GetCurrentThread();
123+
return (t) ? t->stats() : unknown_thread_stats;
124+
}
125+
70126
} // namespace __asan
71127

72128
// ---------------------- Interface ---------------- {{{1
73129
using namespace __asan; // NOLINT
74130

75131
uptr __asan_get_current_allocated_bytes() {
76-
return asanThreadRegistry().GetCurrentAllocatedBytes();
132+
BlockingMutexLock lock(&acc_stats_lock);
133+
UpdateAccumulatedStatsUnlocked();
134+
uptr malloced = accumulated_stats.malloced;
135+
uptr freed = accumulated_stats.freed;
136+
// Return sane value if malloced < freed due to racy
137+
// way we update accumulated stats.
138+
return (malloced > freed) ? malloced - freed : 1;
77139
}
78140

79141
uptr __asan_get_heap_size() {
80-
return asanThreadRegistry().GetHeapSize();
142+
BlockingMutexLock lock(&acc_stats_lock);
143+
UpdateAccumulatedStatsUnlocked();
144+
return accumulated_stats.mmaped - accumulated_stats.munmaped;
81145
}
82146

83147
uptr __asan_get_free_bytes() {
84-
return asanThreadRegistry().GetFreeBytes();
148+
BlockingMutexLock lock(&acc_stats_lock);
149+
UpdateAccumulatedStatsUnlocked();
150+
uptr total_free = accumulated_stats.mmaped
151+
- accumulated_stats.munmaped
152+
+ accumulated_stats.really_freed
153+
+ accumulated_stats.really_freed_redzones;
154+
uptr total_used = accumulated_stats.malloced
155+
+ accumulated_stats.malloced_redzones;
156+
// Return sane value if total_free < total_used due to racy
157+
// way we update accumulated stats.
158+
return (total_free > total_used) ? total_free - total_used : 1;
85159
}
86160

87161
uptr __asan_get_unmapped_bytes() {

compiler-rt/lib/asan/asan_stats.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,17 @@ struct AsanStats {
5656
void Print();
5757
};
5858

59+
// Returns stats for GetCurrentThread(), or stats for fake "unknown thread"
60+
// if GetCurrentThread() returns 0.
61+
AsanStats &GetCurrentThreadStats();
62+
// Flushes all thread-local stats to accumulated stats, and makes
63+
// a copy of accumulated stats.
64+
void GetAccumulatedStats(AsanStats *stats);
65+
// Flushes a given stats into accumulated stats.
66+
void FlushToAccumulatedStats(AsanStats *stats);
67+
// FIXME: Hide this method when AsanThreadRegistry is removed.
68+
void FlushToAccumulatedStatsUnlocked(AsanStats *stats);
69+
5970
// A cross-platform equivalent of malloc_statistics_t on Mac OS.
6071
struct AsanMallocStats {
6172
uptr blocks_in_use;
@@ -64,6 +75,8 @@ struct AsanMallocStats {
6475
uptr size_allocated;
6576
};
6677

78+
void FillMallocStatistics(AsanMallocStats *malloc_stats);
79+
6780
} // namespace __asan
6881

6982
#endif // ASAN_STATS_H

0 commit comments

Comments
 (0)