1 //===-- scudo_tsd_shared.cpp ------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 /// Scudo shared TSD implementation.
12 //===----------------------------------------------------------------------===//
14 #include "scudo_tsd.h"
16 #if !SCUDO_TSD_EXCLUSIVE
20 static pthread_once_t GlobalInitialized = PTHREAD_ONCE_INIT;
21 pthread_key_t PThreadKey;
23 static atomic_uint32_t CurrentIndex;
24 static ScudoTSD *TSDs;
25 static u32 NumberOfTSDs;
27 static void initOnce() {
28 CHECK_EQ(pthread_key_create(&PThreadKey, NULL), 0);
30 NumberOfTSDs = Min(Max(1U, GetNumberOfCPUsCached()),
31 static_cast<u32>(SCUDO_SHARED_TSD_POOL_SIZE));
32 TSDs = reinterpret_cast<ScudoTSD *>(
33 MmapOrDie(sizeof(ScudoTSD) * NumberOfTSDs, "ScudoTSDs"));
34 for (u32 i = 0; i < NumberOfTSDs; i++)
35 TSDs[i].init(/*Shared=*/true);
38 ALWAYS_INLINE void setCurrentTSD(ScudoTSD *TSD) {
40 *get_android_tls_ptr() = reinterpret_cast<uptr>(TSD);
42 CHECK_EQ(pthread_setspecific(PThreadKey, reinterpret_cast<void *>(TSD)), 0);
43 #endif // SANITIZER_ANDROID
46 void initThread(bool MinimalInit) {
47 pthread_once(&GlobalInitialized, initOnce);
48 // Initial context assignment is done in a plain round-robin fashion.
49 u32 Index = atomic_fetch_add(&CurrentIndex, 1, memory_order_relaxed);
50 setCurrentTSD(&TSDs[Index % NumberOfTSDs]);
53 ScudoTSD *getTSDAndLockSlow() {
55 if (NumberOfTSDs > 1) {
56 // Go through all the contexts and find the first unlocked one.
57 for (u32 i = 0; i < NumberOfTSDs; i++) {
64 // No luck, find the one with the lowest Precedence, and slow lock it.
65 u64 LowestPrecedence = UINT64_MAX;
66 for (u32 i = 0; i < NumberOfTSDs; i++) {
67 u64 Precedence = TSDs[i].getPrecedence();
68 if (Precedence && Precedence < LowestPrecedence) {
70 LowestPrecedence = Precedence;
73 if (LIKELY(LowestPrecedence != UINT64_MAX)) {
79 // Last resort, stick with the current one.
80 TSD = getCurrentTSD();
85 } // namespace __scudo
87 #endif // !SCUDO_TSD_EXCLUSIVE