Index: CMakeLists.txt =================================================================== --- CMakeLists.txt +++ CMakeLists.txt @@ -273,6 +273,10 @@ if (NOT LIBCXXABI_ENABLE_THREADS) add_definitions(-DLIBCXXABI_HAS_NO_THREADS=1) +else () + # TODO: this should be defined for all targets when using the POSIX threading + # model by the driver as on NetBSD + add_definitions(-D_POSIX_THREADS) endif() # This is the _ONLY_ place where add_definitions is called. Index: include/__cxxabi_config.h =================================================================== --- include/__cxxabi_config.h +++ include/__cxxabi_config.h @@ -41,4 +41,17 @@ #endif #endif +#define _LIBCXXABI_STRINGIFY_EXPANDED(_value_) #_value_ +#define _LIBCXXABI_STRINGIFY(_value_) _LIBCXXABI_STRINGIFY_EXPANDED(_value_) + +#if defined(__GNUC__) || defined(__clang__) +#define _LIBCXXABI_PRAGMA(_parameter_) _Pragma(#_parameter_) +#define _LIBCXXABI_WARNING(_message_) _LIBCXXABI_PRAGMA(GCC warning _message_) +#elif defined(_MSC_VER) +#define _LIBCXXABI_WARNING(_message_) \ + __pragma(message(__FILE__ "(" _LIBCXXABI_STRINGIFY(__LINE__) "): warning: " _message_)) +#else +#define _LIBCXXABI_WARNING(_message_) +#endif + #endif // ____CXXABI_CONFIG_H Index: src/__cxa_thread.h =================================================================== --- /dev/null +++ src/__cxa_thread.h @@ -0,0 +1,90 @@ +//===---------------------------- cxa_thread.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 ____CXA_THREAD_H +#define ____CXA_THREAD_H + +#include "__cxxabi_config.h" + +#if defined(LIBCXXABI_HAS_NO_THREADS) && LIBCXXABI_HAS_NO_THREADS == 1 + +#else + +#if defined(_WIN32) + +_LIBCXXABI_WARNING("unsupported threading model"); + +#elif defined(_POSIX_THREADS) + +#include + +typedef pthread_cond_t __cxxabi_condition_variable; +typedef pthread_once_t __cxxabi_execute_once_control; +typedef pthread_mutex_t __cxxabi_mutex; +typedef pthread_key_t __cxxabi_thread_storage_key; + +constexpr __cxxabi_condition_variable __CXXABI_CONDITION_VARIABLE_INITIALIZER = + PTHREAD_COND_INITIALIZER; +constexpr __cxxabi_execute_once_control __CXXABI_EXECUTE_ONCE_INITIALIZER = + PTHREAD_ONCE_INIT; +constexpr __cxxabi_mutex __CXXABI_MUTEX_INITIALIZER = PTHREAD_MUTEX_INITIALIZER; + +inline int __attribute__((__always_inline__)) +__cxxabi_condition_variable_wait(__cxxabi_condition_variable *cv, + __cxxabi_mutex *mutex) { + return pthread_cond_wait(cv, mutex); +} + +inline int __attribute__((__always_inline__)) +__cxxabi_condition_variable_wake_all(__cxxabi_condition_variable *cv) { + return pthread_cond_broadcast(cv); +} + +inline int __attribute__((__always_inline__)) +__cxxabi_execute_once(__cxxabi_execute_once_control *flag, + void (*init_routine)(void)) { + return pthread_once(flag, init_routine); +} + +inline int __attribute__((__always_inline__)) +__cxxabi_mutex_lock(__cxxabi_mutex *mutex) { + return pthread_mutex_lock(mutex); +} + +inline int __attribute__((__always_inline__)) +__cxxabi_mutex_unlock(__cxxabi_mutex *mutex) { + return pthread_mutex_unlock(mutex); +} + +inline int __attribute__((__always_inline__)) +__cxxabi_thread_specific_key_init(__cxxabi_thread_storage_key *key, + void (*destructor)(void *)) { + return pthread_key_create(key, destructor); +} + +inline void *__attribute__((__always_inline__)) +__cxxabi_get_thread_specific(__cxxabi_thread_storage_key key) { + return pthread_getspecific(key); +} + +inline int __attribute__((__always_inline__)) +__cxxabi_set_thread_specific(__cxxabi_thread_storage_key key, void *value) { + return pthread_setspecific(key, value); +} + +#else + +_LIBCXXABI_WARNING("unknown threading model"); + +#endif + +#endif + +#endif + Index: src/cxa_exception.cpp =================================================================== --- src/cxa_exception.cpp +++ src/cxa_exception.cpp @@ -13,13 +13,11 @@ #include "config.h" #include "cxxabi.h" +#include "__cxa_thread.h" #include // for std::terminate #include // for malloc, free #include // for memset -#if !LIBCXXABI_HAS_NO_THREADS -# include // for fallback_malloc.ipp's mutexes -#endif #include "cxa_exception.hpp" #include "cxa_handlers.hpp" Index: src/cxa_exception_storage.cpp =================================================================== --- src/cxa_exception_storage.cpp +++ src/cxa_exception_storage.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "cxa_exception.hpp" +#include "__cxa_thread.h" #include "config.h" @@ -44,7 +45,6 @@ #else -#include #include // for calloc, free #include "abort_message.h" @@ -54,18 +54,18 @@ namespace __cxxabiv1 { namespace { - pthread_key_t key_; - pthread_once_t flag_ = PTHREAD_ONCE_INIT; + __cxxabi_thread_storage_key key_; + __cxxabi_execute_once_control flag_ = __CXXABI_EXECUTE_ONCE_INITIALIZER; void destruct_ (void *p) { std::free ( p ); - if ( 0 != ::pthread_setspecific ( key_, NULL ) ) + if ( 0 != __cxxabi_set_thread_specific ( key_, NULL ) ) abort_message("cannot zero out thread value for __cxa_get_globals()"); } void construct_ () { - if ( 0 != pthread_key_create ( &key_, destruct_ ) ) - abort_message("cannot create pthread key for __cxa_get_globals()"); + if ( 0 != __cxxabi_thread_specific_key_init ( &key_, destruct_ ) ) + abort_message("cannot create thread specific key for __cxa_get_globals()"); } } @@ -80,8 +80,8 @@ (std::calloc (1, sizeof (__cxa_eh_globals))); if ( NULL == retVal ) abort_message("cannot allocate __cxa_eh_globals"); - if ( 0 != pthread_setspecific ( key_, retVal ) ) - abort_message("pthread_setspecific failure in __cxa_get_globals()"); + if ( 0 != __cxxabi_set_thread_specific ( key_, retVal ) ) + abort_message("__cxxabi_set_thread_specific 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 != pthread_once(&flag_, construct_)) - abort_message("pthread_once failure in __cxa_get_globals_fast()"); + if (0 != __cxxabi_execute_once(&flag_, construct_)) + abort_message("execute once failure in __cxa_get_globals_fast()"); // static int init = construct_(); - return static_cast<__cxa_eh_globals*>(::pthread_getspecific(key_)); + return static_cast<__cxa_eh_globals*>(__cxxabi_get_thread_specific(key_)); } } Index: src/cxa_guard.cpp =================================================================== --- src/cxa_guard.cpp +++ src/cxa_guard.cpp @@ -8,23 +8,21 @@ //===----------------------------------------------------------------------===// #include "__cxxabi_config.h" +#include "__cxa_thread.h" #include "abort_message.h" #include "config.h" -#if !LIBCXXABI_HAS_NO_THREADS -# include -#endif #include /* This implementation must be careful to not call code external to this file - which will turn around and try to call __cxa_guard_acquire reentrantly. + which will turn around and try to call __cxxabi_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 - pthread_mutex_lock and the abort_message utility without problem. This - implementation also uses pthread_cond_wait which has tested to not be a - problem. + __cxxabi_mutex_lock and the abort_message utility without problem. This + implementation also uses __cxxabi_condition_variable_wait which has tested + to not be a problem. */ namespace __cxxabiv1 @@ -65,8 +63,8 @@ #endif #if !LIBCXXABI_HAS_NO_THREADS -pthread_mutex_t guard_mut = PTHREAD_MUTEX_INITIALIZER; -pthread_cond_t guard_cv = PTHREAD_COND_INITIALIZER; +__cxxabi_mutex guard_mut = __CXXABI_MUTEX_INITIALIZER; +__cxxabi_condition_variable guard_cv = __CXXABI_CONDITION_VARIABLE_INITIALIZER; #endif #if defined(__APPLE__) && !defined(__arm__) @@ -186,7 +184,7 @@ _LIBCXXABI_FUNC_VIS int __cxa_guard_acquire(guard_type *guard_object) { char* initialized = (char*)guard_object; - if (pthread_mutex_lock(&guard_mut)) + if (__cxxabi_mutex_lock(&guard_mut)) abort_message("__cxa_guard_acquire failed to acquire mutex"); int result = *initialized == 0; if (result) @@ -201,7 +199,7 @@ abort_message("__cxa_guard_acquire detected deadlock"); do { - if (pthread_cond_wait(&guard_cv, &guard_mut)) + if (__cxxabi_condition_variable_wait(&guard_cv, &guard_mut)) abort_message("__cxa_guard_acquire condition variable wait failed"); lock = get_lock(*guard_object); } while (lock); @@ -213,36 +211,36 @@ set_lock(*guard_object, id); #else // !__APPLE__ || __arm__ while (get_lock(*guard_object)) - if (pthread_cond_wait(&guard_cv, &guard_mut)) + if (__cxxabi_condition_variable_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 (pthread_mutex_unlock(&guard_mut)) + if (__cxxabi_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 (pthread_mutex_lock(&guard_mut)) + if (__cxxabi_mutex_lock(&guard_mut)) abort_message("__cxa_guard_release failed to acquire mutex"); *guard_object = 0; set_initialized(guard_object); - if (pthread_mutex_unlock(&guard_mut)) + if (__cxxabi_mutex_unlock(&guard_mut)) abort_message("__cxa_guard_release failed to release mutex"); - if (pthread_cond_broadcast(&guard_cv)) + if (__cxxabi_condition_variable_wake_all(&guard_cv)) abort_message("__cxa_guard_release failed to broadcast condition variable"); } _LIBCXXABI_FUNC_VIS void __cxa_guard_abort(guard_type *guard_object) { - if (pthread_mutex_lock(&guard_mut)) + if (__cxxabi_mutex_lock(&guard_mut)) abort_message("__cxa_guard_abort failed to acquire mutex"); *guard_object = 0; - if (pthread_mutex_unlock(&guard_mut)) + if (__cxxabi_mutex_unlock(&guard_mut)) abort_message("__cxa_guard_abort failed to release mutex"); - if (pthread_cond_broadcast(&guard_cv)) + if (__cxxabi_condition_variable_wake_all(&guard_cv)) abort_message("__cxa_guard_abort failed to broadcast condition variable"); } Index: src/fallback_malloc.ipp =================================================================== --- src/fallback_malloc.ipp +++ src/fallback_malloc.ipp @@ -29,7 +29,7 @@ #if LIBCXXABI_HAS_NO_THREADS static void * heap_mutex = 0; #else -static pthread_mutex_t heap_mutex = PTHREAD_MUTEX_INITIALIZER; +static __cxxabi_mutex heap_mutex = __CXXABI_MUTEX_INITIALIZER; #endif class mutexor { @@ -38,14 +38,14 @@ mutexor ( void * ) {} ~mutexor () {} #else - mutexor ( pthread_mutex_t *m ) : mtx_(m) { pthread_mutex_lock ( mtx_ ); } - ~mutexor () { pthread_mutex_unlock ( mtx_ ); } + mutexor ( __cxxabi_mutex *m ) : mtx_(m) { __cxxabi_mutex_lock ( mtx_ ); } + ~mutexor () { __cxxabi_mutex_unlock ( mtx_ ); } #endif private: mutexor ( const mutexor &rhs ); mutexor & operator = ( const mutexor &rhs ); #if !LIBCXXABI_HAS_NO_THREADS - pthread_mutex_t *mtx_; + __cxxabi_mutex *mtx_; #endif }; Index: test/test_fallback_malloc.pass.cpp =================================================================== --- test/test_fallback_malloc.pass.cpp +++ test/test_fallback_malloc.pass.cpp @@ -10,7 +10,8 @@ #include #include -#include +#define _POSIX_THREADS +#include "../src/__cxa_thread.h" typedef std::deque container;