104 lines · c
1//===-- sanitizer_allocator_stats.h -----------------------------*- C++ -*-===//2//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-exception6//7//===----------------------------------------------------------------------===//8//9// Part of the Sanitizer Allocator.10//11//===----------------------------------------------------------------------===//12#ifndef SANITIZER_ALLOCATOR_H13#error This file must be included inside sanitizer_allocator.h14#endif15 16// Memory allocator statistics17enum AllocatorStat {18 AllocatorStatAllocated,19 AllocatorStatMapped,20 AllocatorStatCount21};22 23typedef uptr AllocatorStatCounters[AllocatorStatCount];24 25// Per-thread stats, live in per-thread cache.26class AllocatorStats {27 public:28 void Init() { internal_memset(this, 0, sizeof(*this)); }29 void Add(AllocatorStat i, uptr v) {30 atomic_fetch_add(&stats_[i], v, memory_order_relaxed);31 }32 33 void Sub(AllocatorStat i, uptr v) {34 atomic_fetch_sub(&stats_[i], v, memory_order_relaxed);35 }36 37 void Set(AllocatorStat i, uptr v) {38 atomic_store(&stats_[i], v, memory_order_relaxed);39 }40 41 uptr Get(AllocatorStat i) const {42 return atomic_load(&stats_[i], memory_order_relaxed);43 }44 45 private:46 friend class AllocatorGlobalStats;47 AllocatorStats *next_;48 AllocatorStats *prev_;49 atomic_uintptr_t stats_[AllocatorStatCount];50};51 52// Global stats, used for aggregation and querying.53class AllocatorGlobalStats : public AllocatorStats {54 public:55 void Init() {56 internal_memset(this, 0, sizeof(*this));57 }58 59 void Register(AllocatorStats *s) {60 SpinMutexLock l(&mu_);61 LazyInit();62 s->next_ = next_;63 s->prev_ = this;64 next_->prev_ = s;65 next_ = s;66 }67 68 void Unregister(AllocatorStats *s) {69 SpinMutexLock l(&mu_);70 s->prev_->next_ = s->next_;71 s->next_->prev_ = s->prev_;72 for (int i = 0; i < AllocatorStatCount; i++)73 Add(AllocatorStat(i), s->Get(AllocatorStat(i)));74 }75 76 void Get(AllocatorStatCounters s) const {77 internal_memset(s, 0, AllocatorStatCount * sizeof(uptr));78 SpinMutexLock l(&mu_);79 const AllocatorStats *stats = this;80 for (; stats;) {81 for (int i = 0; i < AllocatorStatCount; i++)82 s[i] += stats->Get(AllocatorStat(i));83 stats = stats->next_;84 if (stats == this)85 break;86 }87 // All stats must be non-negative.88 for (int i = 0; i < AllocatorStatCount; i++)89 s[i] = ((sptr)s[i]) >= 0 ? s[i] : 0;90 }91 92 private:93 void LazyInit() {94 if (!next_) {95 next_ = this;96 prev_ = this;97 }98 }99 100 mutable StaticSpinMutex mu_;101};102 103 104