From 2ff03dc2e01dbf0525ad32960612b5df0c6cb9f8 Mon Sep 17 00:00:00 2001 From: Thomas Pfaff Date: Tue, 18 Mar 2003 19:39:21 +0000 Subject: [PATCH] * include/pthread.h (PTHREAD_MUTEX_NORMAL): New define. * thread.cc: Remove errno.h include. (pthread::precreate): Change internal mutex type to normal. (pthread_mutex::canBeUnlocked): Implement. (pthread_mutex::pthread_mutex): Initialize lock_counter with 0. (pthread_mutex::Lock): Rename to _Lock. Add self parameter. Change lock_counter logic. Update SetOwner call. (pthread_mutex::TryLock): Rename to _TryLock. Add self parameter. Change lock_counter logic. Update SetOwner call. (pthread_mutex::UnLock): Rename to _UnLock. Add self parameter. Change lock_counter logic. (pthread_mutex::Destroy): Rename to _Destroy. Update TryLock call. (pthread_mutex::SetOwner): Move to thread.h as inline. (pthread_mutex::LockRecursive): Ditto. (pthread_mutex::fixup_after_fork): Change lock_counter logic. (__pthread_mutexattr_settype): Add PTHREAD_MUTEX_NORMAL to valid types check. * thread.h: Include errno.h and limits.h. (MUTEX_LOCK_COUNTER_INITIAL): Remove. (MUTEX_OWNER_ANONYMOUS): New define. (pthread_mutex::canBeUnlocked): New static method. (pthread_mutex::lock_counter): Change type to unsigned long. (pthread_mutex::GetPthreadSelf): New method. (pthread_mutex::Lock): Call _Lock with pthread_self pointer. (pthread_mutex::TryLock): Call _TryLock with pthread_self pointer. (pthread_mutex::UnLock): Call _UnLock with pthread_self pointer. (pthread_mutex::Destroy): Call _Destroy with pthread_self pointer. (pthread_mutex::SetOwner): Moved from thread.cc as inline. (pthread_mutex::LockRecursive): Ditto. (pthread_mutex::_Lock): New method. (pthread_mutex::_TryLock): New method. (pthread_mutex::_UnLock): New method. (pthread_mutex::_Destroy): New method. --- winsup/cygwin/ChangeLog | 36 ++++++++++++++++ winsup/cygwin/include/pthread.h | 1 + winsup/cygwin/thread.cc | 75 +++++++++++++++------------------ winsup/cygwin/thread.h | 57 +++++++++++++++++++++---- 4 files changed, 119 insertions(+), 50 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index e70ae9327..aea639287 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,39 @@ +2003-03-18 Thomas Pfaff + + * include/pthread.h (PTHREAD_MUTEX_NORMAL): New define. + * thread.cc: Remove errno.h include. + (pthread::precreate): Change internal mutex type to normal. + (pthread_mutex::canBeUnlocked): Implement. + (pthread_mutex::pthread_mutex): Initialize lock_counter with 0. + (pthread_mutex::Lock): Rename to _Lock. Add self parameter. + Change lock_counter logic. Update SetOwner call. + (pthread_mutex::TryLock): Rename to _TryLock. Add self parameter. + Change lock_counter logic. Update SetOwner call. + (pthread_mutex::UnLock): Rename to _UnLock. Add self parameter. + Change lock_counter logic. + (pthread_mutex::Destroy): Rename to _Destroy. Update TryLock call. + (pthread_mutex::SetOwner): Move to thread.h as inline. + (pthread_mutex::LockRecursive): Ditto. + (pthread_mutex::fixup_after_fork): Change lock_counter logic. + (__pthread_mutexattr_settype): Add PTHREAD_MUTEX_NORMAL to valid + types check. + * thread.h: Include errno.h and limits.h. + (MUTEX_LOCK_COUNTER_INITIAL): Remove. + (MUTEX_OWNER_ANONYMOUS): New define. + (pthread_mutex::canBeUnlocked): New static method. + (pthread_mutex::lock_counter): Change type to unsigned long. + (pthread_mutex::GetPthreadSelf): New method. + (pthread_mutex::Lock): Call _Lock with pthread_self pointer. + (pthread_mutex::TryLock): Call _TryLock with pthread_self pointer. + (pthread_mutex::UnLock): Call _UnLock with pthread_self pointer. + (pthread_mutex::Destroy): Call _Destroy with pthread_self pointer. + (pthread_mutex::SetOwner): Moved from thread.cc as inline. + (pthread_mutex::LockRecursive): Ditto. + (pthread_mutex::_Lock): New method. + (pthread_mutex::_TryLock): New method. + (pthread_mutex::_UnLock): New method. + (pthread_mutex::_Destroy): New method. + 2003-03-18 Christopher January * fhandler_proc.cc (format_proc_cpuinfo): Use IsProcessorFeaturePresent diff --git a/winsup/cygwin/include/pthread.h b/winsup/cygwin/include/pthread.h index bc7db4d39..7ac683487 100644 --- a/winsup/cygwin/include/pthread.h +++ b/winsup/cygwin/include/pthread.h @@ -52,6 +52,7 @@ extern "C" #define PTHREAD_INHERIT_SCHED 0 #define PTHREAD_MUTEX_RECURSIVE 0 #define PTHREAD_MUTEX_ERRORCHECK 1 +#define PTHREAD_MUTEX_NORMAL 2 #define PTHREAD_MUTEX_DEFAULT PTHREAD_MUTEX_ERRORCHECK /* this should be too low to ever be a valid address */ #define PTHREAD_MUTEX_INITIALIZER (pthread_mutex_t)20 diff --git a/winsup/cygwin/thread.cc b/winsup/cygwin/thread.cc index 9f8839fb1..f20356439 100644 --- a/winsup/cygwin/thread.cc +++ b/winsup/cygwin/thread.cc @@ -32,7 +32,6 @@ details. */ #ifdef _MT_SAFE #include "winsup.h" #include -#include #include "cygerrno.h" #include #include @@ -328,6 +327,8 @@ pthread::precreate (pthread_attr *newattr) magic = 0; return; } + /* Change the mutex type to NORMAL to speed up mutex operations */ + mutex.type = PTHREAD_MUTEX_NORMAL; cancel_event = ::CreateEvent (&sec_none_nih, TRUE, FALSE, NULL); if (!cancel_event) @@ -1157,6 +1158,19 @@ pthread_mutex::isGoodInitializerOrBadObject (pthread_mutex_t const *mutex) return true; } +bool +pthread_mutex::canBeUnlocked (pthread_mutex_t const *mutex) +{ + pthread_t self = pthread::self (); + + if (!isGoodObject (mutex)) + return false; + /* + * Check if the mutex is owned by the current thread and can be unlocked + */ + return (__pthread_equal (&(*mutex)->owner, &self)) && 1 == (*mutex)->recursion_counter; +} + /* This is used for mutex creation protection within a single process only */ nativeMutex NO_COPY pthread_mutex::mutexInitializationLock; @@ -1172,7 +1186,7 @@ pthread_mutex::initMutex () pthread_mutex::pthread_mutex (pthread_mutexattr *attr) : verifyable_object (PTHREAD_MUTEX_MAGIC), - lock_counter (MUTEX_LOCK_COUNTER_INITIAL), + lock_counter (0), win32_obj_id (NULL), recursion_counter (0), condwaits (0), owner (NULL), type (PTHREAD_MUTEX_DEFAULT), pshared (PTHREAD_PROCESS_PRIVATE) @@ -1221,16 +1235,15 @@ pthread_mutex::~pthread_mutex () } int -pthread_mutex::Lock () +pthread_mutex::_Lock (pthread_t self) { int result = 0; - pthread_t self = pthread::self (); - if (0 == InterlockedIncrement (&lock_counter)) - SetOwner (); - else if (__pthread_equal (&owner, &self)) + if (1 == InterlockedIncrement ((long *)&lock_counter)) + SetOwner (self); + else if (PTHREAD_MUTEX_NORMAL != type && __pthread_equal (&owner, &self)) { - InterlockedDecrement (&lock_counter); + InterlockedDecrement ((long *) &lock_counter); if (PTHREAD_MUTEX_RECURSIVE == type) result = LockRecursive (); else @@ -1239,23 +1252,20 @@ pthread_mutex::Lock () else { WaitForSingleObject (win32_obj_id, INFINITE); - SetOwner (); + SetOwner (self); } return result; } -/* returns non-zero on failure */ int -pthread_mutex::TryLock () +pthread_mutex::_TryLock (pthread_t self) { int result = 0; - pthread_t self = pthread::self (); - if (MUTEX_LOCK_COUNTER_INITIAL == - InterlockedCompareExchange (&lock_counter, 0, MUTEX_LOCK_COUNTER_INITIAL )) - SetOwner (); - else if (__pthread_equal (&owner, &self) && PTHREAD_MUTEX_RECURSIVE == type) + if (0 == InterlockedCompareExchange ((long *)&lock_counter, 1, 0 )) + SetOwner (self); + else if (PTHREAD_MUTEX_RECURSIVE == type && __pthread_equal (&owner, &self)) result = LockRecursive (); else result = EBUSY; @@ -1264,17 +1274,15 @@ pthread_mutex::TryLock () } int -pthread_mutex::UnLock () +pthread_mutex::_UnLock (pthread_t self) { - pthread_t self = pthread::self (); - if (!__pthread_equal (&owner, &self)) return EPERM; if (0 == --recursion_counter) { owner = NULL; - if (MUTEX_LOCK_COUNTER_INITIAL != InterlockedDecrement (&lock_counter)) + if (InterlockedDecrement ((long *)&lock_counter)) // Another thread is waiting ::ReleaseSemaphore (win32_obj_id, 1, NULL); } @@ -1283,9 +1291,9 @@ pthread_mutex::UnLock () } int -pthread_mutex::Destroy () +pthread_mutex::_Destroy (pthread_t self) { - if (condwaits || TryLock ()) + if (condwaits || _TryLock (self)) // Do not destroy a condwaited or locked mutex return EBUSY; else if (recursion_counter != 1) @@ -1299,22 +1307,6 @@ pthread_mutex::Destroy () return 0; } -void -pthread_mutex::SetOwner () -{ - recursion_counter = 1; - owner = pthread::self (); -} - -int -pthread_mutex::LockRecursive () -{ - if (UINT_MAX == recursion_counter) - return EAGAIN; - ++recursion_counter; - return 0; -} - void pthread_mutex::fixup_after_fork () { @@ -1324,10 +1316,10 @@ pthread_mutex::fixup_after_fork () if (NULL == owner) /* mutex has no owner, reset to initial */ - lock_counter = MUTEX_LOCK_COUNTER_INITIAL; - else if (lock_counter != MUTEX_LOCK_COUNTER_INITIAL) - /* All waiting threads are gone after a fork */ lock_counter = 0; + else if (lock_counter != 0) + /* All waiting threads are gone after a fork */ + lock_counter = 1; win32_obj_id = ::CreateSemaphore (&sec_none_nih, 0, LONG_MAX, NULL); if (!win32_obj_id) @@ -2615,6 +2607,7 @@ __pthread_mutexattr_settype (pthread_mutexattr_t *attr, int type) { case PTHREAD_MUTEX_ERRORCHECK: case PTHREAD_MUTEX_RECURSIVE: + case PTHREAD_MUTEX_NORMAL: (*attr)->mutextype = type; break; default: diff --git a/winsup/cygwin/thread.h b/winsup/cygwin/thread.h index 9e1405d61..bd911bd49 100644 --- a/winsup/cygwin/thread.h +++ b/winsup/cygwin/thread.h @@ -39,6 +39,8 @@ extern "C" #else #include +#include +#include #include #include #include @@ -160,9 +162,9 @@ private: #define PTHREAD_COND_MAGIC PTHREAD_MAGIC+5 #define PTHREAD_CONDATTR_MAGIC PTHREAD_MAGIC+6 #define SEM_MAGIC PTHREAD_MAGIC+7 -#define PTHREAD_ONCE_MAGIC PTHREAD_MAGIC+8; +#define PTHREAD_ONCE_MAGIC PTHREAD_MAGIC+8 -#define MUTEX_LOCK_COUNTER_INITIAL (-1) +#define MUTEX_OWNER_ANONYMOUS ((pthread_t) -1) /* verifyable_object should not be defined here - it's a general purpose class */ @@ -304,10 +306,11 @@ public: static bool isGoodInitializer (pthread_mutex_t const *); static bool isGoodInitializerOrObject (pthread_mutex_t const *); static bool isGoodInitializerOrBadObject (pthread_mutex_t const *mutex); + static bool canBeUnlocked (pthread_mutex_t const *mutex); static void initMutex (); static int init (pthread_mutex_t *, const pthread_mutexattr_t *); - LONG lock_counter; + unsigned long lock_counter; HANDLE win32_obj_id; unsigned int recursion_counter; LONG condwaits; @@ -316,12 +319,43 @@ public: int pshared; class pthread_mutex * next; - int Lock (); - int TryLock (); - int UnLock (); - int Destroy (); - void SetOwner (); - int LockRecursive (); + pthread_t GetPthreadSelf () const + { + return PTHREAD_MUTEX_NORMAL == type ? MUTEX_OWNER_ANONYMOUS : + ::pthread_self (); + } + + int Lock () + { + return _Lock (GetPthreadSelf ()); + } + int TryLock () + { + return _TryLock (GetPthreadSelf ()); + } + int UnLock () + { + return _UnLock (GetPthreadSelf ()); + } + int Destroy () + { + return _Destroy (GetPthreadSelf ()); + } + + void SetOwner (pthread_t self) + { + recursion_counter = 1; + owner = self; + } + + int LockRecursive () + { + if (UINT_MAX == recursion_counter) + return EAGAIN; + ++recursion_counter; + return 0; + } + void fixup_after_fork (); pthread_mutex (pthread_mutexattr * = NULL); @@ -329,6 +363,11 @@ public: ~pthread_mutex (); private: + int _Lock (pthread_t self); + int _TryLock (pthread_t self); + int _UnLock (pthread_t self); + int _Destroy (pthread_t self); + static nativeMutex mutexInitializationLock; };