* 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 _<func>.  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.
This commit is contained in:
Christopher Faylor 2010-02-10 07:25:26 +00:00
parent 161387a725
commit 3700578ee8
4 changed files with 109 additions and 102 deletions

View File

@ -1,3 +1,35 @@
2010-02-10 Christopher Faylor <me+cygwin@cgf.cx>
* 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 _<func>. 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 <me+cygwin@cgf.cx> 2010-02-09 Christopher Faylor <me+cygwin@cgf.cx>
* cygtls.h (struct _cygtls): Remove unneeded elements. * cygtls.h (struct _cygtls): Remove unneeded elements.

View File

@ -955,11 +955,16 @@ _dll_crt0 ()
{ {
main_environ = user_data->envptr; main_environ = user_data->envptr;
if (in_forkee) if (in_forkee)
fork_info->alloc_stack (); {
fork_info->alloc_stack ();
_main_tls = &_my_tls;
}
else 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); _main_tls->call ((DWORD (*) (void *, void *)) dll_crt0_1, NULL);
} }

View File

@ -1,7 +1,7 @@
/* thread.cc: Locking and threading module functions /* thread.cc: Locking and threading module functions
Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 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. This file is part of Cygwin.
@ -187,9 +187,8 @@ pthread_mutex::can_be_unlocked (pthread_mutex_t const *mutex)
return false; return false;
/* Check if the mutex is owned by the current thread and can be unlocked. /* 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. */ * Also check for the ANONYMOUS owner to cover NORMAL mutexes as well. */
return ((*mutex)->recursion_counter == 1 return (*mutex)->recursion_counter == 1
&& ((*mutex)->owner == MUTEX_OWNER_ANONYMOUS && pthread::equal ((*mutex)->owner, self);
|| pthread::equal ((*mutex)->owner, self)));
} }
inline bool inline bool
@ -302,7 +301,7 @@ MTinterface::fixup_after_fork ()
void void
pthread::init_mainthread () pthread::init_mainthread ()
{ {
pthread *thread = get_tls_self_pointer (); pthread *thread = _my_tls.tid;
if (!thread) if (!thread)
{ {
thread = new pthread (); thread = new pthread ();
@ -325,7 +324,7 @@ pthread::init_mainthread ()
pthread * pthread *
pthread::self () pthread::self ()
{ {
pthread *thread = get_tls_self_pointer (); pthread *thread = _my_tls.tid;
if (!thread) if (!thread)
{ {
thread = pthread_null::get_null_pthread (); thread = pthread_null::get_null_pthread ();
@ -334,12 +333,6 @@ pthread::self ()
return thread; return thread;
} }
pthread *
pthread::get_tls_self_pointer ()
{
return _my_tls.tid;
}
void void
pthread::set_tls_self_pointer (pthread *thread) pthread::set_tls_self_pointer (pthread *thread)
{ {
@ -1561,7 +1554,7 @@ pthread_mutex::pthread_mutex (pthread_mutexattr *attr) :
type (PTHREAD_MUTEX_ERRORCHECK), type (PTHREAD_MUTEX_ERRORCHECK),
pshared (PTHREAD_PROCESS_PRIVATE) 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) if (!win32_obj_id)
{ {
magic = 0; magic = 0;
@ -1592,8 +1585,9 @@ pthread_mutex::~pthread_mutex ()
} }
int int
pthread_mutex::_lock (pthread_t self) pthread_mutex::lock ()
{ {
pthread_t self = ::pthread_self ();
int result = 0; int result = 0;
if (InterlockedIncrement ((long *)&lock_counter) == 1) if (InterlockedIncrement ((long *)&lock_counter) == 1)
@ -1616,8 +1610,31 @@ pthread_mutex::_lock (pthread_t self)
} }
int 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; int result = 0;
if (InterlockedCompareExchange ((long *) &lock_counter, 1, 0) == 0) if (InterlockedCompareExchange ((long *) &lock_counter, 1, 0) == 0)
@ -1631,31 +1648,9 @@ pthread_mutex::_trylock (pthread_t self)
} }
int int
pthread_mutex::_unlock (pthread_t self) pthread_mutex::destroy ()
{ {
if (!pthread::equal (owner, self)) if (condwaits || trylock ())
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))
// Do not destroy a condwaited or locked mutex // Do not destroy a condwaited or locked mutex
return EBUSY; return EBUSY;
else if (recursion_counter > 1) else if (recursion_counter > 1)
@ -1683,7 +1678,7 @@ pthread_mutex::_fixup_after_fork ()
#ifdef DEBUGGING #ifdef DEBUGGING
tid = 0xffffffff; /* Don't know the tid after a fork */ tid = 0xffffffff; /* Don't know the tid after a fork */
#endif #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) if (!win32_obj_id)
api_fatal ("pthread_mutex::_fixup_after_fork () failed to recreate win32 semaphore for mutex"); 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_mutexattr_t *attr,
const pthread_mutex_t initializer) const pthread_mutex_t initializer)
{ {
pthread_mutex_t new_mutex;
if (attr && !pthread_mutexattr::is_good_object (attr)) if (attr && !pthread_mutexattr::is_good_object (attr))
return EINVAL; return EINVAL;
mutex_initialization_lock.lock (); mutex_initialization_lock.lock ();
if (pthread_mutex::is_good_initializer (mutex))
new_mutex = new pthread_mutex (attr ? (*attr) : NULL);
if (!is_good_object (&new_mutex))
{ {
delete new_mutex; pthread_mutex_t new_mutex = new pthread_mutex (attr ? (*attr) : NULL);
mutex_initialization_lock.unlock (); if (!is_good_object (&new_mutex))
return EAGAIN; {
} delete new_mutex;
mutex_initialization_lock.unlock ();
return EAGAIN;
}
if (!attr && initializer) if (!attr && initializer)
{ {
if (initializer == PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP) if (initializer == PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP)
new_mutex->type = PTHREAD_MUTEX_RECURSIVE; new_mutex->type = PTHREAD_MUTEX_RECURSIVE;
else if (initializer == PTHREAD_NORMAL_MUTEX_INITIALIZER_NP) else if (initializer == PTHREAD_NORMAL_MUTEX_INITIALIZER_NP)
new_mutex->type = PTHREAD_MUTEX_NORMAL; new_mutex->type = PTHREAD_MUTEX_NORMAL;
else if (initializer == PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP) else if (initializer == PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP)
new_mutex->type = PTHREAD_MUTEX_ERRORCHECK; new_mutex->type = PTHREAD_MUTEX_ERRORCHECK;
} }
myfault efault; myfault efault;
if (efault.faulted ()) if (efault.faulted ())
{ {
delete new_mutex; delete new_mutex;
mutex_initialization_lock.unlock (); mutex_initialization_lock.unlock ();
return EINVAL; return EINVAL;
} }
*mutex = new_mutex; *mutex = new_mutex;
}
mutex_initialization_lock.unlock (); mutex_initialization_lock.unlock ();
return 0; return 0;

View File

@ -1,7 +1,7 @@
/* thread.h: Locking and threading module definitions /* thread.h: Locking and threading module definitions
Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 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. This file is part of Cygwin.
@ -57,10 +57,10 @@ public:
bool init () bool init ()
{ {
lock_counter = 0; 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) if (!win32_obj_id)
{ {
debug_printf ("CreateSemaphore failed. %E"); debug_printf ("CreateEvent failed. %E");
return false; return false;
} }
return true; return true;
@ -75,7 +75,7 @@ public:
void unlock () void unlock ()
{ {
if (InterlockedDecrement ((long *) &lock_counter)) if (InterlockedDecrement ((long *) &lock_counter))
::ReleaseSemaphore (win32_obj_id, 1, NULL); ::SetEvent (win32_obj_id);
} }
private: private:
@ -285,29 +285,10 @@ public:
int type; int type;
int pshared; int pshared;
pthread_t get_pthread_self () const int lock ();
{ int trylock ();
return PTHREAD_MUTEX_NORMAL == type ? MUTEX_OWNER_ANONYMOUS : int unlock ();
::pthread_self (); int destroy ();
}
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 ());
}
void set_owner (pthread_t self) void set_owner (pthread_t self)
{ {
recursion_counter = 1; recursion_counter = 1;
@ -337,11 +318,6 @@ public:
} }
private: 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 (); void _fixup_after_fork ();
static List<pthread_mutex> mutexes; static List<pthread_mutex> mutexes;
@ -446,7 +422,6 @@ private:
void precreate (pthread_attr *); void precreate (pthread_attr *);
void postcreate (); void postcreate ();
bool create_cancel_event (); bool create_cancel_event ();
static pthread *get_tls_self_pointer ();
static void set_tls_self_pointer (pthread *); static void set_tls_self_pointer (pthread *);
void cancel_self (); void cancel_self ();
DWORD get_thread_id (); DWORD get_thread_id ();