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::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::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::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::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 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 keys; static void saveAKey (pthread_key *); static void restoreAKey (pthread_key *); @@ -232,51 +267,6 @@ private: void *fork_buf; }; -/* implementation */ -template -List::List () : head(NULL) -{ -} -template void -List::Insert (ListNode *aNode) -{ - if (!aNode) - return; - aNode->next = (ListNode *) InterlockedExchangePointer (&head, aNode); -} -template ListNode * -List::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 ListNode * -List::Pop () -{ - return (ListNode *) InterlockedExchangePointer (&head, head->next); -} -/* poor mans generic programming. */ -template void -List::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 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 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 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 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) { }