1 //===-- stats.h -------------------------------------------------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
10 #define SCUDO_STATS_H_
12 #include "atomic_helpers.h"
15 #include "thread_annotations.h"
21 // Memory allocator statistics
22 enum StatType
{ StatAllocated
, StatFree
, StatMapped
, StatCount
};
24 typedef uptr StatCounters
[StatCount
];
26 // Per-thread stats, live in per-thread cache. We use atomics so that the
27 // numbers themselves are consistent. But we don't use atomic_{add|sub} or a
28 // lock, because those are expensive operations , and we only care for the stats
29 // to be "somewhat" correct: eg. if we call GlobalStats::get while a thread is
30 // LocalStats::add'ing, this is OK, we will still get a meaningful number.
34 for (uptr I
= 0; I
< StatCount
; I
++)
35 DCHECK_EQ(get(static_cast<StatType
>(I
)), 0U);
38 void add(StatType I
, uptr V
) {
39 V
+= atomic_load_relaxed(&StatsArray
[I
]);
40 atomic_store_relaxed(&StatsArray
[I
], V
);
43 void sub(StatType I
, uptr V
) {
44 V
= atomic_load_relaxed(&StatsArray
[I
]) - V
;
45 atomic_store_relaxed(&StatsArray
[I
], V
);
48 void set(StatType I
, uptr V
) { atomic_store_relaxed(&StatsArray
[I
], V
); }
50 uptr
get(StatType I
) const { return atomic_load_relaxed(&StatsArray
[I
]); }
52 LocalStats
*Next
= nullptr;
53 LocalStats
*Prev
= nullptr;
56 atomic_uptr StatsArray
[StatCount
] = {};
59 // Global stats, used for aggregation and querying.
60 class GlobalStats
: public LocalStats
{
62 void init() { LocalStats::init(); }
64 void link(LocalStats
*S
) EXCLUDES(Mutex
) {
66 StatsList
.push_back(S
);
69 void unlink(LocalStats
*S
) EXCLUDES(Mutex
) {
72 for (uptr I
= 0; I
< StatCount
; I
++)
73 add(static_cast<StatType
>(I
), S
->get(static_cast<StatType
>(I
)));
76 void get(uptr
*S
) const EXCLUDES(Mutex
) {
78 for (uptr I
= 0; I
< StatCount
; I
++)
79 S
[I
] = LocalStats::get(static_cast<StatType
>(I
));
80 for (const auto &Stats
: StatsList
) {
81 for (uptr I
= 0; I
< StatCount
; I
++)
82 S
[I
] += Stats
.get(static_cast<StatType
>(I
));
84 // All stats must be non-negative.
85 for (uptr I
= 0; I
< StatCount
; I
++)
86 S
[I
] = static_cast<sptr
>(S
[I
]) >= 0 ? S
[I
] : 0;
89 void lock() ACQUIRE(Mutex
) { Mutex
.lock(); }
90 void unlock() RELEASE(Mutex
) { Mutex
.unlock(); }
92 void disable() ACQUIRE(Mutex
) { lock(); }
93 void enable() RELEASE(Mutex
) { unlock(); }
96 mutable HybridMutex Mutex
;
97 DoublyLinkedList
<LocalStats
> StatsList
GUARDED_BY(Mutex
);
102 #endif // SCUDO_STATS_H_