sanitizer_allocator_stats.h revision 311697
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
18enum AllocatorStat {
19  AllocatorStatAllocated,
20  AllocatorStatMapped,
21  AllocatorStatCount
22};
23
24typedef uptr AllocatorStatCounters[AllocatorStatCount];
25
26// Per-thread stats, live in per-thread cache.
27class 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.
60class 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 SpinMutex mu_;
105};
106
107
108