Use bionic lock in pthread_internal_t.

It removes calling to pthread_mutex_lock() at the beginning of new
thread, which helps to support thread sanitizer.

Change-Id: Ia3601c476de7976a9177b792bd74bb200cee0e13
This commit is contained in:
Yabin Cui 2015-10-22 20:07:56 -07:00
parent 5edf077c5b
commit d26e780df6
3 changed files with 11 additions and 13 deletions

View File

@ -193,8 +193,7 @@ static int __pthread_start(void* arg) {
// notify gdb about this thread before we start doing anything. // notify gdb about this thread before we start doing anything.
// This also provides the memory barrier needed to ensure that all memory // This also provides the memory barrier needed to ensure that all memory
// accesses previously made by the creating thread are visible to us. // accesses previously made by the creating thread are visible to us.
pthread_mutex_lock(&thread->startup_handshake_mutex); thread->startup_handshake_lock.lock();
pthread_mutex_destroy(&thread->startup_handshake_mutex);
__init_alternate_signal_stack(thread); __init_alternate_signal_stack(thread);
@ -233,14 +232,14 @@ int pthread_create(pthread_t* thread_out, pthread_attr_t const* attr,
return result; return result;
} }
// Create a mutex for the thread in TLS to wait on once it starts so we can keep // Create a lock for the thread to wait on once it starts so we can keep
// it from doing anything until after we notify the debugger about it // it from doing anything until after we notify the debugger about it
// //
// This also provides the memory barrier we need to ensure that all // This also provides the memory barrier we need to ensure that all
// memory accesses previously performed by this thread are visible to // memory accesses previously performed by this thread are visible to
// the new thread. // the new thread.
pthread_mutex_init(&thread->startup_handshake_mutex, NULL); thread->startup_handshake_lock.init(false);
pthread_mutex_lock(&thread->startup_handshake_mutex); thread->startup_handshake_lock.lock();
thread->start_routine = start_routine; thread->start_routine = start_routine;
thread->start_routine_arg = arg; thread->start_routine_arg = arg;
@ -263,7 +262,7 @@ int pthread_create(pthread_t* thread_out, pthread_attr_t const* attr,
// We don't have to unlock the mutex at all because clone(2) failed so there's no child waiting to // We don't have to unlock the mutex at all because clone(2) failed so there's no child waiting to
// be unblocked, but we're about to unmap the memory the mutex is stored in, so this serves as a // be unblocked, but we're about to unmap the memory the mutex is stored in, so this serves as a
// reminder that you can't rewrite this function to use a ScopedPthreadMutexLocker. // reminder that you can't rewrite this function to use a ScopedPthreadMutexLocker.
pthread_mutex_unlock(&thread->startup_handshake_mutex); thread->startup_handshake_lock.unlock();
if (thread->mmap_size != 0) { if (thread->mmap_size != 0) {
munmap(thread->attr.stack_base, thread->mmap_size); munmap(thread->attr.stack_base, thread->mmap_size);
} }
@ -278,13 +277,13 @@ int pthread_create(pthread_t* thread_out, pthread_attr_t const* attr,
atomic_store(&thread->join_state, THREAD_DETACHED); atomic_store(&thread->join_state, THREAD_DETACHED);
__pthread_internal_add(thread); __pthread_internal_add(thread);
thread->start_routine = __do_nothing; thread->start_routine = __do_nothing;
pthread_mutex_unlock(&thread->startup_handshake_mutex); thread->startup_handshake_lock.unlock();
return init_errno; return init_errno;
} }
// Publish the pthread_t and unlock the mutex to let the new thread start running. // Publish the pthread_t and unlock the mutex to let the new thread start running.
*thread_out = __pthread_internal_add(thread); *thread_out = __pthread_internal_add(thread);
pthread_mutex_unlock(&thread->startup_handshake_mutex); thread->startup_handshake_lock.unlock();
return 0; return 0;
} }

View File

@ -31,6 +31,7 @@
#include <pthread.h> #include <pthread.h>
#include <stdatomic.h> #include <stdatomic.h>
#include "private/bionic_lock.h"
#include "private/bionic_tls.h" #include "private/bionic_tls.h"
/* Has the thread been detached by a pthread_join or pthread_detach call? */ /* Has the thread been detached by a pthread_join or pthread_detach call? */
@ -89,7 +90,7 @@ struct pthread_internal_t {
void* alternate_signal_stack; void* alternate_signal_stack;
pthread_mutex_t startup_handshake_mutex; Lock startup_handshake_lock;
size_t mmap_size; size_t mmap_size;

View File

@ -31,6 +31,8 @@
#include <stdatomic.h> #include <stdatomic.h>
#include "private/bionic_futex.h" #include "private/bionic_futex.h"
// Lock is used in places like pthread_rwlock_t, which can be initialized without calling
// an initialization function. So make sure Lock can be initialized by setting its memory to 0.
class Lock { class Lock {
private: private:
enum LockState { enum LockState {
@ -42,10 +44,6 @@ class Lock {
bool process_shared; bool process_shared;
public: public:
Lock(bool process_shared = false) {
init(process_shared);
}
void init(bool process_shared) { void init(bool process_shared) {
atomic_init(&state, Unlocked); atomic_init(&state, Unlocked);
this->process_shared = process_shared; this->process_shared = process_shared;