xref: /llvm-project/compiler-rt/lib/scudo/standalone/stats.h (revision 6a4c39596d688955f203351bb28f72c7bc1e93d6)
116d9a3a4SKostya Kortchinsky //===-- stats.h -------------------------------------------------*- C++ -*-===//
216d9a3a4SKostya Kortchinsky //
316d9a3a4SKostya Kortchinsky // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
416d9a3a4SKostya Kortchinsky // See https://llvm.org/LICENSE.txt for license information.
516d9a3a4SKostya Kortchinsky // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
616d9a3a4SKostya Kortchinsky //
716d9a3a4SKostya Kortchinsky //===----------------------------------------------------------------------===//
816d9a3a4SKostya Kortchinsky 
916d9a3a4SKostya Kortchinsky #ifndef SCUDO_STATS_H_
1016d9a3a4SKostya Kortchinsky #define SCUDO_STATS_H_
1116d9a3a4SKostya Kortchinsky 
1216d9a3a4SKostya Kortchinsky #include "atomic_helpers.h"
136f2de9cbSKostya Kortchinsky #include "list.h"
1416d9a3a4SKostya Kortchinsky #include "mutex.h"
15*6a4c3959SChia-hung Duan #include "thread_annotations.h"
1616d9a3a4SKostya Kortchinsky 
1716d9a3a4SKostya Kortchinsky #include <string.h>
1816d9a3a4SKostya Kortchinsky 
1916d9a3a4SKostya Kortchinsky namespace scudo {
2016d9a3a4SKostya Kortchinsky 
2116d9a3a4SKostya Kortchinsky // Memory allocator statistics
222be59170SKostya Kortchinsky enum StatType { StatAllocated, StatFree, StatMapped, StatCount };
2316d9a3a4SKostya Kortchinsky 
2416d9a3a4SKostya Kortchinsky typedef uptr StatCounters[StatCount];
2516d9a3a4SKostya Kortchinsky 
2616d9a3a4SKostya Kortchinsky // Per-thread stats, live in per-thread cache. We use atomics so that the
2716d9a3a4SKostya Kortchinsky // numbers themselves are consistent. But we don't use atomic_{add|sub} or a
2816d9a3a4SKostya Kortchinsky // lock, because those are expensive operations , and we only care for the stats
2916d9a3a4SKostya Kortchinsky // to be "somewhat" correct: eg. if we call GlobalStats::get while a thread is
3016d9a3a4SKostya Kortchinsky // LocalStats::add'ing, this is OK, we will still get a meaningful number.
3116d9a3a4SKostya Kortchinsky class LocalStats {
3216d9a3a4SKostya Kortchinsky public:
init()33a45877eeSKostya Kortchinsky   void init() {
34a45877eeSKostya Kortchinsky     for (uptr I = 0; I < StatCount; I++)
35a45877eeSKostya Kortchinsky       DCHECK_EQ(get(static_cast<StatType>(I)), 0U);
36a45877eeSKostya Kortchinsky   }
3716d9a3a4SKostya Kortchinsky 
add(StatType I,uptr V)3816d9a3a4SKostya Kortchinsky   void add(StatType I, uptr V) {
3916d9a3a4SKostya Kortchinsky     V += atomic_load_relaxed(&StatsArray[I]);
4016d9a3a4SKostya Kortchinsky     atomic_store_relaxed(&StatsArray[I], V);
4116d9a3a4SKostya Kortchinsky   }
4216d9a3a4SKostya Kortchinsky 
sub(StatType I,uptr V)4316d9a3a4SKostya Kortchinsky   void sub(StatType I, uptr V) {
4416d9a3a4SKostya Kortchinsky     V = atomic_load_relaxed(&StatsArray[I]) - V;
4516d9a3a4SKostya Kortchinsky     atomic_store_relaxed(&StatsArray[I], V);
4616d9a3a4SKostya Kortchinsky   }
4716d9a3a4SKostya Kortchinsky 
set(StatType I,uptr V)4816d9a3a4SKostya Kortchinsky   void set(StatType I, uptr V) { atomic_store_relaxed(&StatsArray[I], V); }
4916d9a3a4SKostya Kortchinsky 
get(StatType I)5016d9a3a4SKostya Kortchinsky   uptr get(StatType I) const { return atomic_load_relaxed(&StatsArray[I]); }
5116d9a3a4SKostya Kortchinsky 
52d56ef852SVitaly Buka   LocalStats *Next = nullptr;
53d56ef852SVitaly Buka   LocalStats *Prev = nullptr;
546f2de9cbSKostya Kortchinsky 
556f2de9cbSKostya Kortchinsky private:
56d56ef852SVitaly Buka   atomic_uptr StatsArray[StatCount] = {};
5716d9a3a4SKostya Kortchinsky };
5816d9a3a4SKostya Kortchinsky 
5916d9a3a4SKostya Kortchinsky // Global stats, used for aggregation and querying.
6016d9a3a4SKostya Kortchinsky class GlobalStats : public LocalStats {
6116d9a3a4SKostya Kortchinsky public:
init()62a45877eeSKostya Kortchinsky   void init() { LocalStats::init(); }
6316d9a3a4SKostya Kortchinsky 
link(LocalStats * S)64*6a4c3959SChia-hung Duan   void link(LocalStats *S) EXCLUDES(Mutex) {
65aeb38262SKostya Kortchinsky     ScopedLock L(Mutex);
666f2de9cbSKostya Kortchinsky     StatsList.push_back(S);
6716d9a3a4SKostya Kortchinsky   }
6816d9a3a4SKostya Kortchinsky 
unlink(LocalStats * S)69*6a4c3959SChia-hung Duan   void unlink(LocalStats *S) EXCLUDES(Mutex) {
70aeb38262SKostya Kortchinsky     ScopedLock L(Mutex);
716f2de9cbSKostya Kortchinsky     StatsList.remove(S);
7216d9a3a4SKostya Kortchinsky     for (uptr I = 0; I < StatCount; I++)
7316d9a3a4SKostya Kortchinsky       add(static_cast<StatType>(I), S->get(static_cast<StatType>(I)));
7416d9a3a4SKostya Kortchinsky   }
7516d9a3a4SKostya Kortchinsky 
get(uptr * S)76*6a4c3959SChia-hung Duan   void get(uptr *S) const EXCLUDES(Mutex) {
77aeb38262SKostya Kortchinsky     ScopedLock L(Mutex);
7816d9a3a4SKostya Kortchinsky     for (uptr I = 0; I < StatCount; I++)
796f2de9cbSKostya Kortchinsky       S[I] = LocalStats::get(static_cast<StatType>(I));
806f2de9cbSKostya Kortchinsky     for (const auto &Stats : StatsList) {
816f2de9cbSKostya Kortchinsky       for (uptr I = 0; I < StatCount; I++)
826f2de9cbSKostya Kortchinsky         S[I] += Stats.get(static_cast<StatType>(I));
8316d9a3a4SKostya Kortchinsky     }
8416d9a3a4SKostya Kortchinsky     // All stats must be non-negative.
8516d9a3a4SKostya Kortchinsky     for (uptr I = 0; I < StatCount; I++)
8616d9a3a4SKostya Kortchinsky       S[I] = static_cast<sptr>(S[I]) >= 0 ? S[I] : 0;
8716d9a3a4SKostya Kortchinsky   }
8816d9a3a4SKostya Kortchinsky 
lock()89*6a4c3959SChia-hung Duan   void lock() ACQUIRE(Mutex) { Mutex.lock(); }
unlock()90*6a4c3959SChia-hung Duan   void unlock() RELEASE(Mutex) { Mutex.unlock(); }
91e78b64dfSMitch Phillips 
disable()92*6a4c3959SChia-hung Duan   void disable() ACQUIRE(Mutex) { lock(); }
enable()93*6a4c3959SChia-hung Duan   void enable() RELEASE(Mutex) { unlock(); }
949ef6faf4SKostya Kortchinsky 
9516d9a3a4SKostya Kortchinsky private:
96aeb38262SKostya Kortchinsky   mutable HybridMutex Mutex;
97*6a4c3959SChia-hung Duan   DoublyLinkedList<LocalStats> StatsList GUARDED_BY(Mutex);
9816d9a3a4SKostya Kortchinsky };
9916d9a3a4SKostya Kortchinsky 
10016d9a3a4SKostya Kortchinsky } // namespace scudo
10116d9a3a4SKostya Kortchinsky 
10216d9a3a4SKostya Kortchinsky #endif // SCUDO_STATS_H_
103