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 | |