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