sanitizer_allocator_stats.h 2.8 KB

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