xref: /openbsd-src/gnu/llvm/compiler-rt/lib/scudo/standalone/tsd.h (revision d89ec533011f513df1010f142a111086a0785f09)
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