[compiler-rt] r355643 - [scudo][standalone] Adding a stats class

Kostya Kortchinsky via llvm-commits llvm-commits at lists.llvm.org
Thu Mar 7 13:44:35 PST 2019


Author: cryptoad
Date: Thu Mar  7 13:44:35 2019
New Revision: 355643

URL: http://llvm.org/viewvc/llvm-project?rev=355643&view=rev
Log:
[scudo][standalone] Adding a stats class

Summary:
This adds simple local & global stats classes to be used by the Primary
and Secondary, and associated test. Note that we don't need the strict
atomicity of the addition & subtraction (as is in sanitizer_common) so
we just use load & store.

Reviewers: morehouse, vitalybuka, eugenis, flowerhack, dmmoore415

Reviewed By: morehouse, vitalybuka

Subscribers: mgorny, delcypher, jfb, #sanitizers, llvm-commits

Tags: #llvm, #sanitizers

Differential Revision: https://reviews.llvm.org/D59031

Added:
    compiler-rt/trunk/lib/scudo/standalone/stats.h
    compiler-rt/trunk/lib/scudo/standalone/tests/stats_test.cc
Modified:
    compiler-rt/trunk/lib/scudo/standalone/CMakeLists.txt
    compiler-rt/trunk/lib/scudo/standalone/tests/CMakeLists.txt

Modified: compiler-rt/trunk/lib/scudo/standalone/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/scudo/standalone/CMakeLists.txt?rev=355643&r1=355642&r2=355643&view=diff
==============================================================================
--- compiler-rt/trunk/lib/scudo/standalone/CMakeLists.txt (original)
+++ compiler-rt/trunk/lib/scudo/standalone/CMakeLists.txt Thu Mar  7 13:44:35 2019
@@ -46,6 +46,7 @@ set(SCUDO_HEADERS
   list.h
   mutex.h
   platform.h
+  stats.h
   vector.h)
 
 if(COMPILER_RT_HAS_SCUDO_STANDALONE)

Added: compiler-rt/trunk/lib/scudo/standalone/stats.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/scudo/standalone/stats.h?rev=355643&view=auto
==============================================================================
--- compiler-rt/trunk/lib/scudo/standalone/stats.h (added)
+++ compiler-rt/trunk/lib/scudo/standalone/stats.h Thu Mar  7 13:44:35 2019
@@ -0,0 +1,105 @@
+//===-- stats.h -------------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SCUDO_STATS_H_
+#define SCUDO_STATS_H_
+
+#include "atomic_helpers.h"
+#include "mutex.h"
+
+#include <string.h>
+
+namespace scudo {
+
+// Memory allocator statistics
+enum StatType { StatAllocated, StatMapped, StatCount };
+
+typedef uptr StatCounters[StatCount];
+
+// Per-thread stats, live in per-thread cache. We use atomics so that the
+// numbers themselves are consistent. But we don't use atomic_{add|sub} or a
+// lock, because those are expensive operations , and we only care for the stats
+// to be "somewhat" correct: eg. if we call GlobalStats::get while a thread is
+// LocalStats::add'ing, this is OK, we will still get a meaningful number.
+class LocalStats {
+public:
+  void initLinkerInitialized() {}
+  void init() { memset(this, 0, sizeof(*this)); }
+
+  void add(StatType I, uptr V) {
+    V += atomic_load_relaxed(&StatsArray[I]);
+    atomic_store_relaxed(&StatsArray[I], V);
+  }
+
+  void sub(StatType I, uptr V) {
+    V = atomic_load_relaxed(&StatsArray[I]) - V;
+    atomic_store_relaxed(&StatsArray[I], V);
+  }
+
+  void set(StatType I, uptr V) { atomic_store_relaxed(&StatsArray[I], V); }
+
+  uptr get(StatType I) const { return atomic_load_relaxed(&StatsArray[I]); }
+
+private:
+  friend class GlobalStats;
+  atomic_uptr StatsArray[StatCount];
+  LocalStats *Next;
+  LocalStats *Prev;
+};
+
+// Global stats, used for aggregation and querying.
+class GlobalStats : public LocalStats {
+public:
+  void initLinkerInitialized() {
+    Next = this;
+    Prev = this;
+  }
+  void init() {
+    memset(this, 0, sizeof(*this));
+    initLinkerInitialized();
+  }
+
+  void link(LocalStats *S) {
+    SpinMutexLock L(&Mutex);
+    S->Next = Next;
+    S->Prev = this;
+    Next->Prev = S;
+    Next = S;
+  }
+
+  void unlink(LocalStats *S) {
+    SpinMutexLock L(&Mutex);
+    S->Prev->Next = S->Next;
+    S->Next->Prev = S->Prev;
+    for (uptr I = 0; I < StatCount; I++)
+      add(static_cast<StatType>(I), S->get(static_cast<StatType>(I)));
+  }
+
+  void get(uptr *S) const {
+    memset(S, 0, StatCount * sizeof(uptr));
+    SpinMutexLock L(&Mutex);
+    const LocalStats *Stats = this;
+    for (;;) {
+      for (uptr I = 0; I < StatCount; I++)
+        S[I] += Stats->get(static_cast<StatType>(I));
+      Stats = Stats->Next;
+      if (Stats == this)
+        break;
+    }
+    // All stats must be non-negative.
+    for (uptr I = 0; I < StatCount; I++)
+      S[I] = static_cast<sptr>(S[I]) >= 0 ? S[I] : 0;
+  }
+
+private:
+  mutable StaticSpinMutex Mutex;
+};
+
+} // namespace scudo
+
+#endif // SCUDO_STATS_H_

Modified: compiler-rt/trunk/lib/scudo/standalone/tests/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/scudo/standalone/tests/CMakeLists.txt?rev=355643&r1=355642&r2=355643&view=diff
==============================================================================
--- compiler-rt/trunk/lib/scudo/standalone/tests/CMakeLists.txt (original)
+++ compiler-rt/trunk/lib/scudo/standalone/tests/CMakeLists.txt Thu Mar  7 13:44:35 2019
@@ -54,6 +54,7 @@ set(SCUDO_UNIT_TEST_SOURCES
   list_test.cc
   map_test.cc
   mutex_test.cc
+  stats_test.cc
   vector_test.cc
   scudo_unit_test_main.cc)
 

Added: compiler-rt/trunk/lib/scudo/standalone/tests/stats_test.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/scudo/standalone/tests/stats_test.cc?rev=355643&view=auto
==============================================================================
--- compiler-rt/trunk/lib/scudo/standalone/tests/stats_test.cc (added)
+++ compiler-rt/trunk/lib/scudo/standalone/tests/stats_test.cc Thu Mar  7 13:44:35 2019
@@ -0,0 +1,45 @@
+//===-- stats_test.cc -------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "scudo/standalone/stats.h"
+#include "gtest/gtest.h"
+
+TEST(ScudoStatsTest, LocalStats) {
+  scudo::LocalStats LStats;
+  LStats.init();
+  for (scudo::uptr I = 0; I < scudo::StatCount; I++)
+    EXPECT_EQ(LStats.get(static_cast<scudo::StatType>(I)), 0U);
+  LStats.add(scudo::StatAllocated, 4096U);
+  EXPECT_EQ(LStats.get(scudo::StatAllocated), 4096U);
+  LStats.sub(scudo::StatAllocated, 4096U);
+  EXPECT_EQ(LStats.get(scudo::StatAllocated), 0U);
+  LStats.set(scudo::StatAllocated, 4096U);
+  EXPECT_EQ(LStats.get(scudo::StatAllocated), 4096U);
+}
+
+TEST(ScudoStatsTest, GlobalStats) {
+  scudo::GlobalStats GStats;
+  GStats.init();
+  scudo::uptr Counters[scudo::StatCount] = {};
+  GStats.get(Counters);
+  for (scudo::uptr I = 0; I < scudo::StatCount; I++)
+    EXPECT_EQ(Counters[I], 0U);
+  scudo::LocalStats LStats;
+  LStats.init();
+  GStats.link(&LStats);
+  for (scudo::uptr I = 0; I < scudo::StatCount; I++)
+    LStats.add(static_cast<scudo::StatType>(I), 4096U);
+  GStats.get(Counters);
+  for (scudo::uptr I = 0; I < scudo::StatCount; I++)
+    EXPECT_EQ(Counters[I], 4096U);
+  // Unlinking the local stats move numbers to the global stats.
+  GStats.unlink(&LStats);
+  GStats.get(Counters);
+  for (scudo::uptr I = 0; I < scudo::StatCount; I++)
+    EXPECT_EQ(Counters[I], 4096U);
+}




More information about the llvm-commits mailing list