summaryrefslogtreecommitdiffstats
path: root/libcxxabi
diff options
context:
space:
mode:
authorAsiri Rathnayake <asiri.rathnayake@arm.com>2016-10-13 15:05:19 +0000
committerAsiri Rathnayake <asiri.rathnayake@arm.com>2016-10-13 15:05:19 +0000
commit6d3ea6831d6fe30683d6b5078ad826fdedc2e946 (patch)
tree92f3fb6daa13e34459ba54f27f5bad8da3099793 /libcxxabi
parent85874a9360334ddb9619aca6344b8ee53296fa1e (diff)
downloadbcm5719-llvm-6d3ea6831d6fe30683d6b5078ad826fdedc2e946.tar.gz
bcm5719-llvm-6d3ea6831d6fe30683d6b5078ad826fdedc2e946.zip
[libcxxabi] Refactor pthread usage into a separate API
This patch refactors all pthread uses of libc++abi into a separate API. This is the first step towards supporting an externlly-threaded libc++abi library. I've followed the conventions already used in the libc++ library for the same purpose. Patch from: Saleem Abdulrasool and Asiri Rathnayake Reviewed by: compnerd, EricWF Differential revisions: https://reviews.llvm.org/D18482 (original) https://reviews.llvm.org/D24864 (final) llvm-svn: 284128
Diffstat (limited to 'libcxxabi')
-rw-r--r--libcxxabi/CMakeLists.txt1
-rw-r--r--libcxxabi/src/config.h30
-rw-r--r--libcxxabi/src/cxa_exception.cpp1
-rw-r--r--libcxxabi/src/cxa_exception_storage.cpp24
-rw-r--r--libcxxabi/src/cxa_guard.cpp36
-rw-r--r--libcxxabi/src/cxa_thread_atexit.cpp25
-rw-r--r--libcxxabi/src/fallback_malloc.cpp13
-rw-r--r--libcxxabi/src/threading_support.h107
-rw-r--r--libcxxabi/test/test_exception_storage.pass.cpp12
-rw-r--r--libcxxabi/test/test_fallback_malloc.pass.cpp2
10 files changed, 192 insertions, 59 deletions
diff --git a/libcxxabi/CMakeLists.txt b/libcxxabi/CMakeLists.txt
index e75c0b81bb4..73ec5c55750 100644
--- a/libcxxabi/CMakeLists.txt
+++ b/libcxxabi/CMakeLists.txt
@@ -340,6 +340,7 @@ endif()
if (LIBCXXABI_HAS_PTHREAD_API)
add_definitions(-D_LIBCPP_HAS_THREAD_API_PTHREAD)
+ add_definitions(-D_LIBCXXABI_USE_THREAD_API_PTHREAD)
endif()
if (MSVC)
diff --git a/libcxxabi/src/config.h b/libcxxabi/src/config.h
index 5d38d4d1465..d30c49b57ea 100644
--- a/libcxxabi/src/config.h
+++ b/libcxxabi/src/config.h
@@ -16,6 +16,36 @@
#include <unistd.h>
+// Configure inline visibility attributes
+#if defined(_WIN32)
+ #if defined(_MSC_VER) && !defined(__clang__)
+ // Using Microsoft Visual C++ compiler
+ #define _LIBCXXABI_INLINE_VISIBILITY __forceinline
+ #else
+ #if __has_attribute(__internal_linkage__)
+ #define _LIBCXXABI_INLINE_VISIBILITY __attribute__ ((__internal_linkage__, __always_inline__))
+ #else
+ #define _LIBCXXABI_INLINE_VISIBILITY __attribute__ ((__always_inline__))
+ #endif
+ #endif
+#else
+ #if __has_attribute(__internal_linkage__)
+ #define _LIBCXXABI_INLINE_VISIBILITY __attribute__ ((__internal_linkage__, __always_inline__))
+ #else
+ #define _LIBCXXABI_INLINE_VISIBILITY __attribute__ ((__visibility__("hidden"), __always_inline__))
+ #endif
+#endif
+
+// Try and deduce a threading api if one has not been explicitly set.
+#if !defined(_LIBCXXABI_HAS_NO_THREADS) && \
+ !defined(_LIBCXXABI_USE_THREAD_API_PTHREAD)
+ #if defined(_POSIX_THREADS) && _POSIX_THREADS >= 0
+ #define _LIBCXXABI_USE_THREAD_API_PTHREAD
+ #else
+ #error "No thread API"
+ #endif
+#endif
+
// Set this in the CXXFLAGS when you need it, because otherwise we'd have to
// #if !defined(__linux__) && !defined(__APPLE__) && ...
// and so-on for *every* platform.
diff --git a/libcxxabi/src/cxa_exception.cpp b/libcxxabi/src/cxa_exception.cpp
index 757b3d4558c..f84c0e84065 100644
--- a/libcxxabi/src/cxa_exception.cpp
+++ b/libcxxabi/src/cxa_exception.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "config.h"
+#include "threading_support.h"
#include "cxxabi.h"
#include <exception> // for std::terminate
diff --git a/libcxxabi/src/cxa_exception_storage.cpp b/libcxxabi/src/cxa_exception_storage.cpp
index ec69094c40c..d18eb0f84c2 100644
--- a/libcxxabi/src/cxa_exception_storage.cpp
+++ b/libcxxabi/src/cxa_exception_storage.cpp
@@ -14,6 +14,7 @@
#include "cxa_exception.hpp"
#include "config.h"
+#include "threading_support.h"
#if defined(_LIBCXXABI_HAS_NO_THREADS)
@@ -44,28 +45,27 @@ extern "C" {
#else
-#include <pthread.h>
#include "abort_message.h"
#include "fallback_malloc.h"
-// In general, we treat all pthread errors as fatal.
+// In general, we treat all threading errors as fatal.
// We cannot call std::terminate() because that will in turn
// call __cxa_get_globals() and cause infinite recursion.
namespace __cxxabiv1 {
namespace {
- pthread_key_t key_;
- pthread_once_t flag_ = PTHREAD_ONCE_INIT;
+ __libcxxabi_tls_key key_;
+ __libcxxabi_exec_once_flag flag_ = _LIBCXXABI_EXEC_ONCE_INITIALIZER;
void destruct_ (void *p) {
__free_with_fallback ( p );
- if ( 0 != ::pthread_setspecific ( key_, NULL ) )
+ if ( 0 != __libcxxabi_tls_set ( 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 != __libcxxabi_tls_create ( &key_, destruct_ ) )
+ abort_message("cannot create thread specific key for __cxa_get_globals()");
}
}
@@ -80,8 +80,8 @@ extern "C" {
(__calloc_with_fallback (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 != __libcxxabi_tls_set ( key_, retVal ) )
+ abort_message("__libcxxabi_tls_set failure in __cxa_get_globals()");
}
return retVal;
}
@@ -92,10 +92,10 @@ extern "C" {
// 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 != __libcxxabi_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*>(__libcxxabi_tls_get(key_));
}
}
diff --git a/libcxxabi/src/cxa_guard.cpp b/libcxxabi/src/cxa_guard.cpp
index 253d5d4ec5c..1c468ff5f8e 100644
--- a/libcxxabi/src/cxa_guard.cpp
+++ b/libcxxabi/src/cxa_guard.cpp
@@ -11,10 +11,8 @@
#include "abort_message.h"
#include "config.h"
+#include "threading_support.h"
-#ifndef _LIBCXXABI_HAS_NO_THREADS
-# include <pthread.h>
-#endif
#include <stdint.h>
/*
@@ -22,9 +20,9 @@
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
- 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.
+ __libcxxabi_mutex_lock and the abort_message utility without problem. This
+ implementation also uses __libcxxabi_condvar_wait which has tested
+ to not be a problem.
*/
namespace __cxxabiv1
@@ -69,8 +67,8 @@ bool is_initialized(guard_type* guard_object) {
#endif
#ifndef _LIBCXXABI_HAS_NO_THREADS
-pthread_mutex_t guard_mut = PTHREAD_MUTEX_INITIALIZER;
-pthread_cond_t guard_cv = PTHREAD_COND_INITIALIZER;
+__libcxxabi_mutex_t guard_mut = _LIBCXXABI_MUTEX_INITIALIZER;
+__libcxxabi_condvar_t guard_cv = _LIBCXXABI_CONDVAR_INITIALIZER;
#endif
#if defined(__APPLE__) && !defined(__arm__)
@@ -175,13 +173,13 @@ extern "C"
#ifndef _LIBCXXABI_HAS_NO_THREADS
_LIBCXXABI_FUNC_VIS int __cxa_guard_acquire(guard_type *guard_object) {
char* initialized = (char*)guard_object;
- if (pthread_mutex_lock(&guard_mut))
+ if (__libcxxabi_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 = pthread_mach_thread_np(pthread_self());
+ const lock_type id = __libcxxabi_thread_get_port();
lock_type lock = get_lock(*guard_object);
if (lock)
{
@@ -190,7 +188,7 @@ _LIBCXXABI_FUNC_VIS int __cxa_guard_acquire(guard_type *guard_object) {
abort_message("__cxa_guard_acquire detected deadlock");
do
{
- if (pthread_cond_wait(&guard_cv, &guard_mut))
+ if (__libcxxabi_condvar_wait(&guard_cv, &guard_mut))
abort_message("__cxa_guard_acquire condition variable wait failed");
lock = get_lock(*guard_object);
} while (lock);
@@ -202,36 +200,36 @@ _LIBCXXABI_FUNC_VIS int __cxa_guard_acquire(guard_type *guard_object) {
set_lock(*guard_object, id);
#else // !__APPLE__ || __arm__
while (get_lock(*guard_object))
- if (pthread_cond_wait(&guard_cv, &guard_mut))
+ if (__libcxxabi_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 (pthread_mutex_unlock(&guard_mut))
+ if (__libcxxabi_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 (__libcxxabi_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 (__libcxxabi_mutex_unlock(&guard_mut))
abort_message("__cxa_guard_release failed to release mutex");
- if (pthread_cond_broadcast(&guard_cv))
+ if (__libcxxabi_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 (pthread_mutex_lock(&guard_mut))
+ if (__libcxxabi_mutex_lock(&guard_mut))
abort_message("__cxa_guard_abort failed to acquire mutex");
*guard_object = 0;
- if (pthread_mutex_unlock(&guard_mut))
+ if (__libcxxabi_mutex_unlock(&guard_mut))
abort_message("__cxa_guard_abort failed to release mutex");
- if (pthread_cond_broadcast(&guard_cv))
+ if (__libcxxabi_condvar_broadcast(&guard_cv))
abort_message("__cxa_guard_abort failed to broadcast condition variable");
}
diff --git a/libcxxabi/src/cxa_thread_atexit.cpp b/libcxxabi/src/cxa_thread_atexit.cpp
index dea5c21504b..933c9c7243c 100644
--- a/libcxxabi/src/cxa_thread_atexit.cpp
+++ b/libcxxabi/src/cxa_thread_atexit.cpp
@@ -9,8 +9,8 @@
#include "abort_message.h"
#include "cxxabi.h"
+#include "threading_support.h"
#include <cstdlib>
-#include <pthread.h>
namespace __cxxabiv1 {
@@ -39,9 +39,10 @@ namespace {
// destructors of any objects with static storage duration.
//
// - thread_local destructors on non-main threads run on the first iteration
- // through the pthread_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.
+ // through the __libcxxabi_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.
//
// Another limitation, though one shared with ..._impl(), is that any
// thread_locals that are first initialized after non-thread_local global
@@ -65,7 +66,7 @@ namespace {
// 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
- pthread_key_t dtors_key;
+ __libcxxabi_tls_key dtors_key;
void run_dtors(void*) {
while (auto head = dtors) {
@@ -79,16 +80,16 @@ namespace {
struct DtorsManager {
DtorsManager() {
- // There is intentionally no matching pthread_key_delete call, as
+ // There is intentionally no matching __libcxxabi_tls_delete call, as
// __cxa_thread_atexit() may be called arbitrarily late (for example, from
// global destructors or atexit() handlers).
- if (pthread_key_create(&dtors_key, run_dtors) != 0) {
- abort_message("pthread_key_create() failed in __cxa_thread_atexit()");
+ if (__libcxxabi_tls_create(&dtors_key, run_dtors) != 0) {
+ abort_message("__libcxxabi_tls_create() failed in __cxa_thread_atexit()");
}
}
~DtorsManager() {
- // pthread_key destructors do not run on threads that call exit()
+ // __libcxxabi_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
@@ -109,12 +110,12 @@ extern "C" {
if (__cxa_thread_atexit_impl) {
return __cxa_thread_atexit_impl(dtor, obj, dso_symbol);
} else {
- // Initialize the dtors pthread_key (uses __cxa_guard_*() for one-time
- // initialization and __cxa_atexit() for destruction)
+ // Initialize the dtors __libcxxabi_tls_key (uses __cxa_guard_*() for
+ // one-time initialization and __cxa_atexit() for destruction)
static DtorsManager manager;
if (!dtors_alive) {
- if (pthread_setspecific(dtors_key, &dtors_key) != 0) {
+ if (__libcxxabi_tls_set(dtors_key, &dtors_key) != 0) {
return -1;
}
dtors_alive = true;
diff --git a/libcxxabi/src/fallback_malloc.cpp b/libcxxabi/src/fallback_malloc.cpp
index a436ed0ece7..5f52ece56f4 100644
--- a/libcxxabi/src/fallback_malloc.cpp
+++ b/libcxxabi/src/fallback_malloc.cpp
@@ -10,14 +10,11 @@
#include "fallback_malloc.h"
#include "config.h"
+#include "threading_support.h"
#include <cstdlib> // for malloc, calloc, free
#include <cstring> // for memset
-#ifndef _LIBCXXABI_HAS_NO_THREADS
-#include <pthread.h> // for mutexes
-#endif
-
// A small, simple heap manager based (loosely) on
// the startup heap manager from FreeBSD, optimized for space.
//
@@ -32,7 +29,7 @@ namespace {
// When POSIX threads are not available, make the mutex operations a nop
#ifndef _LIBCXXABI_HAS_NO_THREADS
-static pthread_mutex_t heap_mutex = PTHREAD_MUTEX_INITIALIZER;
+static __libcxxabi_mutex_t heap_mutex = _LIBCXXABI_MUTEX_INITIALIZER;
#else
static void * heap_mutex = 0;
#endif
@@ -40,8 +37,8 @@ static void * heap_mutex = 0;
class mutexor {
public:
#ifndef _LIBCXXABI_HAS_NO_THREADS
- mutexor ( pthread_mutex_t *m ) : mtx_(m) { pthread_mutex_lock ( mtx_ ); }
- ~mutexor () { pthread_mutex_unlock ( mtx_ ); }
+ mutexor ( __libcxxabi_mutex_t *m ) : mtx_(m) { __libcxxabi_mutex_lock ( mtx_ ); }
+ ~mutexor () { __libcxxabi_mutex_unlock ( mtx_ ); }
#else
mutexor ( void * ) {}
~mutexor () {}
@@ -50,7 +47,7 @@ private:
mutexor ( const mutexor &rhs );
mutexor & operator = ( const mutexor &rhs );
#ifndef _LIBCXXABI_HAS_NO_THREADS
- pthread_mutex_t *mtx_;
+ __libcxxabi_mutex_t *mtx_;
#endif
};
diff --git a/libcxxabi/src/threading_support.h b/libcxxabi/src/threading_support.h
new file mode 100644
index 00000000000..78a225f8af4
--- /dev/null
+++ b/libcxxabi/src/threading_support.h
@@ -0,0 +1,107 @@
+//===------------------------ 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 <pthread.h>
+
+#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
diff --git a/libcxxabi/test/test_exception_storage.pass.cpp b/libcxxabi/test/test_exception_storage.pass.cpp
index 90812469281..d5092274d91 100644
--- a/libcxxabi/test/test_exception_storage.pass.cpp
+++ b/libcxxabi/test/test_exception_storage.pass.cpp
@@ -12,9 +12,7 @@
#include <cstdlib>
#include <algorithm>
#include <iostream>
-#ifndef _LIBCXXABI_HAS_NO_THREADS
-# include <pthread.h>
-#endif
+#include "../src/threading_support.h"
#include <unistd.h>
#include "../src/cxa_exception.hpp"
@@ -40,8 +38,8 @@ void *thread_code (void *parm) {
#ifndef _LIBCXXABI_HAS_NO_THREADS
#define NUMTHREADS 10
-size_t thread_globals [ NUMTHREADS ] = { 0 };
-pthread_t threads [ NUMTHREADS ];
+size_t thread_globals [ NUMTHREADS ] = { 0 };
+__libcxxabi_thread_t threads [ NUMTHREADS ];
#endif
int main ( int argc, char *argv [] ) {
@@ -50,9 +48,9 @@ int main ( int argc, char *argv [] ) {
#ifndef _LIBCXXABI_HAS_NO_THREADS
// Make the threads, let them run, and wait for them to finish
for ( int i = 0; i < NUMTHREADS; ++i )
- pthread_create( threads + i, NULL, thread_code, (void *) (thread_globals + i));
+ __libcxxabi_thread_create ( threads + i, thread_code, (void *) (thread_globals + i));
for ( int i = 0; i < NUMTHREADS; ++i )
- pthread_join ( threads [ i ], NULL );
+ __libcxxabi_thread_join ( &threads [ i ] );
for ( int i = 0; i < NUMTHREADS; ++i )
if ( 0 == thread_globals [ i ] ) {
diff --git a/libcxxabi/test/test_fallback_malloc.pass.cpp b/libcxxabi/test/test_fallback_malloc.pass.cpp
index 474e0b3b336..250a7389186 100644
--- a/libcxxabi/test/test_fallback_malloc.pass.cpp
+++ b/libcxxabi/test/test_fallback_malloc.pass.cpp
@@ -10,7 +10,7 @@
#include <iostream>
#include <deque>
-#include <pthread.h>
+#include "../src/threading_support.h"
typedef std::deque<void *> container;
OpenPOWER on IntegriCloud