[libcxxabi] Add __cxa_thread_atexit for TLS support on Linux.

Summary:
Fixes PR21738.

The implementation for this is handled by __cxa_thread_atexit_impl,
which is supplied by libc.

More information:
https://sourceware.org/glibc/wiki/Destructor%20support%20for%20thread_local%20variables

Reviewers: mclow.lists, EricWF, jroelofs

Reviewed By: jroelofs

Subscribers: majnemer, cfe-commits

Differential Revision: http://reviews.llvm.org/D6708

llvm-svn: 224477
This commit is contained in:
Dan Albert 2014-12-18 00:03:57 +00:00
parent 8e015ff43b
commit 12c0c8b67f
6 changed files with 79 additions and 0 deletions

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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;
}

View File

@ -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,