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