1 //===-- guarded_pool_allocator_tls.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 GWP_ASAN_GUARDED_POOL_ALLOCATOR_TLS_H_
10 #define GWP_ASAN_GUARDED_POOL_ALLOCATOR_TLS_H_
11 
12 #include "gwp_asan/definitions.h"
13 
14 #include <stdint.h>
15 
16 namespace gwp_asan {
17 // Pack the thread local variables into a struct to ensure that they're in
18 // the same cache line for performance reasons. These are the most touched
19 // variables in GWP-ASan.
20 struct ThreadLocalPackedVariables {
21   constexpr ThreadLocalPackedVariables()
22       : RandomState(0xacd979ce), NextSampleCounter(0), RecursiveGuard(false) {}
23   // Initialised to a magic constant so that an uninitialised GWP-ASan won't
24   // regenerate its sample counter for as long as possible. The xorshift32()
25   // algorithm used below results in getRandomUnsigned32(0xacd979ce) ==
26   // 0xfffffffe.
27   uint32_t RandomState;
28   // Thread-local decrementing counter that indicates that a given allocation
29   // should be sampled when it reaches zero.
30   uint32_t NextSampleCounter : 31;
31   // The mask is needed to silence conversion errors.
32   static const uint32_t NextSampleCounterMask = (1U << 31) - 1;
33   // Guard against recursivity. Unwinders often contain complex behaviour that
34   // may not be safe for the allocator (i.e. the unwinder calls dlopen(),
35   // which calls malloc()). When recursive behaviour is detected, we will
36   // automatically fall back to the supporting allocator to supply the
37   // allocation.
38   bool RecursiveGuard : 1;
39 };
40 static_assert(sizeof(ThreadLocalPackedVariables) == sizeof(uint64_t),
41               "thread local data does not fit in a uint64_t");
42 } // namespace gwp_asan
43 
44 #ifdef GWP_ASAN_PLATFORM_TLS_HEADER
45 #include GWP_ASAN_PLATFORM_TLS_HEADER
46 #else
47 namespace gwp_asan {
48 inline ThreadLocalPackedVariables *getThreadLocals() {
49   alignas(8) static GWP_ASAN_TLS_INITIAL_EXEC ThreadLocalPackedVariables Locals;
50   return &Locals;
51 }
52 } // namespace gwp_asan
53 #endif // GWP_ASAN_PLATFORM_TLS_HEADER
54 
55 #endif // GWP_ASAN_GUARDED_POOL_ALLOCATOR_TLS_H_
56