Index: cmake/config-ix.cmake =================================================================== --- cmake/config-ix.cmake +++ cmake/config-ix.cmake @@ -43,5 +43,3 @@ check_library_exists(dl dladdr "" LIBCXXABI_HAS_DL_LIB) check_library_exists(pthread pthread_once "" LIBCXXABI_HAS_PTHREAD_LIB) check_library_exists(gcc_s __gcc_personality_v0 "" LIBCXXABI_HAS_GCC_S_LIB) -check_library_exists(c __cxa_thread_atexit_impl "" - LIBCXXABI_HAS_CXA_THREAD_ATEXIT_IMPL) Index: src/CMakeLists.txt =================================================================== --- src/CMakeLists.txt +++ src/CMakeLists.txt @@ -41,10 +41,6 @@ include_directories("${LIBCXXABI_LIBCXX_INCLUDES}") -if (LIBCXXABI_HAS_CXA_THREAD_ATEXIT_IMPL) - add_definitions(-DHAVE___CXA_THREAD_ATEXIT_IMPL) -endif() - # Generate library list set(libraries ${LIBCXXABI_CXX_ABI_LIBRARIES}) Index: src/cxa_thread_atexit.cpp =================================================================== --- src/cxa_thread_atexit.cpp +++ src/cxa_thread_atexit.cpp @@ -8,19 +8,85 @@ //===----------------------------------------------------------------------===// #include "cxxabi.h" +#include +#include +#include "abort_message.h" namespace __cxxabiv1 { -extern "C" { +namespace { + typedef void (*Dtor)(void *); + + struct DtorList { + Dtor dtor; + void* obj; + DtorList* next; + }; + + void run_dtors(void* ptr) { + auto elem = static_cast(ptr); + while (elem) { + auto saved = elem; + elem = elem->next; + saved->dtor(saved->obj); + std::free(saved); + } + } + + class DtorListHolder { + public: + DtorListHolder() { + if (pthread_key_create(&key_, run_dtors) != 0) { + abort_message("cannot create pthread key for __cxa_thread_atexit()"); + } + } + + ~DtorListHolder() { + run_dtors(get()); + pthread_key_delete(key_); + } + + DtorList* get() { + return static_cast(pthread_getspecific(key_)); + } + + bool set(DtorList* list) { + return pthread_setspecific(key_, list) == 0; + } + + private: + pthread_key_t key_; + }; +} // namespace -#ifdef HAVE___CXA_THREAD_ATEXIT_IMPL +extern "C" { -_LIBCXXABI_FUNC_VIS int __cxa_thread_atexit(void (*dtor)(void *), void *obj, +_LIBCXXABI_FUNC_VIS int __cxa_thread_atexit(Dtor dtor, void *obj, void *dso_symbol) throw() { - extern int __cxa_thread_atexit_impl(void (*)(void *), void *, void *); - return __cxa_thread_atexit_impl(dtor, obj, dso_symbol); -} + extern int __cxa_thread_atexit_impl(Dtor, void *, void *) + __attribute__((__weak__)); + + if (__cxa_thread_atexit_impl) { + return __cxa_thread_atexit_impl(dtor, obj, dso_symbol); + } else { + static DtorListHolder dtors; + + auto head = static_cast(std::malloc(sizeof(DtorList))); + if (!head) { + return -1; + } + + head->dtor = dtor; + head->obj = obj; + head->next = dtors.get(); + + if (!dtors.set(head)) { + std::free(head); + return -1; + } -#endif // HAVE__CXA_THREAD_ATEXIT_IMPL + return 0; + } +} } // extern "C" } // namespace __cxxabiv1 Index: test/CMakeLists.txt =================================================================== --- test/CMakeLists.txt +++ test/CMakeLists.txt @@ -16,7 +16,6 @@ pythonize_bool(LIBCXXABI_ENABLE_THREADS) pythonize_bool(LIBCXXABI_ENABLE_EXCEPTIONS) pythonize_bool(LIBCXXABI_USE_LLVM_UNWINDER) -pythonize_bool(LIBCXXABI_HAS_CXA_THREAD_ATEXIT_IMPL) set(LIBCXXABI_TARGET_INFO "libcxx.test.target_info.LocalTI" CACHE STRING "TargetInfo to use when setting up test environment.") set(LIBCXXABI_EXECUTOR "None" CACHE STRING Index: test/cxa_thread_atexit_test.pass.cpp =================================================================== --- test/cxa_thread_atexit_test.pass.cpp +++ test/cxa_thread_atexit_test.pass.cpp @@ -8,7 +8,6 @@ //===----------------------------------------------------------------------===// // REQUIRES: linux -// REQUIRES: thread_atexit #include #include Index: test/libcxxabi/test/config.py =================================================================== --- test/libcxxabi/test/config.py +++ test/libcxxabi/test/config.py @@ -37,8 +37,6 @@ super(Configuration, self).configure_features() if not self.get_lit_bool('enable_exceptions', True): self.config.available_features.add('libcxxabi-no-exceptions') - if self.get_lit_bool('thread_atexit', True): - self.config.available_features.add('thread_atexit') def configure_compile_flags(self): self.cxx.compile_flags += ['-DLIBCXXABI_NO_TIMER'] Index: test/lit.site.cfg.in =================================================================== --- test/lit.site.cfg.in +++ test/lit.site.cfg.in @@ -13,7 +13,6 @@ config.enable_32bit = "@LIBCXXABI_BUILD_32_BITS@" config.target_info = "@LIBCXXABI_TARGET_INFO@" config.executor = "@LIBCXXABI_EXECUTOR@" -config.thread_atexit = "@LIBCXXABI_HAS_CXA_THREAD_ATEXIT_IMPL@" config.libcxxabi_shared = "@LIBCXXABI_ENABLE_SHARED@" config.enable_shared = "@LIBCXX_ENABLE_SHARED@" config.enable_exceptions = "@LIBCXXABI_ENABLE_EXCEPTIONS@"