]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/compiler-rt/lib/scudo/scudo_tsd_exclusive.cpp
Merge ^/vendor/lld/dist up to its last change, and resolve conflicts.
[FreeBSD/FreeBSD.git] / contrib / llvm-project / compiler-rt / lib / scudo / scudo_tsd_exclusive.cpp
1 //===-- scudo_tsd_exclusive.cpp ---------------------------------*- 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 /// Scudo exclusive TSD implementation.
10 ///
11 //===----------------------------------------------------------------------===//
12
13 #include "scudo_tsd.h"
14
15 #if SCUDO_TSD_EXCLUSIVE
16
17 namespace __scudo {
18
19 static pthread_once_t GlobalInitialized = PTHREAD_ONCE_INIT;
20 static pthread_key_t PThreadKey;
21
22 __attribute__((tls_model("initial-exec")))
23 THREADLOCAL ThreadState ScudoThreadState = ThreadNotInitialized;
24 __attribute__((tls_model("initial-exec")))
25 THREADLOCAL ScudoTSD TSD;
26
27 // Fallback TSD for when the thread isn't initialized yet or is torn down. It
28 // can be shared between multiple threads and as such must be locked.
29 ScudoTSD FallbackTSD;
30
31 static void teardownThread(void *Ptr) {
32   uptr I = reinterpret_cast<uptr>(Ptr);
33   // The glibc POSIX thread-local-storage deallocation routine calls user
34   // provided destructors in a loop of PTHREAD_DESTRUCTOR_ITERATIONS.
35   // We want to be called last since other destructors might call free and the
36   // like, so we wait until PTHREAD_DESTRUCTOR_ITERATIONS before draining the
37   // quarantine and swallowing the cache.
38   if (I > 1) {
39     // If pthread_setspecific fails, we will go ahead with the teardown.
40     if (LIKELY(pthread_setspecific(PThreadKey,
41                                    reinterpret_cast<void *>(I - 1)) == 0))
42       return;
43   }
44   TSD.commitBack();
45   ScudoThreadState = ThreadTornDown;
46 }
47
48
49 static void initOnce() {
50   CHECK_EQ(pthread_key_create(&PThreadKey, teardownThread), 0);
51   initScudo();
52   FallbackTSD.init();
53 }
54
55 void initThread(bool MinimalInit) {
56   CHECK_EQ(pthread_once(&GlobalInitialized, initOnce), 0);
57   if (UNLIKELY(MinimalInit))
58     return;
59   CHECK_EQ(pthread_setspecific(PThreadKey, reinterpret_cast<void *>(
60       GetPthreadDestructorIterations())), 0);
61   TSD.init();
62   ScudoThreadState = ThreadInitialized;
63 }
64
65 }  // namespace __scudo
66
67 #endif  // SCUDO_TSD_EXCLUSIVE