summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmake/config-ix.cmake2
-rw-r--r--include/cxxabi.h6
-rw-r--r--src/CMakeLists.txt8
-rw-r--r--src/cxa_thread_atexit.cpp28
-rw-r--r--test/cxa_thread_atexit_test.cpp33
-rw-r--r--test/lit.cfg2
6 files changed, 79 insertions, 0 deletions
diff --git a/cmake/config-ix.cmake b/cmake/config-ix.cmake
index cbf5c78..ac31eed 100644
--- a/cmake/config-ix.cmake
+++ b/cmake/config-ix.cmake
@@ -38,3 +38,5 @@ check_library_exists(c printf "" LIBCXXABI_HAS_C_LIB)
check_library_exists(dl dladdr "" LIBCXXABI_HAS_DL_LIB)
check_library_exists(pthread pthread_once "" LIBCXXABI_HAS_PTHREAD_LIB)
check_library_exists(gcc_eh _Unwind_GetRegionStart "" LIBCXXABI_HAS_GCC_EH_LIB)
+check_library_exists(c __cxa_thread_atexit_impl ""
+ LIBCXXABI_HAS_CXA_THREAD_ATEXIT_IMPL)
diff --git a/include/cxxabi.h b/include/cxxabi.h
index 46d6730..e5c9b66 100644
--- a/include/cxxabi.h
+++ b/include/cxxabi.h
@@ -178,6 +178,12 @@ extern void __cxa_decrement_exception_refcount(void* primary_exception) throw();
// Apple addition to support std::uncaught_exception()
extern bool __cxa_uncaught_exception() throw();
+#ifdef __linux__
+// Linux TLS support. Not yet an official part of the Itanium ABI.
+// https://sourceware.org/glibc/wiki/Destructor%20support%20for%20thread_local%20variables
+extern int __cxa_thread_atexit(void (*)(void *), void *, void *) throw();
+#endif
+
} // extern "C"
} // namespace __cxxabiv1
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 08920e2..a623a49 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -19,6 +19,10 @@ set(LIBCXXABI_SOURCES
typeinfo.cpp
)
+if (UNIX AND NOT (APPLE OR CYGWIN))
+ list(APPEND LIBCXXABI_SOURCES cxa_thread_atexit.cpp)
+endif()
+
set(LIBCXXABI_HEADERS ../include/cxxabi.h)
# Add all the headers to the project for IDEs.
@@ -44,6 +48,10 @@ endif()
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})
append_if(libraries LIBCXXABI_HAS_C_LIB c)
diff --git a/src/cxa_thread_atexit.cpp b/src/cxa_thread_atexit.cpp
new file mode 100644
index 0000000..2b4b9fa
--- /dev/null
+++ b/src/cxa_thread_atexit.cpp
@@ -0,0 +1,28 @@
+//===----------------------- cxa_thread_atexit.cpp ------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "cxxabi.h"
+
+namespace __cxxabiv1 {
+
+extern "C" {
+
+#ifdef HAVE___CXA_THREAD_ATEXIT_IMPL
+
+int __cxa_thread_atexit(void (*dtor)(void *), 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);
+}
+
+#endif // HAVE__CXA_THREAD_ATEXIT_IMPL
+
+} // extern "C"
+
+} // namespace __cxxabiv1
diff --git a/test/cxa_thread_atexit_test.cpp b/test/cxa_thread_atexit_test.cpp
new file mode 100644
index 0000000..42f713e
--- /dev/null
+++ b/test/cxa_thread_atexit_test.cpp
@@ -0,0 +1,33 @@
+//===--------------------- cxa_thread_atexit_test.cpp ---------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: linux2
+
+#include <assert.h>
+#include <cxxabi.h>
+
+static bool AtexitImplCalled = false;
+
+extern "C" int __cxa_thread_atexit_impl(void (*dtor)(void *), void *obj,
+ void *dso_symbol) {
+ assert(dtor == reinterpret_cast<void (*)(void *)>(1));
+ assert(obj == reinterpret_cast<void *>(2));
+ assert(dso_symbol == reinterpret_cast<void *>(3));
+ AtexitImplCalled = true;
+ return 4;
+}
+
+int main() {
+ int RV = __cxxabiv1::__cxa_thread_atexit(
+ reinterpret_cast<void (*)(void *)>(1), reinterpret_cast<void *>(2),
+ reinterpret_cast<void *>(3));
+ assert(RV = 4);
+ assert(AtexitImplCalled);
+ return 0;
+}
diff --git a/test/lit.cfg b/test/lit.cfg
index 0ba6e28..1b67817 100644
--- a/test/lit.cfg
+++ b/test/lit.cfg
@@ -283,6 +283,8 @@ elif sys.platform.startswith('linux'):
else:
lit_config.fatal("unrecognized system")
+config.available_features.add(sys.platform)
+
config.test_format = LibcxxabiTestFormat(
cxx_under_test,
cpp_flags = ['-nostdinc++'] + compile_flags + include_paths,