Index: CMakeLists.txt =================================================================== --- CMakeLists.txt +++ CMakeLists.txt @@ -118,6 +118,12 @@ 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(LIBCXX_HAS_EXTERNAL_THREAD_API + "Build libc++ with an externalized threading API. + This option may only be set to ON when LIBCXX_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 +353,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: src/CMakeLists.txt =================================================================== --- src/CMakeLists.txt +++ src/CMakeLists.txt @@ -128,6 +128,23 @@ list(APPEND LIBCXXABI_TARGETS "cxxabi_shared") endif() +if (LIBCXXABI_HAS_EXTERNAL_THREAD_API) + file(GLOB LIBCXXABI_EXTERNAL_THREADING_SUPPORT_SOURCES ../test/support/external_threads.cpp) + + if (LIBCXXABI_ENABLE_SHARED) + add_library(cxxabi_external_threads SHARED ${LIBCXXABI_EXTERNAL_THREADING_SUPPORT_SOURCES}) + else() + add_library(cxxabi_external_threads STATIC ${LIBCXXABI_EXTERNAL_THREADING_SUPPORT_SOURCES}) + endif() + + set_target_properties(cxxabi_external_threads + PROPERTIES + LINK_FLAGS "${LIBCXXABI_LINK_FLAGS}" + COMPILE_FLAGS "${LIBCXXABI_COMPILE_FLAGS}" + OUTPUT_NAME "cxxabi_external_threads" + ) +endif() + # Build the static library. if (LIBCXXABI_ENABLE_STATIC) add_library(cxxabi_static STATIC $) Index: src/config.h =================================================================== --- src/config.h +++ 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: src/threading_support.h =================================================================== --- src/threading_support.h +++ src/threading_support.h @@ -15,45 +15,110 @@ #ifndef _LIBCXXABI_HAS_NO_THREADS -#if defined(_LIBCXXABI_USE_THREAD_API_PTHREAD) +#ifndef __libcxxabi_has_include + #ifndef __has_include + #define __libcxxabi_has_include(x) 0 + #else + #define __libcxxabi_has_include(x) __has_include(x) + #endif +#endif + +#if defined(_LIBCXXABI_HAS_THREAD_API_EXTERNAL) && \ + __libcxxabi_has_include() +#include +#else #include +#if defined(_LIBCXXABI_HAS_THREAD_API_EXTERNAL) +#define _LIBCXXABI_THREAD_ABI_VISIBILITY _LIBCXXABI_FUNC_VIS +#else #define _LIBCXXABI_THREAD_ABI_VISIBILITY inline _LIBCXXABI_INLINE_VISIBILITY +#endif // 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); + +_LIBCXXABI_THREAD_ABI_VISIBILITY +int __libcxxabi_mutex_unlock(__libcxxabi_mutex_t *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); + +_LIBCXXABI_THREAD_ABI_VISIBILITY +int __libcxxabi_condvar_broadcast(__libcxxabi_condvar_t *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)); + +// Thread id +#if defined(__APPLE__) && !defined(__arm__) +_LIBCXXABI_THREAD_ABI_VISIBILITY +mach_port_t __libcxxabi_thread_get_port(); +#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); + +_LIBCXXABI_THREAD_ABI_VISIBILITY +int __libcxxabi_thread_join(__libcxxabi_thread_t* __t); + +// TLS +typedef pthread_key_t __libcxxabi_tls_key; + +_LIBCXXABI_THREAD_ABI_VISIBILITY +int __libcxxabi_tls_create(__libcxxabi_tls_key *key, + void (*destructor)(void *)); + +_LIBCXXABI_THREAD_ABI_VISIBILITY +void *__libcxxabi_tls_get(__libcxxabi_tls_key key); + +_LIBCXXABI_THREAD_ABI_VISIBILITY +int __libcxxabi_tls_set(__libcxxabi_tls_key key, void *value); + +// Implementation of the above thread API. Used both by the pthread based +// libc++abi build and the proof-of-concept externally threaded (i.e. no +// external_threading.h header) libc++abi build (below implementation built +// into a separate library for linking against the test suite). +#if defined(_LIBCXXABI_USE_THREAD_API_PTHREAD) || \ + defined(_LIBCXXABI_BUILDING_EXTERNAL_THREADS) +// Mutex 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); @@ -61,47 +126,38 @@ // Thread id #if defined(__APPLE__) && !defined(__arm__) -_LIBCXXABI_THREAD_ABI_VISIBILITY -mach_port_t __libcxxabi_thread_get_port() -{ +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) -{ + void* (*__func)(void*), void* __arg) { return pthread_create(__t, 0, __func, __arg); } -_LIBCXXABI_THREAD_ABI_VISIBILITY -int __libcxxabi_thread_join(__libcxxabi_thread_t* __t) -{ +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_THREAD_API_EXTERNAL || !__libcxxabi_has_include() + #endif // !_LIBCXXABI_HAS_NO_THREADS + #endif // _LIBCXXABI_THREADING_SUPPORT_H Index: test/CMakeLists.txt =================================================================== --- test/CMakeLists.txt +++ test/CMakeLists.txt @@ -17,6 +17,9 @@ pythonize_bool(LIBCXXABI_ENABLE_THREADS) pythonize_bool(LIBCXXABI_ENABLE_EXCEPTIONS) pythonize_bool(LIBCXXABI_USE_LLVM_UNWINDER) +pythonize_bool(LIBCXXABI_HAS_CXA_THREAD_ATEXIT_IMPL) +pythonize_bool(LIBCXX_HAS_EXTERNAL_THREAD_API) +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 +37,14 @@ set(LIBCXXABI_TEST_DEPS cxxabi_static) endif() +if (LIBCXXABI_HAS_EXTERNAL_THREAD_API) + list(APPEND LIBCXXABI_TEST_DEPS "cxxabi_external_threads") +endif() + +if (LIBCXX_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: test/libcxxabi/test/config.py =================================================================== --- test/libcxxabi/test/config.py +++ test/libcxxabi/test/config.py @@ -39,6 +39,9 @@ self.config.available_features.add('libcxxabi-no-exceptions') if not self.cxx.addCompileFlagIfSupported(['-Xclang', '-mqualified-function-type-info']): self.config.available_features.add("libcxxabi-no-qualified-function-types") + # test_exception_storage_nodynmem.pass.cpp fails under this specific configuration + if self.get_lit_bool('cxxabi_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: test/lit.cfg =================================================================== --- test/lit.cfg +++ test/lit.cfg @@ -18,7 +18,7 @@ config.name = 'libc++abi' # suffixes: A list of file extensions to treat as test files. -config.suffixes = ['.cpp', '.s'] +config.suffixes = ['.pass.cpp', '.sh.s', '.sh.cpp'] # test_source_root: The root path where tests are located. config.test_source_root = os.path.dirname(__file__) Index: test/lit.site.cfg.in =================================================================== --- test/lit.site.cfg.in +++ test/lit.site.cfg.in @@ -19,6 +19,8 @@ config.host_triple = "@LLVM_HOST_TRIPLE@" config.target_triple = "@TARGET_TRIPLE@" config.use_target = len("@LIBCXXABI_TARGET_TRIPLE@") > 0 +config.cxx_ext_threads = "@LIBCXX_HAS_EXTERNAL_THREAD_API@" +config.cxxabi_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: test/support/external_threads.cpp =================================================================== --- /dev/null +++ test/support/external_threads.cpp @@ -0,0 +1,10 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// +#define _LIBCXXABI_BUILDING_EXTERNAL_THREADS +#include