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)
{
}