xref: /freebsd/contrib/llvm-project/compiler-rt/lib/scudo/standalone/tsd.h (revision fe6060f10f634930ff71b7c50291ddc610da2475)
10b57cec5SDimitry Andric //===-- tsd.h ---------------------------------------------------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #ifndef SCUDO_TSD_H_
100b57cec5SDimitry Andric #define SCUDO_TSD_H_
110b57cec5SDimitry Andric 
120b57cec5SDimitry Andric #include "atomic_helpers.h"
130b57cec5SDimitry Andric #include "common.h"
140b57cec5SDimitry Andric #include "mutex.h"
150b57cec5SDimitry Andric 
160b57cec5SDimitry Andric #include <limits.h> // for PTHREAD_DESTRUCTOR_ITERATIONS
17480093f4SDimitry Andric #include <pthread.h>
180b57cec5SDimitry Andric 
190b57cec5SDimitry Andric // With some build setups, this might still not be defined.
200b57cec5SDimitry Andric #ifndef PTHREAD_DESTRUCTOR_ITERATIONS
210b57cec5SDimitry Andric #define PTHREAD_DESTRUCTOR_ITERATIONS 4
220b57cec5SDimitry Andric #endif
230b57cec5SDimitry Andric 
240b57cec5SDimitry Andric namespace scudo {
250b57cec5SDimitry Andric 
265ffd83dbSDimitry Andric template <class Allocator> struct alignas(SCUDO_CACHE_LINE_SIZE) TSD {
270b57cec5SDimitry Andric   typename Allocator::CacheT Cache;
280b57cec5SDimitry Andric   typename Allocator::QuarantineCacheT QuarantineCache;
29*fe6060f1SDimitry Andric   using ThisT = TSD<Allocator>;
30*fe6060f1SDimitry Andric   u8 DestructorIterations = 0;
310b57cec5SDimitry Andric 
32*fe6060f1SDimitry Andric   void init(Allocator *Instance) {
33*fe6060f1SDimitry Andric     DCHECK_EQ(DestructorIterations, 0U);
34*fe6060f1SDimitry Andric     DCHECK(isAligned(reinterpret_cast<uptr>(this), alignof(ThisT)));
350b57cec5SDimitry Andric     Instance->initCache(&Cache);
360b57cec5SDimitry Andric     DestructorIterations = PTHREAD_DESTRUCTOR_ITERATIONS;
370b57cec5SDimitry Andric   }
380b57cec5SDimitry Andric 
390b57cec5SDimitry Andric   void commitBack(Allocator *Instance) { Instance->commitBack(this); }
400b57cec5SDimitry Andric 
41480093f4SDimitry Andric   inline bool tryLock() {
420b57cec5SDimitry Andric     if (Mutex.tryLock()) {
430b57cec5SDimitry Andric       atomic_store_relaxed(&Precedence, 0);
440b57cec5SDimitry Andric       return true;
450b57cec5SDimitry Andric     }
460b57cec5SDimitry Andric     if (atomic_load_relaxed(&Precedence) == 0)
470b57cec5SDimitry Andric       atomic_store_relaxed(
480b57cec5SDimitry Andric           &Precedence,
490b57cec5SDimitry Andric           static_cast<uptr>(getMonotonicTime() >> FIRST_32_SECOND_64(16, 0)));
500b57cec5SDimitry Andric     return false;
510b57cec5SDimitry Andric   }
52480093f4SDimitry Andric   inline void lock() {
530b57cec5SDimitry Andric     atomic_store_relaxed(&Precedence, 0);
540b57cec5SDimitry Andric     Mutex.lock();
550b57cec5SDimitry Andric   }
56480093f4SDimitry Andric   inline void unlock() { Mutex.unlock(); }
57480093f4SDimitry Andric   inline uptr getPrecedence() { return atomic_load_relaxed(&Precedence); }
580b57cec5SDimitry Andric 
590b57cec5SDimitry Andric private:
600b57cec5SDimitry Andric   HybridMutex Mutex;
61*fe6060f1SDimitry Andric   atomic_uptr Precedence = {};
620b57cec5SDimitry Andric };
630b57cec5SDimitry Andric 
640b57cec5SDimitry Andric } // namespace scudo
650b57cec5SDimitry Andric 
660b57cec5SDimitry Andric #endif // SCUDO_TSD_H_
67