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