1 //===-- sanitizer_allocator_stats.h -----------------------------*- C++ -*-===// 2 // 3 // This file is distributed under the University of Illinois Open Source 4 // License. See LICENSE.TXT for details. 5 // 6 //===----------------------------------------------------------------------===// 7 // 8 // Part of the Sanitizer Allocator. 9 // 10 //===----------------------------------------------------------------------===// 11 #ifndef SANITIZER_ALLOCATOR_H 12 #error This file must be included inside sanitizer_allocator.h 13 #endif 14 15 // Memory allocator statistics 16 enum AllocatorStat { 17 AllocatorStatAllocated, 18 AllocatorStatMapped, 19 AllocatorStatCount 20 }; 21 22 typedef uptr AllocatorStatCounters[AllocatorStatCount]; 23 24 // Per-thread stats, live in per-thread cache. 25 class AllocatorStats { 26 public: Init()27 void Init() { 28 internal_memset(this, 0, sizeof(*this)); 29 } InitLinkerInitialized()30 void InitLinkerInitialized() {} 31 Add(AllocatorStat i,uptr v)32 void Add(AllocatorStat i, uptr v) { 33 v += atomic_load(&stats_[i], memory_order_relaxed); 34 atomic_store(&stats_[i], v, memory_order_relaxed); 35 } 36 Sub(AllocatorStat i,uptr v)37 void Sub(AllocatorStat i, uptr v) { 38 v = atomic_load(&stats_[i], memory_order_relaxed) - v; 39 atomic_store(&stats_[i], v, memory_order_relaxed); 40 } 41 Set(AllocatorStat i,uptr v)42 void Set(AllocatorStat i, uptr v) { 43 atomic_store(&stats_[i], v, memory_order_relaxed); 44 } 45 Get(AllocatorStat i)46 uptr Get(AllocatorStat i) const { 47 return atomic_load(&stats_[i], memory_order_relaxed); 48 } 49 50 private: 51 friend class AllocatorGlobalStats; 52 AllocatorStats *next_; 53 AllocatorStats *prev_; 54 atomic_uintptr_t stats_[AllocatorStatCount]; 55 }; 56 57 // Global stats, used for aggregation and querying. 58 class AllocatorGlobalStats : public AllocatorStats { 59 public: InitLinkerInitialized()60 void InitLinkerInitialized() { 61 next_ = this; 62 prev_ = this; 63 } Init()64 void Init() { 65 internal_memset(this, 0, sizeof(*this)); 66 InitLinkerInitialized(); 67 } 68 Register(AllocatorStats * s)69 void Register(AllocatorStats *s) { 70 SpinMutexLock l(&mu_); 71 s->next_ = next_; 72 s->prev_ = this; 73 next_->prev_ = s; 74 next_ = s; 75 } 76 Unregister(AllocatorStats * s)77 void Unregister(AllocatorStats *s) { 78 SpinMutexLock l(&mu_); 79 s->prev_->next_ = s->next_; 80 s->next_->prev_ = s->prev_; 81 for (int i = 0; i < AllocatorStatCount; i++) 82 Add(AllocatorStat(i), s->Get(AllocatorStat(i))); 83 } 84 Get(AllocatorStatCounters s)85 void Get(AllocatorStatCounters s) const { 86 internal_memset(s, 0, AllocatorStatCount * sizeof(uptr)); 87 SpinMutexLock l(&mu_); 88 const AllocatorStats *stats = this; 89 for (;;) { 90 for (int i = 0; i < AllocatorStatCount; i++) 91 s[i] += stats->Get(AllocatorStat(i)); 92 stats = stats->next_; 93 if (stats == this) 94 break; 95 } 96 // All stats must be non-negative. 97 for (int i = 0; i < AllocatorStatCount; i++) 98 s[i] = ((sptr)s[i]) >= 0 ? s[i] : 0; 99 } 100 101 private: 102 mutable SpinMutex mu_; 103 }; 104