Index: libcxxabi/trunk/CMakeLists.txt =================================================================== --- libcxxabi/trunk/CMakeLists.txt +++ libcxxabi/trunk/CMakeLists.txt @@ -118,6 +118,9 @@ option(LIBCXXABI_USE_COMPILER_RT "Use compiler-rt instead of libgcc" OFF) option(LIBCXXABI_ENABLE_THREADS "Build with threads enabled" ON) option(LIBCXXABI_HAS_PTHREAD_API "Ignore auto-detection and force use of pthread API" OFF) +option(LIBCXXABI_HAS_EXTERNAL_THREAD_API + "Build libc++abi with an externalized threading API. + This option may only be set to ON when LIBCXXABI_ENABLE_THREADS=ON." OFF) option(LIBCXXABI_BUILD_32_BITS "Build 32 bit libc++abi." ${LLVM_BUILD_32_BITS}) set(LIBCXXABI_TARGET_TRIPLE "" CACHE STRING "Target triple for cross compiling.") set(LIBCXXABI_GCC_TOOLCHAIN "" CACHE PATH "GCC toolchain for cross compiling.") @@ -347,20 +350,46 @@ list(APPEND LIBCXXABI_COMPILE_FLAGS -D_LIBCPP_BUILD_STATIC) endif() +# Threading if (NOT LIBCXXABI_ENABLE_THREADS) if (LIBCXXABI_HAS_PTHREAD_API) message(FATAL_ERROR "LIBCXXABI_HAS_PTHREAD_API can only" " be set to ON when LIBCXXABI_ENABLE_THREADS" " is also set to ON.") endif() + if (LIBCXXABI_HAS_EXTERNAL_THREAD_API) + message(FATAL_ERROR "LIBCXXABI_HAS_EXTERNAL_THREAD_API can only" + " be set to ON when LIBCXXABI_ENABLE_THREADS" + " is also set to ON.") + endif() add_definitions(-D_LIBCXXABI_HAS_NO_THREADS) endif() +if (LIBCXXABI_HAS_PTHREAD_API AND LIBCXXABI_HAS_EXTERNAL_THREAD_API) + message(FATAL_ERROR "The options LIBCXXABI_HAS_EXTERNAL_THREAD_API" + "and LIBCXXABI_HAS_PTHREAD_API cannot be both" + "set to ON at the same time.") +endif() + +if (LIBCXXABI_HAS_EXTERNAL_THREAD_API AND LIBCXXABI_ENABLE_SHARED) + # Need to allow unresolved symbols if this is to work with shared library builds + if (APPLE) + add_link_flags("-undefined dynamic_lookup") + else() + # Relax this restriction from HandleLLVMOptions + string(REPLACE "-Wl,-z,defs" "" CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}") + endif() +endif() + if (LIBCXXABI_HAS_PTHREAD_API) add_definitions(-D_LIBCPP_HAS_THREAD_API_PTHREAD) add_definitions(-D_LIBCXXABI_USE_THREAD_API_PTHREAD) endif() +if (LIBCXXABI_HAS_EXTERNAL_THREAD_API) + add_definitions(-D_LIBCXXABI_HAS_THREAD_API_EXTERNAL) +endif() + if (MSVC) add_definitions(-D_CRT_SECURE_NO_WARNINGS) endif() Index: libcxxabi/trunk/src/config.h =================================================================== --- libcxxabi/trunk/src/config.h +++ libcxxabi/trunk/src/config.h @@ -42,6 +42,7 @@ // Try and deduce a threading api if one has not been explicitly set. #if !defined(_LIBCXXABI_HAS_NO_THREADS) && \ + !defined(_LIBCXXABI_HAS_THREAD_API_EXTERNAL) && \ !defined(_LIBCXXABI_USE_THREAD_API_PTHREAD) #if defined(_POSIX_THREADS) && _POSIX_THREADS >= 0 #define _LIBCXXABI_USE_THREAD_API_PTHREAD Index: libcxxabi/trunk/src/cxa_exception.cpp =================================================================== --- libcxxabi/trunk/src/cxa_exception.cpp +++ libcxxabi/trunk/src/cxa_exception.cpp @@ -12,7 +12,6 @@ //===----------------------------------------------------------------------===// #include "config.h" -#include "threading_support.h" #include "cxxabi.h" #include // for std::terminate Index: libcxxabi/trunk/src/cxa_exception_storage.cpp =================================================================== --- libcxxabi/trunk/src/cxa_exception_storage.cpp +++ libcxxabi/trunk/src/cxa_exception_storage.cpp @@ -14,7 +14,7 @@ #include "cxa_exception.hpp" #include "config.h" -#include "threading_support.h" +#include <__threading_support> #if defined(_LIBCXXABI_HAS_NO_THREADS) @@ -54,17 +54,17 @@ namespace __cxxabiv1 { namespace { - __libcxxabi_tls_key key_; - __libcxxabi_exec_once_flag flag_ = _LIBCXXABI_EXEC_ONCE_INITIALIZER; + std::__libcpp_tls_key key_; + std::__libcpp_exec_once_flag flag_ = _LIBCPP_EXEC_ONCE_INITIALIZER; void destruct_ (void *p) { __free_with_fallback ( p ); - if ( 0 != __libcxxabi_tls_set ( key_, NULL ) ) + if ( 0 != std::__libcpp_tls_set ( key_, NULL ) ) abort_message("cannot zero out thread value for __cxa_get_globals()"); } void construct_ () { - if ( 0 != __libcxxabi_tls_create ( &key_, destruct_ ) ) + if ( 0 != std::__libcpp_tls_create ( &key_, destruct_ ) ) abort_message("cannot create thread specific key for __cxa_get_globals()"); } } @@ -80,8 +80,8 @@ (__calloc_with_fallback (1, sizeof (__cxa_eh_globals))); if ( NULL == retVal ) abort_message("cannot allocate __cxa_eh_globals"); - if ( 0 != __libcxxabi_tls_set ( key_, retVal ) ) - abort_message("__libcxxabi_tls_set failure in __cxa_get_globals()"); + if ( 0 != std::__libcpp_tls_set ( key_, retVal ) ) + abort_message("std::__libcpp_tls_set failure in __cxa_get_globals()"); } return retVal; } @@ -92,10 +92,10 @@ // libc++abi. __cxa_eh_globals * __cxa_get_globals_fast () { // First time through, create the key. - if (0 != __libcxxabi_execute_once(&flag_, construct_)) + if (0 != std::__libcpp_execute_once(&flag_, construct_)) abort_message("execute once failure in __cxa_get_globals_fast()"); // static int init = construct_(); - return static_cast<__cxa_eh_globals*>(__libcxxabi_tls_get(key_)); + return static_cast<__cxa_eh_globals*>(std::__libcpp_tls_get(key_)); } } Index: libcxxabi/trunk/src/cxa_guard.cpp =================================================================== --- libcxxabi/trunk/src/cxa_guard.cpp +++ libcxxabi/trunk/src/cxa_guard.cpp @@ -11,7 +11,7 @@ #include "abort_message.h" #include "config.h" -#include "threading_support.h" +#include <__threading_support> #include @@ -20,8 +20,8 @@ which will turn around and try to call __cxa_guard_acquire reentrantly. For this reason, the headers of this file are as restricted as possible. Previous implementations of this code for __APPLE__ have used - __libcxxabi_mutex_lock and the abort_message utility without problem. This - implementation also uses __libcxxabi_condvar_wait which has tested + std::__libcpp_mutex_lock and the abort_message utility without problem. This + implementation also uses std::__libcpp_condvar_wait which has tested to not be a problem. */ @@ -67,8 +67,8 @@ #endif #ifndef _LIBCXXABI_HAS_NO_THREADS -__libcxxabi_mutex_t guard_mut = _LIBCXXABI_MUTEX_INITIALIZER; -__libcxxabi_condvar_t guard_cv = _LIBCXXABI_CONDVAR_INITIALIZER; +std::__libcpp_mutex_t guard_mut = _LIBCPP_MUTEX_INITIALIZER; +std::__libcpp_condvar_t guard_cv = _LIBCPP_CONDVAR_INITIALIZER; #endif #if defined(__APPLE__) && !defined(__arm__) @@ -173,13 +173,13 @@ #ifndef _LIBCXXABI_HAS_NO_THREADS _LIBCXXABI_FUNC_VIS int __cxa_guard_acquire(guard_type *guard_object) { char* initialized = (char*)guard_object; - if (__libcxxabi_mutex_lock(&guard_mut)) + if (std::__libcpp_mutex_lock(&guard_mut)) abort_message("__cxa_guard_acquire failed to acquire mutex"); int result = *initialized == 0; if (result) { #if defined(__APPLE__) && !defined(__arm__) - const lock_type id = __libcxxabi_thread_get_port(); + const lock_type id = std::__libcpp_thread_get_port(); lock_type lock = get_lock(*guard_object); if (lock) { @@ -188,7 +188,7 @@ abort_message("__cxa_guard_acquire detected deadlock"); do { - if (__libcxxabi_condvar_wait(&guard_cv, &guard_mut)) + if (std::__libcpp_condvar_wait(&guard_cv, &guard_mut)) abort_message("__cxa_guard_acquire condition variable wait failed"); lock = get_lock(*guard_object); } while (lock); @@ -200,36 +200,36 @@ set_lock(*guard_object, id); #else // !__APPLE__ || __arm__ while (get_lock(*guard_object)) - if (__libcxxabi_condvar_wait(&guard_cv, &guard_mut)) + if (std::__libcpp_condvar_wait(&guard_cv, &guard_mut)) abort_message("__cxa_guard_acquire condition variable wait failed"); result = *initialized == 0; if (result) set_lock(*guard_object, true); #endif // !__APPLE__ || __arm__ } - if (__libcxxabi_mutex_unlock(&guard_mut)) + if (std::__libcpp_mutex_unlock(&guard_mut)) abort_message("__cxa_guard_acquire failed to release mutex"); return result; } _LIBCXXABI_FUNC_VIS void __cxa_guard_release(guard_type *guard_object) { - if (__libcxxabi_mutex_lock(&guard_mut)) + if (std::__libcpp_mutex_lock(&guard_mut)) abort_message("__cxa_guard_release failed to acquire mutex"); *guard_object = 0; set_initialized(guard_object); - if (__libcxxabi_mutex_unlock(&guard_mut)) + if (std::__libcpp_mutex_unlock(&guard_mut)) abort_message("__cxa_guard_release failed to release mutex"); - if (__libcxxabi_condvar_broadcast(&guard_cv)) + if (std::__libcpp_condvar_broadcast(&guard_cv)) abort_message("__cxa_guard_release failed to broadcast condition variable"); } _LIBCXXABI_FUNC_VIS void __cxa_guard_abort(guard_type *guard_object) { - if (__libcxxabi_mutex_lock(&guard_mut)) + if (std::__libcpp_mutex_lock(&guard_mut)) abort_message("__cxa_guard_abort failed to acquire mutex"); *guard_object = 0; - if (__libcxxabi_mutex_unlock(&guard_mut)) + if (std::__libcpp_mutex_unlock(&guard_mut)) abort_message("__cxa_guard_abort failed to release mutex"); - if (__libcxxabi_condvar_broadcast(&guard_cv)) + if (std::__libcpp_condvar_broadcast(&guard_cv)) abort_message("__cxa_guard_abort failed to broadcast condition variable"); } Index: libcxxabi/trunk/src/cxa_thread_atexit.cpp =================================================================== --- libcxxabi/trunk/src/cxa_thread_atexit.cpp +++ libcxxabi/trunk/src/cxa_thread_atexit.cpp @@ -9,7 +9,7 @@ #include "abort_message.h" #include "cxxabi.h" -#include "threading_support.h" +#include <__threading_support> #include namespace __cxxabiv1 { @@ -39,7 +39,7 @@ // destructors of any objects with static storage duration. // // - thread_local destructors on non-main threads run on the first iteration - // through the __libcxxabi_tls_key destructors. + // through the __libccpp_tls_key destructors. // std::notify_all_at_thread_exit() and similar functions must be careful to // wait until the second iteration to provide their intended ordering // guarantees. @@ -66,7 +66,7 @@ // True if the destructors are currently scheduled to run on this thread __thread bool dtors_alive = false; // Used to trigger destructors on thread exit; value is ignored - __libcxxabi_tls_key dtors_key; + std::__libcpp_tls_key dtors_key; void run_dtors(void*) { while (auto head = dtors) { @@ -80,16 +80,16 @@ struct DtorsManager { DtorsManager() { - // There is intentionally no matching __libcxxabi_tls_delete call, as + // There is intentionally no matching std::__libcpp_tls_delete call, as // __cxa_thread_atexit() may be called arbitrarily late (for example, from // global destructors or atexit() handlers). - if (__libcxxabi_tls_create(&dtors_key, run_dtors) != 0) { - abort_message("__libcxxabi_tls_create() failed in __cxa_thread_atexit()"); + if (std::__libcpp_tls_create(&dtors_key, run_dtors) != 0) { + abort_message("std::__libcpp_tls_create() failed in __cxa_thread_atexit()"); } } ~DtorsManager() { - // __libcxxabi_tls_key destructors do not run on threads that call exit() + // std::__libcpp_tls_key destructors do not run on threads that call exit() // (including when the main thread returns from main()), so we explicitly // call the destructor here. This runs at exit time (potentially earlier // if libc++abi is dlclose()'d). Any thread_locals initialized after this @@ -110,12 +110,12 @@ if (__cxa_thread_atexit_impl) { return __cxa_thread_atexit_impl(dtor, obj, dso_symbol); } else { - // Initialize the dtors __libcxxabi_tls_key (uses __cxa_guard_*() for + // Initialize the dtors std::__libcpp_tls_key (uses __cxa_guard_*() for // one-time initialization and __cxa_atexit() for destruction) static DtorsManager manager; if (!dtors_alive) { - if (__libcxxabi_tls_set(dtors_key, &dtors_key) != 0) { + if (std::__libcpp_tls_set(dtors_key, &dtors_key) != 0) { return -1; } dtors_alive = true; Index: libcxxabi/trunk/src/fallback_malloc.cpp =================================================================== --- libcxxabi/trunk/src/fallback_malloc.cpp +++ libcxxabi/trunk/src/fallback_malloc.cpp @@ -10,7 +10,7 @@ #include "fallback_malloc.h" #include "config.h" -#include "threading_support.h" +#include <__threading_support> #include // for malloc, calloc, free #include // for memset @@ -29,7 +29,8 @@ // When POSIX threads are not available, make the mutex operations a nop #ifndef _LIBCXXABI_HAS_NO_THREADS -static __libcxxabi_mutex_t heap_mutex = _LIBCXXABI_MUTEX_INITIALIZER; +_LIBCPP_SAFE_STATIC +static std::__libcpp_mutex_t heap_mutex = _LIBCPP_MUTEX_INITIALIZER; #else static void * heap_mutex = 0; #endif @@ -37,8 +38,10 @@ class mutexor { public: #ifndef _LIBCXXABI_HAS_NO_THREADS - mutexor ( __libcxxabi_mutex_t *m ) : mtx_(m) { __libcxxabi_mutex_lock ( mtx_ ); } - ~mutexor () { __libcxxabi_mutex_unlock ( mtx_ ); } + mutexor ( std::__libcpp_mutex_t *m ) : mtx_(m) { + std::__libcpp_mutex_lock ( mtx_ ); + } + ~mutexor () { std::__libcpp_mutex_unlock ( mtx_ ); } #else mutexor ( void * ) {} ~mutexor () {} @@ -47,9 +50,9 @@ mutexor ( const mutexor &rhs ); mutexor & operator = ( const mutexor &rhs ); #ifndef _LIBCXXABI_HAS_NO_THREADS - __libcxxabi_mutex_t *mtx_; + std::__libcpp_mutex_t *mtx_; #endif - }; +}; static const size_t HEAP_SIZE = 512; Index: libcxxabi/trunk/src/threading_support.h =================================================================== --- libcxxabi/trunk/src/threading_support.h +++ libcxxabi/trunk/src/threading_support.h @@ -1,107 +0,0 @@ -//===------------------------ threading_support.h -------------------------===// -// -// 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. -// -//===----------------------------------------------------------------------===// - -#ifndef _LIBCXXABI_THREADING_SUPPORT_H -#define _LIBCXXABI_THREADING_SUPPORT_H - -#include "__cxxabi_config.h" -#include "config.h" - -#ifndef _LIBCXXABI_HAS_NO_THREADS - -#if defined(_LIBCXXABI_USE_THREAD_API_PTHREAD) -#include - -#define _LIBCXXABI_THREAD_ABI_VISIBILITY inline _LIBCXXABI_INLINE_VISIBILITY - -// Mutex -typedef pthread_mutex_t __libcxxabi_mutex_t; -#define _LIBCXXABI_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER - -_LIBCXXABI_THREAD_ABI_VISIBILITY -int __libcxxabi_mutex_lock(__libcxxabi_mutex_t *mutex) { - return pthread_mutex_lock(mutex); -} - -_LIBCXXABI_THREAD_ABI_VISIBILITY -int __libcxxabi_mutex_unlock(__libcxxabi_mutex_t *mutex) { - return pthread_mutex_unlock(mutex); -} - -// Condition variable -typedef pthread_cond_t __libcxxabi_condvar_t; -#define _LIBCXXABI_CONDVAR_INITIALIZER PTHREAD_COND_INITIALIZER - -_LIBCXXABI_THREAD_ABI_VISIBILITY -int __libcxxabi_condvar_wait(__libcxxabi_condvar_t *cv, - __libcxxabi_mutex_t *mutex) { - return pthread_cond_wait(cv, mutex); -} - -_LIBCXXABI_THREAD_ABI_VISIBILITY -int __libcxxabi_condvar_broadcast(__libcxxabi_condvar_t *cv) { - return pthread_cond_broadcast(cv); -} - -// Execute once -typedef pthread_once_t __libcxxabi_exec_once_flag; -#define _LIBCXXABI_EXEC_ONCE_INITIALIZER PTHREAD_ONCE_INIT - -_LIBCXXABI_THREAD_ABI_VISIBILITY -int __libcxxabi_execute_once(__libcxxabi_exec_once_flag *flag, - void (*init_routine)(void)) { - return pthread_once(flag, init_routine); -} - -// Thread id -#if defined(__APPLE__) && !defined(__arm__) -_LIBCXXABI_THREAD_ABI_VISIBILITY -mach_port_t __libcxxabi_thread_get_port() -{ - return pthread_mach_thread_np(pthread_self()); -} -#endif - -// Thread -typedef pthread_t __libcxxabi_thread_t; - -_LIBCXXABI_THREAD_ABI_VISIBILITY -int __libcxxabi_thread_create(__libcxxabi_thread_t* __t, - void* (*__func)(void*), void* __arg) -{ - return pthread_create(__t, 0, __func, __arg); -} - -_LIBCXXABI_THREAD_ABI_VISIBILITY -int __libcxxabi_thread_join(__libcxxabi_thread_t* __t) -{ - return pthread_join(*__t, 0); -} - -// TLS -typedef pthread_key_t __libcxxabi_tls_key; - -_LIBCXXABI_THREAD_ABI_VISIBILITY -int __libcxxabi_tls_create(__libcxxabi_tls_key *key, - void (*destructor)(void *)) { - return pthread_key_create(key, destructor); -} - -_LIBCXXABI_THREAD_ABI_VISIBILITY -void *__libcxxabi_tls_get(__libcxxabi_tls_key key) { - return pthread_getspecific(key); -} - -_LIBCXXABI_THREAD_ABI_VISIBILITY -int __libcxxabi_tls_set(__libcxxabi_tls_key key, void *value) { - return pthread_setspecific(key, value); -} -#endif // _LIBCXXABI_USE_THREAD_API_PTHREAD -#endif // !_LIBCXXABI_HAS_NO_THREADS -#endif // _LIBCXXABI_THREADING_SUPPORT_H Index: libcxxabi/trunk/test/CMakeLists.txt =================================================================== --- libcxxabi/trunk/test/CMakeLists.txt +++ libcxxabi/trunk/test/CMakeLists.txt @@ -17,6 +17,7 @@ pythonize_bool(LIBCXXABI_ENABLE_THREADS) pythonize_bool(LIBCXXABI_ENABLE_EXCEPTIONS) pythonize_bool(LIBCXXABI_USE_LLVM_UNWINDER) +pythonize_bool(LIBCXXABI_HAS_EXTERNAL_THREAD_API) 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 @@ -34,6 +35,10 @@ set(LIBCXXABI_TEST_DEPS cxxabi_static) endif() +if (LIBCXXABI_HAS_EXTERNAL_THREAD_API) + list(APPEND LIBCXXABI_TEST_DEPS cxx_external_threads) +endif() + if (NOT LIBCXXABI_STANDALONE_BUILD) list(APPEND LIBCXXABI_TEST_DEPS cxx) if (LIBCXXABI_USE_LLVM_UNWINDER) Index: libcxxabi/trunk/test/libcxxabi/test/config.py =================================================================== --- libcxxabi/trunk/test/libcxxabi/test/config.py +++ libcxxabi/trunk/test/libcxxabi/test/config.py @@ -42,6 +42,9 @@ self.config.available_features.add('libcxxabi-no-exceptions') if not self.has_cpp_feature('noexcept_function_type', 201510): self.config.available_features.add('libcxxabi-no-noexcept-function-type') + # test_exception_storage_nodynmem.pass.cpp fails under this specific configuration + if self.get_lit_bool('cxx_ext_threads', False) and self.get_lit_bool('libcxxabi_shared', False): + self.config.available_features.add('libcxxabi-shared-externally-threaded') def configure_compile_flags(self): self.cxx.compile_flags += ['-DLIBCXXABI_NO_TIMER'] Index: libcxxabi/trunk/test/lit.site.cfg.in =================================================================== --- libcxxabi/trunk/test/lit.site.cfg.in +++ libcxxabi/trunk/test/lit.site.cfg.in @@ -19,6 +19,7 @@ config.host_triple = "@LLVM_HOST_TRIPLE@" config.target_triple = "@TARGET_TRIPLE@" config.use_target = len("@LIBCXXABI_TARGET_TRIPLE@") > 0 +config.cxx_ext_threads = "@LIBCXXABI_HAS_EXTERNAL_THREAD_API@" # Let the main config do the real work. lit_config.load_config(config, "@LIBCXXABI_SOURCE_DIR@/test/lit.cfg") Index: libcxxabi/trunk/test/test_exception_storage.pass.cpp =================================================================== --- libcxxabi/trunk/test/test_exception_storage.pass.cpp +++ libcxxabi/trunk/test/test_exception_storage.pass.cpp @@ -12,7 +12,7 @@ #include #include #include -#include "../src/threading_support.h" +#include <__threading_support> #include #include "../src/cxa_exception.hpp" @@ -39,7 +39,7 @@ #ifndef _LIBCXXABI_HAS_NO_THREADS #define NUMTHREADS 10 size_t thread_globals [ NUMTHREADS ] = { 0 }; -__libcxxabi_thread_t threads [ NUMTHREADS ]; +std::__libcpp_thread_t threads [ NUMTHREADS ]; #endif int main () { @@ -48,9 +48,9 @@ #ifndef _LIBCXXABI_HAS_NO_THREADS // Make the threads, let them run, and wait for them to finish for ( int i = 0; i < NUMTHREADS; ++i ) - __libcxxabi_thread_create ( threads + i, thread_code, (void *) (thread_globals + i)); + std::__libcpp_thread_create ( threads + i, thread_code, (void *) (thread_globals + i)); for ( int i = 0; i < NUMTHREADS; ++i ) - __libcxxabi_thread_join ( &threads [ i ] ); + std::__libcpp_thread_join ( &threads [ i ] ); for ( int i = 0; i < NUMTHREADS; ++i ) if ( 0 == thread_globals [ i ] ) { Index: libcxxabi/trunk/test/test_fallback_malloc.pass.cpp =================================================================== --- libcxxabi/trunk/test/test_fallback_malloc.pass.cpp +++ libcxxabi/trunk/test/test_fallback_malloc.pass.cpp @@ -10,7 +10,7 @@ #include #include -#include "../src/threading_support.h" +#include <__threading_support> typedef std::deque container;