1 //===-- tsd.h ---------------------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef SCUDO_TSD_H_
10 #define SCUDO_TSD_H_
11 
12 #include "atomic_helpers.h"
13 #include "common.h"
14 #include "mutex.h"
15 
16 #include <limits.h> // for PTHREAD_DESTRUCTOR_ITERATIONS
17 #include <pthread.h>
18 
19 // With some build setups, this might still not be defined.
20 #ifndef PTHREAD_DESTRUCTOR_ITERATIONS
21 #define PTHREAD_DESTRUCTOR_ITERATIONS 4
22 #endif
23 
24 namespace scudo {
25 
26 template <class Allocator> struct alignas(SCUDO_CACHE_LINE_SIZE) TSD {
27   typename Allocator::CacheT Cache;
28   typename Allocator::QuarantineCacheT QuarantineCache;
29   using ThisT = TSD<Allocator>;
30   u8 DestructorIterations = 0;
31 
32   void init(Allocator *Instance) {
33     DCHECK_EQ(DestructorIterations, 0U);
34     DCHECK(isAligned(reinterpret_cast<uptr>(this), alignof(ThisT)));
35     Instance->initCache(&Cache);
36     DestructorIterations = PTHREAD_DESTRUCTOR_ITERATIONS;
37   }
38 
39   void commitBack(Allocator *Instance) { Instance->commitBack(this); }
40 
41   inline bool tryLock() {
42     if (Mutex.tryLock()) {
43       atomic_store_relaxed(&Precedence, 0);
44       return true;
45     }
46     if (atomic_load_relaxed(&Precedence) == 0)
47       atomic_store_relaxed(
48           &Precedence,
49           static_cast<uptr>(getMonotonicTime() >> FIRST_32_SECOND_64(16, 0)));
50     return false;
51   }
52   inline void lock() {
53     atomic_store_relaxed(&Precedence, 0);
54     Mutex.lock();
55   }
56   inline void unlock() { Mutex.unlock(); }
57   inline uptr getPrecedence() { return atomic_load_relaxed(&Precedence); }
58 
59 private:
60   HybridMutex Mutex;
61   atomic_uptr Precedence = {};
62 };
63 
64 } // namespace scudo
65 
66 #endif // SCUDO_TSD_H_
67