/src/llvm-project-18.1.8.src/libcxxabi/src/cxa_exception_storage.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===----------------------------------------------------------------------===// |
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 | | // This file implements the storage for the "Caught Exception Stack" |
9 | | // https://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html#cxx-exc-stack |
10 | | // |
11 | | //===----------------------------------------------------------------------===// |
12 | | |
13 | | #include "cxa_exception.h" |
14 | | |
15 | | #include <__threading_support> |
16 | | |
17 | | #if defined(_LIBCXXABI_HAS_NO_THREADS) |
18 | | |
19 | | namespace __cxxabiv1 { |
20 | | extern "C" { |
21 | | static __cxa_eh_globals eh_globals; |
22 | | __cxa_eh_globals *__cxa_get_globals() { return &eh_globals; } |
23 | | __cxa_eh_globals *__cxa_get_globals_fast() { return &eh_globals; } |
24 | | } // extern "C" |
25 | | } // namespace __cxxabiv1 |
26 | | |
27 | | #elif defined(HAS_THREAD_LOCAL) |
28 | | |
29 | | namespace __cxxabiv1 { |
30 | | namespace { |
31 | | __cxa_eh_globals *__globals() { |
32 | | static thread_local __cxa_eh_globals eh_globals; |
33 | | return &eh_globals; |
34 | | } |
35 | | } // namespace |
36 | | |
37 | | extern "C" { |
38 | | __cxa_eh_globals *__cxa_get_globals() { return __globals(); } |
39 | | __cxa_eh_globals *__cxa_get_globals_fast() { return __globals(); } |
40 | | } // extern "C" |
41 | | } // namespace __cxxabiv1 |
42 | | |
43 | | #else |
44 | | |
45 | | #include "abort_message.h" |
46 | | #include "fallback_malloc.h" |
47 | | |
48 | | #if defined(__ELF__) && defined(_LIBCXXABI_LINK_PTHREAD_LIB) |
49 | | #pragma comment(lib, "pthread") |
50 | | #endif |
51 | | |
52 | | // In general, we treat all threading errors as fatal. |
53 | | // We cannot call std::terminate() because that will in turn |
54 | | // call __cxa_get_globals() and cause infinite recursion. |
55 | | |
56 | | namespace __cxxabiv1 { |
57 | | namespace { |
58 | | std::__libcpp_tls_key key_; |
59 | | std::__libcpp_exec_once_flag flag_ = _LIBCPP_EXEC_ONCE_INITIALIZER; |
60 | | |
61 | 271 | void _LIBCPP_TLS_DESTRUCTOR_CC destruct_(void *p) { |
62 | 271 | __free_with_fallback(p); |
63 | 271 | if (0 != std::__libcpp_tls_set(key_, NULL)) |
64 | 0 | abort_message("cannot zero out thread value for __cxa_get_globals()"); |
65 | 271 | } |
66 | | |
67 | 77 | void construct_() { |
68 | 77 | if (0 != std::__libcpp_tls_create(&key_, destruct_)) |
69 | 0 | abort_message("cannot create thread specific key for __cxa_get_globals()"); |
70 | 77 | } |
71 | | } // namespace |
72 | | |
73 | | extern "C" { |
74 | 4.37M | __cxa_eh_globals *__cxa_get_globals() { |
75 | | // Try to get the globals for this thread |
76 | 4.37M | __cxa_eh_globals *retVal = __cxa_get_globals_fast(); |
77 | | |
78 | | // If this is the first time we've been asked for these globals, create them |
79 | 4.37M | if (NULL == retVal) { |
80 | 348 | retVal = static_cast<__cxa_eh_globals*>( |
81 | 348 | __calloc_with_fallback(1, sizeof(__cxa_eh_globals))); |
82 | 348 | if (NULL == retVal) |
83 | 0 | abort_message("cannot allocate __cxa_eh_globals"); |
84 | 348 | if (0 != std::__libcpp_tls_set(key_, retVal)) |
85 | 0 | abort_message("std::__libcpp_tls_set failure in __cxa_get_globals()"); |
86 | 348 | } |
87 | 4.37M | return retVal; |
88 | 4.37M | } |
89 | | |
90 | | // Note that this implementation will reliably return NULL if not |
91 | | // preceded by a call to __cxa_get_globals(). This is an extension |
92 | | // to the Itanium ABI and is taken advantage of in several places in |
93 | | // libc++abi. |
94 | 6.58M | __cxa_eh_globals *__cxa_get_globals_fast() { |
95 | | // First time through, create the key. |
96 | 6.58M | if (0 != std::__libcpp_execute_once(&flag_, construct_)) |
97 | 0 | abort_message("execute once failure in __cxa_get_globals_fast()"); |
98 | 6.58M | return static_cast<__cxa_eh_globals*>(std::__libcpp_tls_get(key_)); |
99 | 6.58M | } |
100 | | } // extern "C" |
101 | | } // namespace __cxxabiv1 |
102 | | |
103 | | #endif |