summaryrefslogtreecommitdiff
path: root/lib/scudo/scudo_tsd_shared.cpp
diff options
context:
space:
mode:
authorKostya Kortchinsky <kostyak@google.com>2017-09-26 17:20:02 +0000
committerKostya Kortchinsky <kostyak@google.com>2017-09-26 17:20:02 +0000
commit7db641bc3ad521e15e8b97fd37f6e7b4666b4188 (patch)
tree71d5b9cf6eeb1ba82e69a46b2f9428346b8a70ea /lib/scudo/scudo_tsd_shared.cpp
parent1ea789be4f8a6a54b46e36fe8a0eed020b7a93ca (diff)
[scudo] Scudo thread specific data refactor, part 3
Summary: Previous parts: D38139, D38183. In this part of the refactor, we abstract the Linux vs Android TSD dissociation in favor of a Exclusive vs Shared one, allowing for easier platform introduction and configuration. Most of this change consist of shuffling the files around to reflect the new organization. We introduce `scudo_platform.h` where platform specific definition lie. This involves the TSD model and the platform specific allocator parameters. In an upcoming CL, those will be configurable via defines, but we currently stick with conservative defaults. Reviewers: alekseyshl, dvyukov Reviewed By: alekseyshl, dvyukov Subscribers: srhines, llvm-commits, mgorny Differential Revision: https://reviews.llvm.org/D38244 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@314224 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/scudo/scudo_tsd_shared.cpp')
-rw-r--r--lib/scudo/scudo_tsd_shared.cpp96
1 files changed, 96 insertions, 0 deletions
diff --git a/lib/scudo/scudo_tsd_shared.cpp b/lib/scudo/scudo_tsd_shared.cpp
new file mode 100644
index 000000000..481635e6a
--- /dev/null
+++ b/lib/scudo/scudo_tsd_shared.cpp
@@ -0,0 +1,96 @@
+//===-- scudo_tsd_shared.cpp ------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// Scudo shared TSD implementation.
+///
+//===----------------------------------------------------------------------===//
+
+#include "scudo_tsd.h"
+
+#if !SCUDO_TSD_EXCLUSIVE
+
+#include <pthread.h>
+
+namespace __scudo {
+
+static pthread_once_t GlobalInitialized = PTHREAD_ONCE_INIT;
+static pthread_key_t PThreadKey;
+
+static atomic_uint32_t CurrentIndex;
+static ScudoTSD *TSDs;
+static u32 NumberOfTSDs;
+
+// sysconf(_SC_NPROCESSORS_{CONF,ONLN}) cannot be used as they allocate memory.
+static uptr getNumberOfCPUs() {
+ cpu_set_t CPUs;
+ CHECK_EQ(sched_getaffinity(0, sizeof(cpu_set_t), &CPUs), 0);
+ return CPU_COUNT(&CPUs);
+}
+
+static void initOnce() {
+ // Hack: TLS_SLOT_TSAN was introduced in N. To be able to use it on M for
+ // testing, we create an unused key. Since the key_data array follows the tls
+ // array, it basically gives us the extra entry we need.
+ // TODO(kostyak): remove and restrict to N and above.
+ CHECK_EQ(pthread_key_create(&PThreadKey, NULL), 0);
+ initScudo();
+ NumberOfTSDs = getNumberOfCPUs();
+ if (NumberOfTSDs == 0)
+ NumberOfTSDs = 1;
+ if (NumberOfTSDs > 32)
+ NumberOfTSDs = 32;
+ TSDs = reinterpret_cast<ScudoTSD *>(
+ MmapOrDie(sizeof(ScudoTSD) * NumberOfTSDs, "ScudoTSDs"));
+ for (u32 i = 0; i < NumberOfTSDs; i++)
+ TSDs[i].init(/*Shared=*/true);
+}
+
+void initThread(bool MinimalInit) {
+ pthread_once(&GlobalInitialized, initOnce);
+ // Initial context assignment is done in a plain round-robin fashion.
+ u32 Index = atomic_fetch_add(&CurrentIndex, 1, memory_order_relaxed);
+ ScudoTSD *TSD = &TSDs[Index % NumberOfTSDs];
+ *get_android_tls_ptr() = reinterpret_cast<uptr>(TSD);
+}
+
+ScudoTSD *getTSDAndLockSlow() {
+ ScudoTSD *TSD;
+ if (NumberOfTSDs > 1) {
+ // Go through all the contexts and find the first unlocked one.
+ for (u32 i = 0; i < NumberOfTSDs; i++) {
+ TSD = &TSDs[i];
+ if (TSD->tryLock()) {
+ *get_android_tls_ptr() = reinterpret_cast<uptr>(TSD);
+ return TSD;
+ }
+ }
+ // No luck, find the one with the lowest Precedence, and slow lock it.
+ u64 LowestPrecedence = UINT64_MAX;
+ for (u32 i = 0; i < NumberOfTSDs; i++) {
+ u64 Precedence = TSDs[i].getPrecedence();
+ if (Precedence && Precedence < LowestPrecedence) {
+ TSD = &TSDs[i];
+ LowestPrecedence = Precedence;
+ }
+ }
+ if (LIKELY(LowestPrecedence != UINT64_MAX)) {
+ TSD->lock();
+ *get_android_tls_ptr() = reinterpret_cast<uptr>(TSD);
+ return TSD;
+ }
+ }
+ // Last resort, stick with the current one.
+ TSD = reinterpret_cast<ScudoTSD *>(*get_android_tls_ptr());
+ TSD->lock();
+ return TSD;
+}
+
+} // namespace __scudo
+
+#endif // !SCUDO_TSD_EXCLUSIVE