This patch adds support for PTHREAD_MUTEX_NORMAL (fast and
deadlocking) mutexes and slightly modifies the lock counter logic.
The counter now start at 0.

Attached are also additional testcases for the MUTEX_NORMAL type.

2002-03-27  Thomas Pfaff  <[EMAIL PROTECTED]>

        * 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::_Lock): New method.
        (pthread_mutex::_TryLock): New method.
        (pthread_mutex::_UnLock): New method.
        (pthread_mutex::_Destroy): New method.
        (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.

Attachment: mutexn.tar.gz
Description: GNU Zip compressed data

diff -urp src.old/winsup/cygwin/include/pthread.h src/winsup/cygwin/include/pthread.h
--- src.old/winsup/cygwin/include/pthread.h     2003-02-27 09:14:21.000000000 +0100
+++ src/winsup/cygwin/include/pthread.h 2003-02-27 09:20:24.000000000 +0100
@@ -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 -urp src.old/winsup/cygwin/thread.cc src/winsup/cygwin/thread.cc
--- src.old/winsup/cygwin/thread.cc     2003-02-27 09:14:21.000000000 +0100
+++ src/winsup/cygwin/thread.cc 2003-02-27 09:23:10.000000000 +0100
@@ -32,7 +32,6 @@ details. */
 #ifdef _MT_SAFE
 #include "winsup.h"
 #include <limits.h>
-#include <errno.h>
 #include "cygerrno.h"
 #include <assert.h>
 #include <stdlib.h>
@@ -328,6 +327,8 @@ pthread::precreate (pthread_attr *newatt
       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::isGoodInitializerOrBadObj
   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)
@@ -1300,22 +1308,6 @@ pthread_mutex::Destroy ()
 }
 
 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 ()
 {
   debug_printf ("mutex %x in fixup_after_fork", this);
@@ -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_mut
     {
     case PTHREAD_MUTEX_ERRORCHECK:
     case PTHREAD_MUTEX_RECURSIVE:
+    case PTHREAD_MUTEX_NORMAL:
       (*attr)->mutextype = type;
       break;
     default:
diff -urp src.old/winsup/cygwin/thread.h src/winsup/cygwin/thread.h
--- src.old/winsup/cygwin/thread.h      2003-02-27 09:14:21.000000000 +0100
+++ src/winsup/cygwin/thread.h  2003-02-27 09:20:24.000000000 +0100
@@ -39,6 +39,8 @@ extern "C"
 #else
 
 #include <pthread.h>
+#include <limits.h>
+#include <errno.h>
 #include <signal.h>
 #include <pwd.h>
 #include <grp.h>
@@ -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,48 @@ public:
   int pshared;
   class pthread_mutex * next;
 
-  int Lock ();
-  int TryLock ();
-  int UnLock ();
-  int Destroy ();
-  void SetOwner ();
-  int LockRecursive ();
+  int _Lock (pthread_t self);
+  int _TryLock (pthread_t self);
+  int _UnLock (pthread_t self);
+  int _Destroy (pthread_t self);
+
+  pthread_t GetPthreadSelf ()
+    {
+      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);

Reply via email to