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
24namespace scudo {
25
26template <class Allocator> struct ALIGNED(SCUDO_CACHE_LINE_SIZE) TSD {
27  typename Allocator::CacheT Cache;
28  typename Allocator::QuarantineCacheT QuarantineCache;
29  u8 DestructorIterations;
30
31  void initLinkerInitialized(Allocator *Instance) {
32    Instance->initCache(&Cache);
33    DestructorIterations = PTHREAD_DESTRUCTOR_ITERATIONS;
34  }
35  void init(Allocator *Instance) {
36    memset(this, 0, sizeof(*this));
37    initLinkerInitialized(Instance);
38  }
39
40  void commitBack(Allocator *Instance) { Instance->commitBack(this); }
41
42  inline bool tryLock() {
43    if (Mutex.tryLock()) {
44      atomic_store_relaxed(&Precedence, 0);
45      return true;
46    }
47    if (atomic_load_relaxed(&Precedence) == 0)
48      atomic_store_relaxed(
49          &Precedence,
50          static_cast<uptr>(getMonotonicTime() >> FIRST_32_SECOND_64(16, 0)));
51    return false;
52  }
53  inline void lock() {
54    atomic_store_relaxed(&Precedence, 0);
55    Mutex.lock();
56  }
57  inline void unlock() { Mutex.unlock(); }
58  inline uptr getPrecedence() { return atomic_load_relaxed(&Precedence); }
59
60private:
61  HybridMutex Mutex;
62  atomic_uptr Precedence;
63};
64
65} // namespace scudo
66
67#endif // SCUDO_TSD_H_
68