]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/compiler-rt/lib/sanitizer_common/sanitizer_allocator_stats.h
Merge clang 7.0.1 and several follow-up changes
[FreeBSD/FreeBSD.git] / contrib / compiler-rt / lib / sanitizer_common / sanitizer_allocator_stats.h
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