xref: /freebsd/contrib/llvm-project/compiler-rt/lib/scudo/standalone/tsd.h (revision 5ffd83dbcc34f10e07f6d3e968ae6365869615f4)
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 
26*5ffd83dbSDimitry Andric template <class Allocator> struct alignas(SCUDO_CACHE_LINE_SIZE) TSD {
270b57cec5SDimitry Andric   typename Allocator::CacheT Cache;
280b57cec5SDimitry Andric   typename Allocator::QuarantineCacheT QuarantineCache;
290b57cec5SDimitry Andric   u8 DestructorIterations;
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric   void initLinkerInitialized(Allocator *Instance) {
320b57cec5SDimitry Andric     Instance->initCache(&Cache);
330b57cec5SDimitry Andric     DestructorIterations = PTHREAD_DESTRUCTOR_ITERATIONS;
340b57cec5SDimitry Andric   }
350b57cec5SDimitry Andric   void init(Allocator *Instance) {
360b57cec5SDimitry Andric     memset(this, 0, sizeof(*this));
370b57cec5SDimitry Andric     initLinkerInitialized(Instance);
380b57cec5SDimitry Andric   }
390b57cec5SDimitry Andric 
400b57cec5SDimitry Andric   void commitBack(Allocator *Instance) { Instance->commitBack(this); }
410b57cec5SDimitry Andric 
42480093f4SDimitry Andric   inline bool tryLock() {
430b57cec5SDimitry Andric     if (Mutex.tryLock()) {
440b57cec5SDimitry Andric       atomic_store_relaxed(&Precedence, 0);
450b57cec5SDimitry Andric       return true;
460b57cec5SDimitry Andric     }
470b57cec5SDimitry Andric     if (atomic_load_relaxed(&Precedence) == 0)
480b57cec5SDimitry Andric       atomic_store_relaxed(
490b57cec5SDimitry Andric           &Precedence,
500b57cec5SDimitry Andric           static_cast<uptr>(getMonotonicTime() >> FIRST_32_SECOND_64(16, 0)));
510b57cec5SDimitry Andric     return false;
520b57cec5SDimitry Andric   }
53480093f4SDimitry Andric   inline void lock() {
540b57cec5SDimitry Andric     atomic_store_relaxed(&Precedence, 0);
550b57cec5SDimitry Andric     Mutex.lock();
560b57cec5SDimitry Andric   }
57480093f4SDimitry Andric   inline void unlock() { Mutex.unlock(); }
58480093f4SDimitry Andric   inline uptr getPrecedence() { return atomic_load_relaxed(&Precedence); }
590b57cec5SDimitry Andric 
600b57cec5SDimitry Andric private:
610b57cec5SDimitry Andric   HybridMutex Mutex;
620b57cec5SDimitry Andric   atomic_uptr Precedence;
630b57cec5SDimitry Andric };
640b57cec5SDimitry Andric 
650b57cec5SDimitry Andric } // namespace scudo
660b57cec5SDimitry Andric 
670b57cec5SDimitry Andric #endif // SCUDO_TSD_H_
68