diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index c74f46fa6..614ad9b9e 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,74 @@ +2003-03-23 Thomas Pfaff + + * thread.h (class List): Move inline code inside class + declaration. + (List::forEach): Change callback parameter to template class + member function pointer. + (pthread_keys::fixup_before_fork): Change to inline. Use + List::forEach to fixup keys. + (pthread_keys::fixup_after_fork): Ditto. + (pthread_keys::runAllDestructors): Ditto. + (pthread_key::saveAKey): Remove. + (pthread_key::restoreAKey): Ditto. + (pthread_key::destroyAKey): Ditto. + (pthread_key::run_destructor): Rename to runDestructor. + (pthread_mutex::fixup_after_fork): Change to inline. Use + List::forEach to fixup mutexes after a fork. + (pthread_mutex::FixupAfterFork): New method. + (pthread_mutex::mutexes): New member. + (pthread_cond::fixup_after_fork): Change to inline. Use + List::forEach to fixup conds after a fork. + (pthread_cond::FixupAfterFork): New method. + (pthread_cond::conds): New member. + (pthread_rwlock::fixup_after_fork): Change to inline. Use + List::forEach to fixup rwlocks after a fork. + (pthread_rwlock::FixupAfterFork): New method. + (pthread_rwlock::rwlocks): New member. + (semaphore::fixup_after_fork): Change to inline. Use + List::forEach to fixup mutexes after a fork. + (semaphore::FixupAfterFork): New method. + (semaphore::semaphores): New member. + (MTinterface::mutexs): Remove. + (MTinterface::conds): Ditto. + (MTinterface::rwlocks): Ditto. + (MTinterface::semaphores): Ditto. + (pthread_equal): Add extern "C". + (pthread_mutex_lock): Ditto. + + * thread.cc (MTinterface::fixup_after_fork): Change + fixup_after_fork calls for pthread objects. + (semaphore::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): Rename 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): Rename to FixupAfterFork. + (pthread_key::saveAKey): Remove. + (pthread_key::fixup_before_fork): Ditto. + (pthread_key::restoreAKey): Ditto. + (pthread_key::fixup_after_fork): Ditto. + (pthread_key::destroyAKey): Ditto. + (pthread_key::runAllDestructors): Ditto. + (pthread_key::run_destructor): Rename to runDestructor. + (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): Rename 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): Rename to FixupAfterFork. + 2003-03-22 Christopher Faylor * pipe.cc (fhandler_pipe::dup): Don't dup input_handle if it doesn't diff --git a/winsup/cygwin/thread.cc b/winsup/cygwin/thread.cc index 56b279662..1c8a876d5 100644 --- a/winsup/cygwin/thread.cc +++ b/winsup/cygwin/thread.cc @@ -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_condattr *attr) : 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 @@ -992,7 +959,7 @@ pthread_cond::Wait (pthread_mutex_t mutex, DWORD dwMilliseconds) } void -pthread_cond::fixup_after_fork () +pthread_cond::FixupAfterFork () { waiting = pending = 0; mtxCond = NULL; @@ -1003,7 +970,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 +990,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 +1047,12 @@ pthread_rwlock::pthread_rwlock (pthread_rwlockattr *attr) : } - /* 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 @@ -1315,7 +1273,7 @@ pthread_rwlock::WrLockCleanup (void *arg) } void -pthread_rwlock::fixup_after_fork () +pthread_rwlock::FixupAfterFork () { pthread_t self = pthread::self (); struct RWLOCK_READER **temp = &readers; @@ -1346,42 +1304,6 @@ pthread_rwlock::fixup_after_fork () /* This stores pthread_key information across fork() boundaries */ List pthread_key::keys; -void -pthread_key::saveAKey (pthread_key *key) -{ - key->saveKeyToBuffer (); -} - -void -pthread_key::fixup_before_fork () -{ - keys.forEach (saveAKey); -} - -void -pthread_key::restoreAKey (pthread_key *key) -{ - key->recreateKeyFromBuffer (); -} - -void -pthread_key::fixup_after_fork () -{ - keys.forEach (restoreAKey); -} - -void -pthread_key::destroyAKey (pthread_key *key) -{ - key->run_destructor (); -} - -void -pthread_key::runAllDestructors () -{ - keys.forEach (destroyAKey); -} - bool pthread_key::isGoodObject (pthread_key_t const *key) { @@ -1445,7 +1367,7 @@ pthread_key::recreateKeyFromBuffer () } void -pthread_key::run_destructor () +pthread_key::runDestructor () { if (destructor) { @@ -1528,6 +1450,8 @@ pthread_mutex::canBeUnlocked (pthread_mutex_t const *mutex) 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 +1491,7 @@ pthread_mutex::pthread_mutex (pthread_mutexattr *attr) : type = attr->mutextype; } - /* threadsafe addition is easy */ - next = (pthread_mutex *) InterlockedExchangePointer (&MT_INTERFACE->mutexs, this); + mutexes.Insert (this); } pthread_mutex::~pthread_mutex () @@ -1576,19 +1499,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 @@ -1665,11 +1576,11 @@ pthread_mutex::_Destroy (pthread_t self) } void -pthread_mutex::fixup_after_fork () +pthread_mutex::FixupAfterFork () { - debug_printf ("mutex %x in fixup_after_fork", this); + 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 +1591,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 +1613,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 +1623,16 @@ semaphore::semaphore (int pshared, unsigned int value):verifyable_object (SEM_MA 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 @@ -1769,9 +1673,9 @@ semaphore::Wait () } void -semaphore::fixup_after_fork () +semaphore::FixupAfterFork () { - debug_printf ("sem %x in fixup_after_fork", this); + 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. */ @@ -2859,7 +2763,7 @@ pthread_sigmask (int operation, const sigset_t *set, sigset_t *old_set) /* ID */ -int +extern "C" int pthread_equal (pthread_t t1, pthread_t t2) { return t1 == t2; @@ -2921,7 +2825,7 @@ pthread_mutex_getprioceiling (const pthread_mutex_t *mutex, return ENOSYS; } -int +extern "C" int pthread_mutex_lock (pthread_mutex_t *mutex) { pthread_mutex_t *themutex = mutex; diff --git a/winsup/cygwin/thread.h b/winsup/cygwin/thread.h index a3418fb4e..cfbd1eee1 100644 --- a/winsup/cygwin/thread.h +++ b/winsup/cygwin/thread.h @@ -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 (ListNode::*callback) ()) + { + ListNode *aNode = head; + while (aNode) + { + (aNode->*callback) (); + aNode = aNode->next; + } + } + protected: ListNode *head; }; @@ -205,8 +241,6 @@ class pthread_key:public verifyable_object { public: static bool isGoodObject (pthread_key_t const *); - static void runAllDestructors (); - DWORD dwTlsIndex; int set (const void *); @@ -214,69 +248,32 @@ public: pthread_key (void (*)(void *)); ~pthread_key (); - static void fixup_before_fork(); - static void fixup_after_fork(); + static void fixup_before_fork() + { + keys.forEach (&pthread_key::saveKeyToBuffer); + } + + static void fixup_after_fork() + { + keys.forEach (&pthread_key::recreateKeyFromBuffer); + } + + static void runAllDestructors () + { + keys.forEach (&pthread_key::runDestructor); + } /* 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 *); - static void destroyAKey (pthread_key *); void saveKeyToBuffer (); void recreateKeyFromBuffer (); void (*destructor) (void *); - void run_destructor (); + void runDestructor (); 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 +316,6 @@ public: pthread_t owner; int type; int pshared; - class pthread_mutex * next; pthread_t GetPthreadSelf () const { @@ -358,18 +354,25 @@ 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 () + { + mutexes.forEach (&pthread_mutex::FixupAfterFork); + } + + void FixupAfterFork (); + private: int _Lock (pthread_t self); int _TryLock (pthread_t self); int _UnLock (pthread_t self); int _Destroy (pthread_t self); + static List mutexes; static nativeMutex mutexInitializationLock; }; @@ -506,16 +509,22 @@ 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 () + { + conds.forEach (&pthread_cond::FixupAfterFork); + } + + void FixupAfterFork (); + private: + static List conds; static nativeMutex condInitializationLock; }; @@ -562,14 +571,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 () + { + rwlocks.forEach (&pthread_rwlock::FixupAfterFork); + } + + void 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 +615,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 () + { + semaphores.forEach (&semaphore::FixupAfterFork); + } + + void FixupAfterFork (); + +private: + static List semaphores; }; class callback @@ -634,12 +658,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 +668,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) { }