13cab2bb3Spatrick //===-- tsd.h ---------------------------------------------------*- C++ -*-===// 23cab2bb3Spatrick // 33cab2bb3Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 43cab2bb3Spatrick // See https://llvm.org/LICENSE.txt for license information. 53cab2bb3Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 63cab2bb3Spatrick // 73cab2bb3Spatrick //===----------------------------------------------------------------------===// 83cab2bb3Spatrick 93cab2bb3Spatrick #ifndef SCUDO_TSD_H_ 103cab2bb3Spatrick #define SCUDO_TSD_H_ 113cab2bb3Spatrick 123cab2bb3Spatrick #include "atomic_helpers.h" 133cab2bb3Spatrick #include "common.h" 143cab2bb3Spatrick #include "mutex.h" 153cab2bb3Spatrick 163cab2bb3Spatrick #include <limits.h> // for PTHREAD_DESTRUCTOR_ITERATIONS 173cab2bb3Spatrick #include <pthread.h> 183cab2bb3Spatrick 193cab2bb3Spatrick // With some build setups, this might still not be defined. 203cab2bb3Spatrick #ifndef PTHREAD_DESTRUCTOR_ITERATIONS 213cab2bb3Spatrick #define PTHREAD_DESTRUCTOR_ITERATIONS 4 223cab2bb3Spatrick #endif 233cab2bb3Spatrick 243cab2bb3Spatrick namespace scudo { 253cab2bb3Spatrick 261f9cb04fSpatrick template <class Allocator> struct alignas(SCUDO_CACHE_LINE_SIZE) TSD { 273cab2bb3Spatrick typename Allocator::CacheT Cache; 283cab2bb3Spatrick typename Allocator::QuarantineCacheT QuarantineCache; 29*d89ec533Spatrick using ThisT = TSD<Allocator>; 30*d89ec533Spatrick u8 DestructorIterations = 0; 313cab2bb3Spatrick initTSD32*d89ec533Spatrick void init(Allocator *Instance) { 33*d89ec533Spatrick DCHECK_EQ(DestructorIterations, 0U); 34*d89ec533Spatrick DCHECK(isAligned(reinterpret_cast<uptr>(this), alignof(ThisT))); 353cab2bb3Spatrick Instance->initCache(&Cache); 363cab2bb3Spatrick DestructorIterations = PTHREAD_DESTRUCTOR_ITERATIONS; 373cab2bb3Spatrick } 383cab2bb3Spatrick commitBackTSD393cab2bb3Spatrick void commitBack(Allocator *Instance) { Instance->commitBack(this); } 403cab2bb3Spatrick tryLockTSD413cab2bb3Spatrick inline bool tryLock() { 423cab2bb3Spatrick if (Mutex.tryLock()) { 433cab2bb3Spatrick atomic_store_relaxed(&Precedence, 0); 443cab2bb3Spatrick return true; 453cab2bb3Spatrick } 463cab2bb3Spatrick if (atomic_load_relaxed(&Precedence) == 0) 473cab2bb3Spatrick atomic_store_relaxed( 483cab2bb3Spatrick &Precedence, 493cab2bb3Spatrick static_cast<uptr>(getMonotonicTime() >> FIRST_32_SECOND_64(16, 0))); 503cab2bb3Spatrick return false; 513cab2bb3Spatrick } lockTSD523cab2bb3Spatrick inline void lock() { 533cab2bb3Spatrick atomic_store_relaxed(&Precedence, 0); 543cab2bb3Spatrick Mutex.lock(); 553cab2bb3Spatrick } unlockTSD563cab2bb3Spatrick inline void unlock() { Mutex.unlock(); } getPrecedenceTSD573cab2bb3Spatrick inline uptr getPrecedence() { return atomic_load_relaxed(&Precedence); } 583cab2bb3Spatrick 593cab2bb3Spatrick private: 603cab2bb3Spatrick HybridMutex Mutex; 61*d89ec533Spatrick atomic_uptr Precedence = {}; 623cab2bb3Spatrick }; 633cab2bb3Spatrick 643cab2bb3Spatrick } // namespace scudo 653cab2bb3Spatrick 663cab2bb3Spatrick #endif // SCUDO_TSD_H_ 67