Index: libunwind/src/RWMutex.hpp =================================================================== --- libunwind/src/RWMutex.hpp +++ libunwind/src/RWMutex.hpp @@ -58,12 +58,34 @@ #else +extern "C" int __attribute__((weak)) +pthread_create(pthread_t *thread, const pthread_attr_t *attr, + void *(*start_routine)(void *), void *arg); +extern "C" int __attribute__((weak)) +pthread_rwlock_rdlock(pthread_rwlock_t *lock); +extern "C" int __attribute__((weak)) +pthread_rwlock_wrlock(pthread_rwlock_t *lock); +extern "C" int __attribute__((weak)) +pthread_rwlock_unlock(pthread_rwlock_t *lock); + +// Calls to the locking functions are gated on pthread_create, and not the +// functions themselves, because the data structure should only be locked if +// another thread has been created. This is what similar libraries do. + class _LIBUNWIND_HIDDEN RWMutex { public: - bool lock_shared() { return pthread_rwlock_rdlock(&_lock) == 0; } - bool unlock_shared() { return pthread_rwlock_unlock(&_lock) == 0; } - bool lock() { return pthread_rwlock_wrlock(&_lock) == 0; } - bool unlock() { return pthread_rwlock_unlock(&_lock) == 0; } + bool lock_shared() { + return !pthread_create || (pthread_rwlock_rdlock(&_lock) == 0); + } + bool unlock_shared() { + return !pthread_create || (pthread_rwlock_unlock(&_lock) == 0); + } + bool lock() { + return !pthread_create || (pthread_rwlock_wrlock(&_lock) == 0); + } + bool unlock() { + return !pthread_create || (pthread_rwlock_unlock(&_lock) == 0); + } private: pthread_rwlock_t _lock = PTHREAD_RWLOCK_INITIALIZER;