xref: /aosp_15_r20/external/libcxxabi/src/cxa_exception_storage.cpp (revision c05d8e5dc3e10f6ce4317e8bc22cc4a25f55fa94)
1*c05d8e5dSAndroid Build Coastguard Worker //===--------------------- cxa_exception_storage.cpp ----------------------===//
2*c05d8e5dSAndroid Build Coastguard Worker //
3*c05d8e5dSAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*c05d8e5dSAndroid Build Coastguard Worker //
5*c05d8e5dSAndroid Build Coastguard Worker // This file is dual licensed under the MIT and the University of Illinois Open
6*c05d8e5dSAndroid Build Coastguard Worker // Source Licenses. See LICENSE.TXT for details.
7*c05d8e5dSAndroid Build Coastguard Worker //
8*c05d8e5dSAndroid Build Coastguard Worker //
9*c05d8e5dSAndroid Build Coastguard Worker //  This file implements the storage for the "Caught Exception Stack"
10*c05d8e5dSAndroid Build Coastguard Worker //  http://mentorembedded.github.io/cxx-abi/abi-eh.html (section 2.2.2)
11*c05d8e5dSAndroid Build Coastguard Worker //
12*c05d8e5dSAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
13*c05d8e5dSAndroid Build Coastguard Worker 
14*c05d8e5dSAndroid Build Coastguard Worker #include "cxa_exception.hpp"
15*c05d8e5dSAndroid Build Coastguard Worker 
16*c05d8e5dSAndroid Build Coastguard Worker #include <__threading_support>
17*c05d8e5dSAndroid Build Coastguard Worker 
18*c05d8e5dSAndroid Build Coastguard Worker #if defined(_LIBCXXABI_HAS_NO_THREADS)
19*c05d8e5dSAndroid Build Coastguard Worker 
20*c05d8e5dSAndroid Build Coastguard Worker namespace __cxxabiv1 {
21*c05d8e5dSAndroid Build Coastguard Worker extern "C" {
22*c05d8e5dSAndroid Build Coastguard Worker     static __cxa_eh_globals eh_globals;
__cxa_get_globals()23*c05d8e5dSAndroid Build Coastguard Worker     __cxa_eh_globals *__cxa_get_globals() { return &eh_globals; }
__cxa_get_globals_fast()24*c05d8e5dSAndroid Build Coastguard Worker     __cxa_eh_globals *__cxa_get_globals_fast() { return &eh_globals; }
25*c05d8e5dSAndroid Build Coastguard Worker     }
26*c05d8e5dSAndroid Build Coastguard Worker }
27*c05d8e5dSAndroid Build Coastguard Worker 
28*c05d8e5dSAndroid Build Coastguard Worker #elif defined(HAS_THREAD_LOCAL)
29*c05d8e5dSAndroid Build Coastguard Worker 
30*c05d8e5dSAndroid Build Coastguard Worker namespace __cxxabiv1 {
31*c05d8e5dSAndroid Build Coastguard Worker 
32*c05d8e5dSAndroid Build Coastguard Worker namespace {
__globals()33*c05d8e5dSAndroid Build Coastguard Worker     __cxa_eh_globals * __globals () {
34*c05d8e5dSAndroid Build Coastguard Worker         static thread_local __cxa_eh_globals eh_globals;
35*c05d8e5dSAndroid Build Coastguard Worker         return &eh_globals;
36*c05d8e5dSAndroid Build Coastguard Worker         }
37*c05d8e5dSAndroid Build Coastguard Worker     }
38*c05d8e5dSAndroid Build Coastguard Worker 
39*c05d8e5dSAndroid Build Coastguard Worker extern "C" {
__cxa_get_globals()40*c05d8e5dSAndroid Build Coastguard Worker     __cxa_eh_globals * __cxa_get_globals      () { return __globals (); }
__cxa_get_globals_fast()41*c05d8e5dSAndroid Build Coastguard Worker     __cxa_eh_globals * __cxa_get_globals_fast () { return __globals (); }
42*c05d8e5dSAndroid Build Coastguard Worker     }
43*c05d8e5dSAndroid Build Coastguard Worker }
44*c05d8e5dSAndroid Build Coastguard Worker 
45*c05d8e5dSAndroid Build Coastguard Worker #else
46*c05d8e5dSAndroid Build Coastguard Worker 
47*c05d8e5dSAndroid Build Coastguard Worker #include "abort_message.h"
48*c05d8e5dSAndroid Build Coastguard Worker #include "fallback_malloc.h"
49*c05d8e5dSAndroid Build Coastguard Worker 
50*c05d8e5dSAndroid Build Coastguard Worker //  In general, we treat all threading errors as fatal.
51*c05d8e5dSAndroid Build Coastguard Worker //  We cannot call std::terminate() because that will in turn
52*c05d8e5dSAndroid Build Coastguard Worker //  call __cxa_get_globals() and cause infinite recursion.
53*c05d8e5dSAndroid Build Coastguard Worker 
54*c05d8e5dSAndroid Build Coastguard Worker namespace __cxxabiv1 {
55*c05d8e5dSAndroid Build Coastguard Worker namespace {
56*c05d8e5dSAndroid Build Coastguard Worker     std::__libcpp_tls_key key_;
57*c05d8e5dSAndroid Build Coastguard Worker     std::__libcpp_exec_once_flag flag_ = _LIBCPP_EXEC_ONCE_INITIALIZER;
58*c05d8e5dSAndroid Build Coastguard Worker 
destruct_(void * p)59*c05d8e5dSAndroid Build Coastguard Worker     void _LIBCPP_TLS_DESTRUCTOR_CC destruct_ (void *p) {
60*c05d8e5dSAndroid Build Coastguard Worker         __free_with_fallback ( p );
61*c05d8e5dSAndroid Build Coastguard Worker         if ( 0 != std::__libcpp_tls_set ( key_, NULL ) )
62*c05d8e5dSAndroid Build Coastguard Worker             abort_message("cannot zero out thread value for __cxa_get_globals()");
63*c05d8e5dSAndroid Build Coastguard Worker         }
64*c05d8e5dSAndroid Build Coastguard Worker 
construct_()65*c05d8e5dSAndroid Build Coastguard Worker     void construct_ () {
66*c05d8e5dSAndroid Build Coastguard Worker         if ( 0 != std::__libcpp_tls_create ( &key_, destruct_ ) )
67*c05d8e5dSAndroid Build Coastguard Worker             abort_message("cannot create thread specific key for __cxa_get_globals()");
68*c05d8e5dSAndroid Build Coastguard Worker         }
69*c05d8e5dSAndroid Build Coastguard Worker }
70*c05d8e5dSAndroid Build Coastguard Worker 
71*c05d8e5dSAndroid Build Coastguard Worker extern "C" {
__cxa_get_globals()72*c05d8e5dSAndroid Build Coastguard Worker     __cxa_eh_globals * __cxa_get_globals () {
73*c05d8e5dSAndroid Build Coastguard Worker     //  Try to get the globals for this thread
74*c05d8e5dSAndroid Build Coastguard Worker         __cxa_eh_globals* retVal = __cxa_get_globals_fast ();
75*c05d8e5dSAndroid Build Coastguard Worker 
76*c05d8e5dSAndroid Build Coastguard Worker     //  If this is the first time we've been asked for these globals, create them
77*c05d8e5dSAndroid Build Coastguard Worker         if ( NULL == retVal ) {
78*c05d8e5dSAndroid Build Coastguard Worker             retVal = static_cast<__cxa_eh_globals*>
79*c05d8e5dSAndroid Build Coastguard Worker                         (__calloc_with_fallback (1, sizeof (__cxa_eh_globals)));
80*c05d8e5dSAndroid Build Coastguard Worker             if ( NULL == retVal )
81*c05d8e5dSAndroid Build Coastguard Worker                 abort_message("cannot allocate __cxa_eh_globals");
82*c05d8e5dSAndroid Build Coastguard Worker             if ( 0 != std::__libcpp_tls_set ( key_, retVal ) )
83*c05d8e5dSAndroid Build Coastguard Worker                abort_message("std::__libcpp_tls_set failure in __cxa_get_globals()");
84*c05d8e5dSAndroid Build Coastguard Worker            }
85*c05d8e5dSAndroid Build Coastguard Worker         return retVal;
86*c05d8e5dSAndroid Build Coastguard Worker         }
87*c05d8e5dSAndroid Build Coastguard Worker 
88*c05d8e5dSAndroid Build Coastguard Worker     // Note that this implementation will reliably return NULL if not
89*c05d8e5dSAndroid Build Coastguard Worker     // preceded by a call to __cxa_get_globals().  This is an extension
90*c05d8e5dSAndroid Build Coastguard Worker     // to the Itanium ABI and is taken advantage of in several places in
91*c05d8e5dSAndroid Build Coastguard Worker     // libc++abi.
__cxa_get_globals_fast()92*c05d8e5dSAndroid Build Coastguard Worker     __cxa_eh_globals * __cxa_get_globals_fast () {
93*c05d8e5dSAndroid Build Coastguard Worker     //  First time through, create the key.
94*c05d8e5dSAndroid Build Coastguard Worker         if (0 != std::__libcpp_execute_once(&flag_, construct_))
95*c05d8e5dSAndroid Build Coastguard Worker             abort_message("execute once failure in __cxa_get_globals_fast()");
96*c05d8e5dSAndroid Build Coastguard Worker //        static int init = construct_();
97*c05d8e5dSAndroid Build Coastguard Worker         return static_cast<__cxa_eh_globals*>(std::__libcpp_tls_get(key_));
98*c05d8e5dSAndroid Build Coastguard Worker         }
99*c05d8e5dSAndroid Build Coastguard Worker 
100*c05d8e5dSAndroid Build Coastguard Worker }
101*c05d8e5dSAndroid Build Coastguard Worker }
102*c05d8e5dSAndroid Build Coastguard Worker #endif
103