]> git.proxmox.com Git - rustc.git/blame - src/compiler-rt/lib/sanitizer_common/sanitizer_allocator_stats.h
New upstream version 1.19.0+dfsg3
[rustc.git] / src / compiler-rt / lib / sanitizer_common / sanitizer_allocator_stats.h
CommitLineData
7cac9316
XL
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