From 3700578ee8a4d7f56184a8a742067a2bdcb71360 Mon Sep 17 00:00:00 2001 From: Christopher Faylor Date: Wed, 10 Feb 2010 07:25:26 +0000 Subject: [PATCH] * dcrt0.cc (_dll_crt0): Set _main_tls as early as possible. * thread.cc (pthread_mutex::can_be_unlocked): Remove check for MUTEX_OWNER_ANONYMOUS since it is racy and unsafe. (pthread::init_mainthread): Initialize thread directly from _my_tls. (pthread::self): Ditto. (pthread::get_tls_self_pointer): Delete. (pthread_mutex::pthread_mutex): Use an event rather than a semaphore. (pthread_mutex::lock): Rename from _. Derive self directly. (pthread_mutex::tryunlock): Ditto. (pthread_mutex::destroy): Ditto. (pthread_mutex::unlock): Ditto. Accommodate change from semaphore to event. (pthread_mutex::_fixup_after_fork): Accommodate change from semaphore to event. (pthread_mutex::init): Don't attempt to initialize a semaphore unless it is in an initialized state. Do this check under mutex_initialization_lock.lock * thread.h (fast_mutex::init): Use event rather than semaphore. (fast_mutex::lock): Ditto. (pthread_mutex::_lock): Delete. (pthread_mutex::_unlock): Ditto. (pthread_mutex::_trylock): Ditto. (pthread_mutex::_destroy): Ditto. (pthread_mutex::get_pthread_self): Ditto. (pthread_mutex::get_tls_self_pointer): Ditto. (pthread_mutex::lock): Un-inline. (pthread_mutex::unlock): Ditto. (pthread_mutex::trylock): Ditto. (pthread_mutex::destroy): Ditto. --- winsup/cygwin/ChangeLog | 32 ++++++++++ winsup/cygwin/dcrt0.cc | 11 +++- winsup/cygwin/thread.cc | 127 +++++++++++++++++++--------------------- winsup/cygwin/thread.h | 41 +++---------- 4 files changed, 109 insertions(+), 102 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 2469ee1bd..72aff2e47 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,35 @@ +2010-02-10 Christopher Faylor + + * dcrt0.cc (_dll_crt0): Set _main_tls as early as possible. + * thread.cc (pthread_mutex::can_be_unlocked): Remove check for + MUTEX_OWNER_ANONYMOUS since it is racy and unsafe. + (pthread::init_mainthread): Initialize thread directly from _my_tls. + (pthread::self): Ditto. + (pthread::get_tls_self_pointer): Delete. + (pthread_mutex::pthread_mutex): Use an event rather than a semaphore. + (pthread_mutex::lock): Rename from _. Derive self directly. + (pthread_mutex::tryunlock): Ditto. + (pthread_mutex::destroy): Ditto. + (pthread_mutex::unlock): Ditto. Accommodate change from semaphore to + event. + (pthread_mutex::_fixup_after_fork): Accommodate change from semaphore + to event. + (pthread_mutex::init): Don't attempt to initialize a semaphore unless + it is in an initialized state. Do this check under + mutex_initialization_lock.lock + * thread.h (fast_mutex::init): Use event rather than semaphore. + (fast_mutex::lock): Ditto. + (pthread_mutex::_lock): Delete. + (pthread_mutex::_unlock): Ditto. + (pthread_mutex::_trylock): Ditto. + (pthread_mutex::_destroy): Ditto. + (pthread_mutex::get_pthread_self): Ditto. + (pthread_mutex::get_tls_self_pointer): Ditto. + (pthread_mutex::lock): Un-inline. + (pthread_mutex::unlock): Ditto. + (pthread_mutex::trylock): Ditto. + (pthread_mutex::destroy): Ditto. + 2010-02-09 Christopher Faylor * cygtls.h (struct _cygtls): Remove unneeded elements. diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc index 7cd383bf7..6745f096e 100644 --- a/winsup/cygwin/dcrt0.cc +++ b/winsup/cygwin/dcrt0.cc @@ -955,11 +955,16 @@ _dll_crt0 () { main_environ = user_data->envptr; if (in_forkee) - fork_info->alloc_stack (); + { + fork_info->alloc_stack (); + _main_tls = &_my_tls; + } else - __sinit (_impure_ptr); + { + _main_tls = &_my_tls; + __sinit (_impure_ptr); + } - _main_tls = &_my_tls; _main_tls->call ((DWORD (*) (void *, void *)) dll_crt0_1, NULL); } diff --git a/winsup/cygwin/thread.cc b/winsup/cygwin/thread.cc index 98ffde24f..16f6ed160 100644 --- a/winsup/cygwin/thread.cc +++ b/winsup/cygwin/thread.cc @@ -1,7 +1,7 @@ /* thread.cc: Locking and threading module functions Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, - 2006, 2007, 2008 Red Hat, Inc. + 2006, 2007, 2008, 2009, 2010 Red Hat, Inc. This file is part of Cygwin. @@ -187,9 +187,8 @@ pthread_mutex::can_be_unlocked (pthread_mutex_t const *mutex) return false; /* Check if the mutex is owned by the current thread and can be unlocked. * Also check for the ANONYMOUS owner to cover NORMAL mutexes as well. */ - return ((*mutex)->recursion_counter == 1 - && ((*mutex)->owner == MUTEX_OWNER_ANONYMOUS - || pthread::equal ((*mutex)->owner, self))); + return (*mutex)->recursion_counter == 1 + && pthread::equal ((*mutex)->owner, self); } inline bool @@ -302,7 +301,7 @@ MTinterface::fixup_after_fork () void pthread::init_mainthread () { - pthread *thread = get_tls_self_pointer (); + pthread *thread = _my_tls.tid; if (!thread) { thread = new pthread (); @@ -325,7 +324,7 @@ pthread::init_mainthread () pthread * pthread::self () { - pthread *thread = get_tls_self_pointer (); + pthread *thread = _my_tls.tid; if (!thread) { thread = pthread_null::get_null_pthread (); @@ -334,12 +333,6 @@ pthread::self () return thread; } -pthread * -pthread::get_tls_self_pointer () -{ - return _my_tls.tid; -} - void pthread::set_tls_self_pointer (pthread *thread) { @@ -1561,7 +1554,7 @@ pthread_mutex::pthread_mutex (pthread_mutexattr *attr) : type (PTHREAD_MUTEX_ERRORCHECK), pshared (PTHREAD_PROCESS_PRIVATE) { - win32_obj_id = ::CreateSemaphore (&sec_none_nih, 0, LONG_MAX, NULL); + win32_obj_id = ::CreateEvent (&sec_none_nih, false, false, NULL); if (!win32_obj_id) { magic = 0; @@ -1592,8 +1585,9 @@ pthread_mutex::~pthread_mutex () } int -pthread_mutex::_lock (pthread_t self) +pthread_mutex::lock () { + pthread_t self = ::pthread_self (); int result = 0; if (InterlockedIncrement ((long *)&lock_counter) == 1) @@ -1616,8 +1610,31 @@ pthread_mutex::_lock (pthread_t self) } int -pthread_mutex::_trylock (pthread_t self) +pthread_mutex::unlock () { + pthread_t self = ::pthread_self (); + if (!pthread::equal (owner, self)) + return EPERM; + + /* Don't try to unlock anything if recursion_counter == 0 initially. + That means that we've forked. */ + if (recursion_counter > 0 && --recursion_counter == 0) + { + owner = NULL; +#ifdef DEBUGGING + tid = 0; +#endif + if (InterlockedDecrement ((long *) &lock_counter)) + ::SetEvent (win32_obj_id); // Another thread may be waiting + } + + return 0; +} + +int +pthread_mutex::trylock () +{ + pthread_t self = ::pthread_self (); int result = 0; if (InterlockedCompareExchange ((long *) &lock_counter, 1, 0) == 0) @@ -1631,31 +1648,9 @@ pthread_mutex::_trylock (pthread_t self) } int -pthread_mutex::_unlock (pthread_t self) +pthread_mutex::destroy () { - if (!pthread::equal (owner, self)) - return EPERM; - - /* Don't try to unlock anything if recursion_counter == 0 initially. - That means that we've forked. */ - if (recursion_counter > 0 && --recursion_counter == 0) - { - owner = NULL; -#ifdef DEBUGGING - tid = 0; -#endif - if (InterlockedDecrement ((long *) &lock_counter)) - // Another thread is waiting - ::ReleaseSemaphore (win32_obj_id, 1, NULL); - } - - return 0; -} - -int -pthread_mutex::_destroy (pthread_t self) -{ - if (condwaits || _trylock (self)) + if (condwaits || trylock ()) // Do not destroy a condwaited or locked mutex return EBUSY; else if (recursion_counter > 1) @@ -1683,7 +1678,7 @@ pthread_mutex::_fixup_after_fork () #ifdef DEBUGGING tid = 0xffffffff; /* Don't know the tid after a fork */ #endif - win32_obj_id = ::CreateSemaphore (&sec_none_nih, 0, LONG_MAX, NULL); + win32_obj_id = ::CreateEvent (&sec_none_nih, false, false, NULL); if (!win32_obj_id) api_fatal ("pthread_mutex::_fixup_after_fork () failed to recreate win32 semaphore for mutex"); } @@ -2665,40 +2660,40 @@ pthread_mutex::init (pthread_mutex_t *mutex, const pthread_mutexattr_t *attr, const pthread_mutex_t initializer) { - pthread_mutex_t new_mutex; - if (attr && !pthread_mutexattr::is_good_object (attr)) return EINVAL; mutex_initialization_lock.lock (); - - new_mutex = new pthread_mutex (attr ? (*attr) : NULL); - if (!is_good_object (&new_mutex)) + if (pthread_mutex::is_good_initializer (mutex)) { - delete new_mutex; - mutex_initialization_lock.unlock (); - return EAGAIN; - } + pthread_mutex_t new_mutex = new pthread_mutex (attr ? (*attr) : NULL); + if (!is_good_object (&new_mutex)) + { + delete new_mutex; + mutex_initialization_lock.unlock (); + return EAGAIN; + } - if (!attr && initializer) - { - if (initializer == PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP) - new_mutex->type = PTHREAD_MUTEX_RECURSIVE; - else if (initializer == PTHREAD_NORMAL_MUTEX_INITIALIZER_NP) - new_mutex->type = PTHREAD_MUTEX_NORMAL; - else if (initializer == PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP) - new_mutex->type = PTHREAD_MUTEX_ERRORCHECK; - } + if (!attr && initializer) + { + if (initializer == PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP) + new_mutex->type = PTHREAD_MUTEX_RECURSIVE; + else if (initializer == PTHREAD_NORMAL_MUTEX_INITIALIZER_NP) + new_mutex->type = PTHREAD_MUTEX_NORMAL; + else if (initializer == PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP) + new_mutex->type = PTHREAD_MUTEX_ERRORCHECK; + } - myfault efault; - if (efault.faulted ()) - { - delete new_mutex; - mutex_initialization_lock.unlock (); - return EINVAL; - } + myfault efault; + if (efault.faulted ()) + { + delete new_mutex; + mutex_initialization_lock.unlock (); + return EINVAL; + } - *mutex = new_mutex; + *mutex = new_mutex; + } mutex_initialization_lock.unlock (); return 0; diff --git a/winsup/cygwin/thread.h b/winsup/cygwin/thread.h index 04869f763..21d278dae 100644 --- a/winsup/cygwin/thread.h +++ b/winsup/cygwin/thread.h @@ -1,7 +1,7 @@ /* thread.h: Locking and threading module definitions Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, - 2008, 2009 Red Hat, Inc. + 2008, 2009, 2010 Red Hat, Inc. This file is part of Cygwin. @@ -57,10 +57,10 @@ public: bool init () { lock_counter = 0; - win32_obj_id = ::CreateSemaphore (&sec_none_nih, 0, LONG_MAX, NULL); + win32_obj_id = ::CreateEvent (&sec_none_nih, false, false, NULL); if (!win32_obj_id) { - debug_printf ("CreateSemaphore failed. %E"); + debug_printf ("CreateEvent failed. %E"); return false; } return true; @@ -75,7 +75,7 @@ public: void unlock () { if (InterlockedDecrement ((long *) &lock_counter)) - ::ReleaseSemaphore (win32_obj_id, 1, NULL); + ::SetEvent (win32_obj_id); } private: @@ -285,29 +285,10 @@ public: int type; int pshared; - pthread_t get_pthread_self () const - { - return PTHREAD_MUTEX_NORMAL == type ? MUTEX_OWNER_ANONYMOUS : - ::pthread_self (); - } - - int lock () - { - return _lock (get_pthread_self ()); - } - int trylock () - { - return _trylock (get_pthread_self ()); - } - int unlock () - { - return _unlock (get_pthread_self ()); - } - int destroy () - { - return _destroy (get_pthread_self ()); - } - + int lock (); + int trylock (); + int unlock (); + int destroy (); void set_owner (pthread_t self) { recursion_counter = 1; @@ -337,11 +318,6 @@ public: } private: - int _lock (pthread_t self); - int _trylock (pthread_t self); - int _unlock (pthread_t self); - int _destroy (pthread_t self); - void _fixup_after_fork (); static List mutexes; @@ -446,7 +422,6 @@ private: void precreate (pthread_attr *); void postcreate (); bool create_cancel_event (); - static pthread *get_tls_self_pointer (); static void set_tls_self_pointer (pthread *); void cancel_self (); DWORD get_thread_id ();