Reorganize the list handling of the pthreads objects by using the List
template class and remove a lot of duplicate code.


2002-02-28  Thomas Pfaff  <[EMAIL PROTECTED]>

        * thread.h (class List): Move inline code inside of class
        declaration.
        (pthread_mutex::fixup_after_fork): Declare as static method.
        (pthread_mutex::FixupAfterFork(pthread_mutex*): New static method.
        (pthread_mutex::FixupAfterFork(void): New method.
        (pthread_mutex::mutexes): New static member.
        (pthread_cond::fixup_after_fork): Declare as static method.
        (pthread_cond::FixupAfterFork(pthread_cond*): New static method.
        (pthread_cond::FixupAfterFork(void): New method.
        (pthread_cond::conds): New static member.
        (pthread_rwlock::fixup_after_fork): Declare as static method.
        (pthread_rwlock::FixupAfterFork(pthread_rwlock*): New static
        method.
        (pthread_rwlock::FixupAfterFork(void): New method.
        (pthread_rwlock::rwlocks): New static member.
        (semaphore::fixup_after_fork): Declare as static method.
        (semaphore::FixupAfterFork(semaphore*): New static method.
        (semaphore::FixupAfterFork(void): New method.
        (semaphore::semaphores): New static member.
        (MTinterface::mutexs): Remove.
        (MTinterface::conds): Ditto.
        (MTinterface::rwlocks): Ditto.
        (MTinterface::semaphores): Ditto.
        (MTinterface::MTinterface): Remove initialization of removed
        member variables.
        * thread.cc (MTinterface::fixup_after_fork): Change
        fixup_after_fork for pthread objects.
        (pthread_cond::conds): Instantiate.
        (pthread_cond::pthread_cond): Use List::Insert rather than custom
        list code.
        (pthread_cond::~pthread_cond): Use List::Remove rather than custom
        list code.
        (pthread_cond::fixup:after_fork): Implement.
        (pthread_cond::FixupAfterFork): Rename old fixup_after_fork
        to FixupAfterFork.
        (pthread_rwlock::rwlocks): Instantiate.
        (pthread_rwlock::pthread_crwlock): Use List::Insert rather than
        custom list code.
        (pthread_rwlock::~pthread_rwlock): Use List::Remove rather than
        custom list code.
        (pthread_rwlock::fixup:after_fork): Implement.
        (pthread_rwlock::FixupAfterFork): Rename old fixup_after_fork
        to FixupAfterFork.
        (pthread_mutex::mutexes): Instantiate.
        (pthread_mutex::pthread_mutex): Use List::Insert rather than
        custom list code.
        (pthread_mutex::~pthread_mutex): Use List::Remove rather than
        custom list code.
        (pthread_mutex::fixup:after_fork): Implement.
        (pthread_mutex::FixupAfterFork): Rename old fixup_after_fork
        to FixupAfterFork.
        (semaphore::conds): Instantiate.
        (semaphore::semaphore): Use List::Insert rather than custom list
        code.
        (semaphores::~semaphore): Use List::Remove rather than custom list
        code.
        (semaphore::fixup:after_fork): Implement.
        (semaphore::FixupAfterFork): Rename old fixup_after_fork to
        FixupAfterFork.



diff -urp src.old/winsup/cygwin/thread.cc src/winsup/cygwin/thread.cc
--- src.old/winsup/cygwin/thread.cc     2003-02-28 11:33:10.000000000 +0100
+++ src/winsup/cygwin/thread.cc 2003-02-28 10:54:17.000000000 +0100
@@ -217,34 +217,10 @@ MTinterface::fixup_after_fork (void)
   threadcount = 1;
   pthread::initMainThread (true);
 
-  pthread_mutex *mutex = mutexs;
-  debug_printf ("mutexs is %x",mutexs);
-  while (mutex)
-    {
-      mutex->fixup_after_fork ();
-      mutex = mutex->next;
-    }
-  pthread_cond *cond = conds;
-  debug_printf ("conds is %x",conds);
-  while (cond)
-    {
-      cond->fixup_after_fork ();
-      cond = cond->next;
-    }
-  pthread_rwlock *rwlock = rwlocks;
-  debug_printf ("rwlocks is %x",rwlocks);
-  while (rwlock)
-    {
-      rwlock->fixup_after_fork ();
-      rwlock = rwlock->next;
-    }
-  semaphore *sem = semaphores;
-  debug_printf ("semaphores is %x",semaphores);
-  while (sem)
-    {
-      sem->fixup_after_fork ();
-      sem = sem->next;
-    }
+  pthread_mutex::fixup_after_fork ();
+  pthread_cond::fixup_after_fork ();
+  pthread_rwlock::fixup_after_fork ();
+  semaphore::fixup_after_fork ();
 }
 
 /* pthread calls */
@@ -807,6 +783,8 @@ pthread_condattr::~pthread_condattr ()
 {
 }
 
+List<pthread_cond> pthread_cond::conds;
+
 /* This is used for cond creation protection within a single process only */
 nativeMutex NO_COPY pthread_cond::condInitializationLock;
 
@@ -862,8 +840,7 @@ pthread_cond::pthread_cond (pthread_cond
       return;
     }
 
-  /* threadsafe addition is easy */
-  next = (pthread_cond *) InterlockedExchangePointer (&MT_INTERFACE->conds, this);
+  conds.Insert (this);
 }
 
 pthread_cond::~pthread_cond ()
@@ -871,17 +848,7 @@ pthread_cond::~pthread_cond ()
   if (semWait)
     CloseHandle (semWait);
 
-  /* I'm not 100% sure the next bit is threadsafe. I think it is... */
-  if (MT_INTERFACE->conds == this)
-    InterlockedExchangePointer (&MT_INTERFACE->conds, this->next);
-  else
-    {
-      pthread_cond *tempcond = MT_INTERFACE->conds;
-      while (tempcond->next && tempcond->next != this)
-       tempcond = tempcond->next;
-      /* but there may be a race between the loop above and this statement */
-      InterlockedExchangePointer (&tempcond->next, this->next);
-    }
+  conds.Remove (this);
 }
 
 void
@@ -994,6 +961,12 @@ pthread_cond::Wait (pthread_mutex_t mute
 void
 pthread_cond::fixup_after_fork ()
 {
+  conds.forEach (FixupAfterFork);
+}
+
+void
+pthread_cond::FixupAfterFork ()
+{
   waiting = pending = 0;
   mtxCond = NULL;
 
@@ -1003,7 +976,7 @@ pthread_cond::fixup_after_fork ()
 
   semWait = ::CreateSemaphore (&sec_none_nih, 0, LONG_MAX, NULL);
   if (!semWait)
-    api_fatal ("pthread_cond::fixup_after_fork () failed to recreate win32 
semaphore");
+    api_fatal ("pthread_cond::FixupAfterFork () failed to recreate win32 semaphore");
 }
 
 bool
@@ -1023,6 +996,8 @@ pthread_rwlockattr::~pthread_rwlockattr 
 {
 }
 
+List<pthread_rwlock> pthread_rwlock::rwlocks;
+
 /* This is used for rwlock creation protection within a single process only */
 nativeMutex NO_COPY pthread_rwlock::rwlockInitializationLock;
 
@@ -1078,23 +1053,12 @@ pthread_rwlock::pthread_rwlock (pthread_
     }
 
 
-  /* threadsafe addition is easy */
-  next = (pthread_rwlock *) InterlockedExchangePointer (&MT_INTERFACE->rwlocks, this);
+  rwlocks.Insert (this);
 }
 
 pthread_rwlock::~pthread_rwlock ()
 {
-  /* I'm not 100% sure the next bit is threadsafe. I think it is... */
-  if (MT_INTERFACE->rwlocks == this)
-    InterlockedExchangePointer (&MT_INTERFACE->rwlocks, this->next);
-  else
-    {
-      pthread_rwlock *temprwlock = MT_INTERFACE->rwlocks;
-      while (temprwlock->next && temprwlock->next != this)
-       temprwlock = temprwlock->next;
-      /* but there may be a race between the loop above and this statement */
-      InterlockedExchangePointer (&temprwlock->next, this->next);
-    }
+  rwlocks.Remove (this);
 }
 
 int
@@ -1317,6 +1281,12 @@ pthread_rwlock::WrLockCleanup (void *arg
 void
 pthread_rwlock::fixup_after_fork ()
 {
+  rwlocks.forEach (FixupAfterFork);
+}
+
+void
+pthread_rwlock::FixupAfterFork ()
+{
   pthread_t self = pthread::self ();
   struct RWLOCK_READER **temp = &readers;
 
@@ -1528,6 +1498,8 @@ pthread_mutex::canBeUnlocked (pthread_mu
   return (__pthread_equal (&(*mutex)->owner, &self)) && 1 == 
(*mutex)->recursion_counter;
 }
 
+List<pthread_mutex> pthread_mutex::mutexes;
+
 /* This is used for mutex creation protection within a single process only */
 nativeMutex NO_COPY pthread_mutex::mutexInitializationLock;
 
@@ -1567,8 +1539,7 @@ pthread_mutex::pthread_mutex (pthread_mu
       type = attr->mutextype;
     }
 
-  /* threadsafe addition is easy */
-  next = (pthread_mutex *) InterlockedExchangePointer (&MT_INTERFACE->mutexs, this);
+  mutexes.Insert (this);
 }
 
 pthread_mutex::~pthread_mutex ()
@@ -1576,19 +1547,7 @@ pthread_mutex::~pthread_mutex ()
   if (win32_obj_id)
     CloseHandle (win32_obj_id);
 
-  /* I'm not 100% sure the next bit is threadsafe. I think it is... */
-  if (MT_INTERFACE->mutexs == this)
-    /* TODO: printf an error if the return value != this */
-    InterlockedExchangePointer (&MT_INTERFACE->mutexs, next);
-  else
-    {
-      pthread_mutex *tempmutex = MT_INTERFACE->mutexs;
-      while (tempmutex->next && tempmutex->next != this)
-       tempmutex = tempmutex->next;
-      /* but there may be a race between the loop above and this statement */
-      /* TODO: printf an error if the return value != this */
-      InterlockedExchangePointer (&tempmutex->next, this->next);
-    }
+  mutexes.Remove (this);
 }
 
 int
@@ -1667,9 +1626,15 @@ pthread_mutex::_Destroy (pthread_t self)
 void
 pthread_mutex::fixup_after_fork ()
 {
-  debug_printf ("mutex %x in fixup_after_fork", this);
+  mutexes.forEach (FixupAfterFork);
+}
+
+void
+pthread_mutex::FixupAfterFork ()
+{
+  debug_printf ("mutex %x in FixupAfterFork", this);
   if (pshared != PTHREAD_PROCESS_PRIVATE)
-    api_fatal ("pthread_mutex::fixup_after_fork () doesn'tunderstand PROCESS_SHARED 
mutex's");
+    api_fatal ("pthread_mutex::FixupAfterFork () doesn'tunderstand PROCESS_SHARED 
mutex's");
 
   if (NULL == owner)
     /* mutex has no owner, reset to initial */
@@ -1680,7 +1645,7 @@ pthread_mutex::fixup_after_fork ()
 
   win32_obj_id = ::CreateSemaphore (&sec_none_nih, 0, LONG_MAX, NULL);
   if (!win32_obj_id)
-    api_fatal ("pthread_mutex::fixup_after_fork () failed to recreate win32 semaphore 
for mutex");
+    api_fatal ("pthread_mutex::FixupAfterFork () failed to recreate win32 semaphore 
for mutex");
 
   condwaits = 0;
 }
@@ -1702,6 +1667,8 @@ pthread_mutexattr::~pthread_mutexattr ()
 {
 }
 
+List<semaphore> semaphore::semaphores;
+
 semaphore::semaphore (int pshared, unsigned int value):verifyable_object (SEM_MAGIC)
 {
   this->win32_obj_id = ::CreateSemaphore (&sec_none_nih, value, LONG_MAX,
@@ -1710,25 +1677,16 @@ semaphore::semaphore (int pshared, unsig
     magic = 0;
   this->shared = pshared;
   currentvalue = value;
-  /* threadsafe addition is easy */
-  next = (semaphore *) InterlockedExchangePointer (&MT_INTERFACE->semaphores, this);
+
+  semaphores.Insert (this);
 }
 
 semaphore::~semaphore ()
 {
   if (win32_obj_id)
     CloseHandle (win32_obj_id);
-  /* I'm not 100% sure the next bit is threadsafe. I think it is... */
-  if (MT_INTERFACE->semaphores == this)
-    InterlockedExchangePointer (&MT_INTERFACE->semaphores, this->next);
-  else
-    {
-      semaphore *tempsem = MT_INTERFACE->semaphores;
-      while (tempsem->next && tempsem->next != this)
-       tempsem = tempsem->next;
-      /* but there may be a race between the loop above and this statement */
-      InterlockedExchangePointer (&tempsem->next, this->next);
-    }
+
+  semaphores.Remove (this);
 }
 
 void
@@ -1771,7 +1729,13 @@ semaphore::Wait ()
 void
 semaphore::fixup_after_fork ()
 {
-  debug_printf ("sem %x in fixup_after_fork", this);
+  semaphores.forEach (FixupAfterFork);
+}
+
+void
+semaphore::FixupAfterFork ()
+{
+  debug_printf ("sem %x in FixupAfterFork", this);
   if (shared != PTHREAD_PROCESS_PRIVATE)
     api_fatal ("doesn't understand PROCESS_SHARED semaphores variables");
   /* FIXME: duplicate code here and in the constructor. */
diff -urp src.old/winsup/cygwin/thread.h src/winsup/cygwin/thread.h
--- src.old/winsup/cygwin/thread.h      2003-02-28 11:33:10.000000000 +0100
+++ src/winsup/cygwin/thread.h  2003-02-28 11:34:23.000000000 +0100
@@ -189,14 +189,50 @@ typedef enum
 verifyable_object_state verifyable_object_isvalid (void const *, long);
 verifyable_object_state verifyable_object_isvalid (void const *, long, void *);
 
-/* interface */
 template <class ListNode> class List {
 public:
-  List();
-  void Insert (ListNode *aNode);
-  ListNode *Remove ( ListNode *aNode);
-  ListNode *Pop ();
-  void forEach (void (*)(ListNode *aNode));
+  List() : head(NULL)
+    {
+    }
+
+  void Insert (ListNode *aNode)
+    {
+      if (!aNode)
+        return;
+      aNode->next = (ListNode *) InterlockedExchangePointer (&head, aNode);
+    }
+
+  ListNode *Remove ( ListNode *aNode)
+    {
+      if (!aNode || !head)
+        return NULL;
+      if (aNode == head)
+        return Pop ();
+
+      ListNode *resultPrev = head;
+      while (resultPrev && resultPrev->next && !(aNode == resultPrev->next))
+        resultPrev = resultPrev->next;
+      if (resultPrev)
+        return (ListNode *)InterlockedExchangePointer (&resultPrev->next, 
resultPrev->next->next);
+      return NULL;
+    }
+
+  ListNode *Pop ()
+    {
+      return (ListNode *) InterlockedExchangePointer (&head, head->next);
+    }
+
+  /* poor mans generic programming. */
+  void forEach (void (*callback)(ListNode *aNode))
+    {
+      ListNode *aNode = head;
+      while (aNode)
+        {
+          callback (aNode);
+          aNode = aNode->next;
+        }
+    }
+
 protected:
   ListNode *head;
 };
@@ -220,7 +256,6 @@ public:
   /* List support calls */
   class pthread_key *next;
 private:
-  // lists of objects. USE THREADSAFE INSERTS AND DELETES.
   static List<pthread_key> keys;
   static void saveAKey (pthread_key *);
   static void restoreAKey (pthread_key *);
@@ -232,51 +267,6 @@ private:
   void *fork_buf;
 };
 
-/* implementation */
-template <class ListNode>
-List<ListNode>::List<ListNode> () : head(NULL)
-{
-}
-template <class ListNode> void
-List<ListNode>::Insert (ListNode *aNode)
-{
-  if (!aNode)
-  return;
-  aNode->next = (ListNode *) InterlockedExchangePointer (&head, aNode);
-}
-template <class ListNode> ListNode *
-List<ListNode>::Remove ( ListNode *aNode)
-{
-  if (!aNode)
-  return NULL;
-  if (!head)
-  return NULL;
-  if (aNode == head)
-  return Pop ();
-  ListNode *resultPrev = head;
-  while (resultPrev && resultPrev->next && !(aNode == resultPrev->next))
-  resultPrev = resultPrev->next;
-  if (resultPrev)
-  return (ListNode *)InterlockedExchangePointer (&resultPrev->next, 
resultPrev->next->next);
-  return NULL;
-}
-template <class ListNode> ListNode *
-List<ListNode>::Pop ()
-{
-  return (ListNode *) InterlockedExchangePointer (&head, head->next);
-}
-/* poor mans generic programming. */
-template <class ListNode> void
-List<ListNode>::forEach (void (*callback)(ListNode *))
-{
-  ListNode *aNode = head;
-  while (aNode)
-  {
-    callback (aNode);
-    aNode = aNode->next;
-  }
-}
-
 class pthread_attr:public verifyable_object
 {
 public:
@@ -319,7 +309,6 @@ public:
   pthread_t owner;
   int type;
   int pshared;
-  class pthread_mutex * next;
 
   int _Lock (pthread_t self);
   int _TryLock (pthread_t self);
@@ -363,13 +352,21 @@ public:
       return 0;
     }
 
-  void fixup_after_fork ();
-
   pthread_mutex (pthread_mutexattr * = NULL);
   pthread_mutex (pthread_mutex_t *, pthread_mutexattr *);
   ~pthread_mutex ();
 
+  class pthread_mutex * next;
+  static void fixup_after_fork ();
+
+  void FixupAfterFork ();
+  static void FixupAfterFork (pthread_mutex *mutex)
+    {
+      mutex->FixupAfterFork ();
+    }
+
 private:
+  static List<pthread_mutex> mutexes;
   static nativeMutex mutexInitializationLock;
 };
 
@@ -506,16 +503,23 @@ public:
 
   pthread_mutex_t mtxCond;
 
-  class pthread_cond * next;
-
   void UnBlock (const bool all);
   int Wait (pthread_mutex_t mutex, DWORD dwMilliseconds = INFINITE);
-  void fixup_after_fork ();
 
   pthread_cond (pthread_condattr *);
   ~pthread_cond ();
 
+  class pthread_cond * next;
+  static void fixup_after_fork ();
+
+  void FixupAfterFork ();
+  static void FixupAfterFork (pthread_cond *cond)
+    {
+      cond->FixupAfterFork ();
+    }
+
 private:
+  static List<pthread_cond> conds;
   static nativeMutex condInitializationLock;
 };
 
@@ -562,14 +566,20 @@ public:
   pthread_cond condReaders;
   pthread_cond condWriters;
 
-  class pthread_rwlock * next;
-
-  void fixup_after_fork ();
-
   pthread_rwlock (pthread_rwlockattr *);
   ~pthread_rwlock ();
 
+  class pthread_rwlock * next;
+  static void fixup_after_fork ();
+
+  void FixupAfterFork ();
+  static void FixupAfterFork (pthread_rwlock *rwlock)
+    {
+      rwlock->FixupAfterFork ();
+    }
 private:
+  static List<pthread_rwlock> rwlocks;
+
   void addReader (struct RWLOCK_READER *rd);
   void removeReader (struct RWLOCK_READER *rd);
   struct RWLOCK_READER *lookupReader (pthread_t thread);
@@ -600,16 +610,25 @@ public:
   static int post (sem_t * sem);
 
   HANDLE win32_obj_id;
-  class semaphore * next;
   int shared;
   long currentvalue;
   void Wait ();
   void Post ();
   int TryWait ();
-  void fixup_after_fork ();
 
   semaphore (int, unsigned int);
   ~semaphore ();
+
+  class semaphore * next;
+  static void fixup_after_fork ();
+
+  void FixupAfterFork ();
+  static void FixupAfterFork (semaphore *sema)
+    {
+      sema->FixupAfterFork ();
+    }
+private:
+  static List<semaphore> semaphores;
 };
 
 class callback
@@ -634,12 +653,6 @@ public:
   callback *pthread_child;
   callback *pthread_parent;
 
-  // lists of pthread objects. USE THREADSAFE INSERTS AND DELETES.
-  class pthread_mutex * mutexs;
-  class pthread_cond  * conds;
-  class pthread_rwlock * rwlocks;
-  class semaphore     * semaphores;
-
   pthread_key reent_key;
   pthread_key thread_self_key;
 
@@ -650,7 +663,6 @@ public:
   MTinterface () :
     concurrency (0), threadcount (1),
     pthread_prepare (NULL), pthread_child (NULL), pthread_parent (NULL),
-    mutexs (NULL), conds (NULL), rwlocks (NULL), semaphores (NULL),
     reent_key (NULL), thread_self_key (NULL)
   {
   }

Reply via email to