From 28194e813eecd55cbc126f0ffd2a3d28d7b526cb Mon Sep 17 00:00:00 2001 From: Thomas Pfaff Date: Fri, 24 Oct 2003 19:34:47 +0000 Subject: [PATCH] Rename native_mutex to fast_mutex throughout. Rename pthread_key::save_key_to_buffer to pthread_key::_fixup_before_fork throughout. Rename pthread_key::recreate_key_from_buffer to pthread_key::_fixup_after_fork throughout. * thread.cc (native_mutex::init): Remove. (native_mutex::lock): Ditto. (native_mutex::unlock): Ditto. (pthread::push_cleanup_handler): InterlockedExchangePointer is not needed here. (pthread_rwlock::pthread_rwlock): Initialize readers list mutex. (pthread_rwlock::add_reader): Add reader via List_insert. (pthread_rwlock::lookup_reader): Lock list while walking through. (pthread_cond::init): Locking the init mutex is now void. (pthread_rwlock::init): Ditto. (pthread_mutex::init): Ditto. * thread.h: Include security.h. (fast_mutex): New class. Replacement for native_mutex. (List_insert): New template function. (List_remove): Ditto. (List::List): Initialize synchronising mutex. (List::fixup_after_fork): New method. (List::insert): Add node via List_insert. (List::remove): Remove node via List_remove. (List::pop): Remove. (List::for_each): Lock list while walking through. (List::mx_init): New method. (pthread_mutex::fixup_after_fork): Fixup mutex list after fork. (pthread::fixup_after_fork): Ditto. (pthread_conds::fixup_after_fork): Ditto. (pthread_rwlock::fixup_after_fork): Ditto. (semaphore::fixup_after_fork): Ditto. (pthread_rwlock::readers_mx): New member. --- winsup/cygwin/ChangeLog | 37 ++++++++++ winsup/cygwin/thread.cc | 93 +++++++++--------------- winsup/cygwin/thread.h | 156 +++++++++++++++++++++++++++++----------- 3 files changed, 185 insertions(+), 101 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index aea08932e..d7006ec44 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,40 @@ +2003-10-24 Thomas Pfaff + + Rename native_mutex to fast_mutex throughout. + Rename pthread_key::save_key_to_buffer to + pthread_key::_fixup_before_fork throughout. + Rename pthread_key::recreate_key_from_buffer to + pthread_key::_fixup_after_fork throughout. + + * thread.cc (native_mutex::init): Remove. + (native_mutex::lock): Ditto. + (native_mutex::unlock): Ditto. + (pthread::push_cleanup_handler): InterlockedExchangePointer + is not needed here. + (pthread_rwlock::pthread_rwlock): Initialize readers list mutex. + (pthread_rwlock::add_reader): Add reader via List_insert. + (pthread_rwlock::lookup_reader): Lock list while walking through. + (pthread_cond::init): Locking the init mutex is now void. + (pthread_rwlock::init): Ditto. + (pthread_mutex::init): Ditto. + * thread.h: Include security.h. + (fast_mutex): New class. Replacement for native_mutex. + (List_insert): New template function. + (List_remove): Ditto. + (List::List): Initialize synchronising mutex. + (List::fixup_after_fork): New method. + (List::insert): Add node via List_insert. + (List::remove): Remove node via List_remove. + (List::pop): Remove. + (List::for_each): Lock list while walking through. + (List::mx_init): New method. + (pthread_mutex::fixup_after_fork): Fixup mutex list after fork. + (pthread::fixup_after_fork): Ditto. + (pthread_conds::fixup_after_fork): Ditto. + (pthread_rwlock::fixup_after_fork): Ditto. + (semaphore::fixup_after_fork): Ditto. + (pthread_rwlock::readers_mx): New member. + 2003-10-24 Brian Ford * fhandler.cc (fhandler_base::fcntl): Don't clobber O_APPEND when diff --git a/winsup/cygwin/thread.cc b/winsup/cygwin/thread.cc index e10824442..bf5f0da24 100644 --- a/winsup/cygwin/thread.cc +++ b/winsup/cygwin/thread.cc @@ -79,37 +79,6 @@ _reent_winsup () return _r->_winsup; } -bool -native_mutex::init () -{ - theHandle = CreateMutex (&sec_none_nih, FALSE, NULL); - if (!theHandle) - { - debug_printf ("CreateMutex failed. %E"); - return false; - } - return true; -} - -bool -native_mutex::lock () -{ - DWORD waitResult = WaitForSingleObject (theHandle, INFINITE); - if (waitResult != WAIT_OBJECT_0) - { - system_printf ("Received unexpected wait result %d on handle %p, %E", waitResult, theHandle); - return false; - } - return true; -} - -void -native_mutex::unlock () -{ - if (!ReleaseMutex (theHandle)) - system_printf ("Received a unexpected result releasing mutex. %E"); -} - inline LPCRITICAL_SECTION ResourceLocks::Lock (int _resid) { @@ -720,7 +689,7 @@ pthread::push_cleanup_handler (__pthread_cleanup_handler *handler) // TODO: do it? api_fatal ("Attempt to push a cleanup handler across threads"); handler->next = cleanup_stack; - InterlockedExchangePointer (&cleanup_stack, handler); + cleanup_stack = handler; } void @@ -830,7 +799,7 @@ pthread_condattr::~pthread_condattr () List pthread_cond::conds; /* This is used for cond creation protection within a single process only */ -native_mutex NO_COPY pthread_cond::cond_initialization_lock; +fast_mutex NO_COPY pthread_cond::cond_initialization_lock; /* We can only be called once. TODO: (no rush) use a non copied memory section to @@ -1040,7 +1009,7 @@ pthread_rwlockattr::~pthread_rwlockattr () List pthread_rwlock::rwlocks; /* This is used for rwlock creation protection within a single process only */ -native_mutex NO_COPY pthread_rwlock::rwlock_initialization_lock; +fast_mutex NO_COPY pthread_rwlock::rwlock_initialization_lock; /* We can only be called once. TODO: (no rush) use a non copied memory section to @@ -1055,12 +1024,19 @@ pthread_rwlock::init_mutex () pthread_rwlock::pthread_rwlock (pthread_rwlockattr *attr) : verifyable_object (PTHREAD_RWLOCK_MAGIC), shared (0), waiting_readers (0), waiting_writers (0), writer (NULL), - readers (NULL), mtx (NULL), cond_readers (NULL), cond_writers (NULL), + readers (NULL), readers_mx (), mtx (NULL), cond_readers (NULL), cond_writers (NULL), next (NULL) { pthread_mutex *verifyable_mutex_obj = &mtx; pthread_cond *verifyable_cond_obj; + if (!readers_mx.init ()) + { + thread_printf ("Internal rwlock synchronisation mutex is not valid. this %p", this); + magic = 0; + return; + } + if (attr) if (attr->shared != PTHREAD_PROCESS_PRIVATE) { @@ -1265,34 +1241,28 @@ pthread_rwlock::unlock () void pthread_rwlock::add_reader (struct RWLOCK_READER *rd) { - rd->next = (struct RWLOCK_READER *) - InterlockedExchangePointer (&readers, rd); + List_insert (readers_mx, readers, rd); } void pthread_rwlock::remove_reader (struct RWLOCK_READER *rd) { - if (readers == rd) - InterlockedExchangePointer (&readers, rd->next); - else - { - struct RWLOCK_READER *temp = readers; - while (temp->next && temp->next != rd) - temp = temp->next; - /* but there may be a race between the loop above and this statement */ - InterlockedExchangePointer (&temp->next, rd->next); - } + List_remove (readers_mx, readers, rd); } struct pthread_rwlock::RWLOCK_READER * pthread_rwlock::lookup_reader (pthread_t thread) { - struct RWLOCK_READER *temp = readers; + readers_mx.lock (); - while (temp && temp->thread != thread) - temp = temp->next; + struct RWLOCK_READER *cur = readers; - return temp; + while (cur && cur->thread != thread) + cur = cur->next; + + readers_mx.unlock (); + + return cur; } void @@ -1324,6 +1294,9 @@ pthread_rwlock::_fixup_after_fork () waiting_readers = 0; waiting_writers = 0; + if (!readers_mx.init ()) + api_fatal ("pthread_rwlock::_fixup_after_fork () failed to recreate mutex"); + /* Unlock eventually locked mutex */ mtx.unlock (); /* @@ -1395,13 +1368,13 @@ pthread_key::get () const } void -pthread_key::save_key_to_buffer () +pthread_key::_fixup_before_fork () { fork_buf = get (); } void -pthread_key::recreate_key_from_buffer () +pthread_key::_fixup_after_fork () { tls_index = TlsAlloc (); if (tls_index == TLS_OUT_OF_INDEXES) @@ -1496,7 +1469,7 @@ pthread_mutex::can_be_unlocked (pthread_mutex_t const *mutex) List pthread_mutex::mutexes; /* This is used for mutex creation protection within a single process only */ -native_mutex NO_COPY pthread_mutex::mutex_initialization_lock; +fast_mutex NO_COPY pthread_mutex::mutex_initialization_lock; /* We can only be called once. TODO: (no rush) use a non copied memory section to @@ -2452,8 +2425,8 @@ pthread_cond::init (pthread_cond_t *cond, const pthread_condattr_t *attr) { if (attr && !pthread_condattr::is_good_object (attr)) return EINVAL; - if (!cond_initialization_lock.lock ()) - return EINVAL; + + cond_initialization_lock.lock (); if (!is_good_initializer_or_bad_object (cond)) { @@ -2650,8 +2623,8 @@ pthread_rwlock::init (pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr { if (attr && !pthread_rwlockattr::is_good_object (attr)) return EINVAL; - if (!rwlock_initialization_lock.lock ()) - return EINVAL; + + rwlock_initialization_lock.lock (); if (!is_good_initializer_or_bad_object (rwlock)) { @@ -2844,8 +2817,8 @@ pthread_mutex::init (pthread_mutex_t *mutex, { if (attr && !pthread_mutexattr::is_good_object (attr) || check_valid_pointer (mutex)) return EINVAL; - if (!mutex_initialization_lock.lock ()) - return EINVAL; + + mutex_initialization_lock.lock (); if (!is_good_initializer_or_bad_object (mutex)) { diff --git a/winsup/cygwin/thread.h b/winsup/cygwin/thread.h index a52c0b771..575310958 100644 --- a/winsup/cygwin/thread.h +++ b/winsup/cygwin/thread.h @@ -44,6 +44,7 @@ extern "C" #include #include #include +#include #define _NOMNTENT_FUNCS #include @@ -123,14 +124,46 @@ void AssertResourceOwner (int, int); #endif } -class native_mutex +class fast_mutex { public: - bool init (); - bool lock (); - void unlock (); + fast_mutex () : + lock_counter (0), win32_obj_id (0) + { + } + + ~fast_mutex () + { + if(win32_obj_id) + CloseHandle (win32_obj_id); + } + + bool init () + { + win32_obj_id = ::CreateSemaphore (&sec_none_nih, 0, LONG_MAX, NULL); + if (!win32_obj_id) + { + debug_printf ("CreateSemaphore failed. %E"); + return false; + } + return true; + } + + void lock () + { + if (InterlockedIncrement ((long *)&lock_counter) != 1) + WaitForSingleObject (win32_obj_id, INFINITE); + } + + void unlock () + { + if (InterlockedDecrement ((long *)&lock_counter)) + ::ReleaseSemaphore (win32_obj_id, 1, NULL); + } + private: - HANDLE theHandle; + unsigned long lock_counter; + HANDLE win32_obj_id; }; class per_process; @@ -189,51 +222,85 @@ typedef enum verifyable_object_state verifyable_object_isvalid (void const *, long); verifyable_object_state verifyable_object_isvalid (void const *, long, void *); -template class List { -public: +template inline void +List_insert (fast_mutex &mx, list_node *&head, list_node *node) +{ + if (!node) + return; + mx.lock (); + node->next = head; + head = node; + mx.unlock (); +} + +template inline void +List_remove (fast_mutex &mx, list_node *&head, list_node *node) +{ + if (!node) + return; + mx.lock (); + if (node == head) + head = head->next; + else if (head) + { + list_node *cur = head; + + while (cur->next && node != cur->next) + cur = cur->next; + if (node == cur->next) + cur->next = cur->next->next; + } + mx.unlock (); +} + + +template class List +{ + public: List() : head(NULL) { + mx_init (); + } + + ~List() + { + } + + void fixup_after_fork () + { + mx_init (); } void insert (list_node *node) { - if (!node) - return; - node->next = (list_node *) InterlockedExchangePointer (&head, node); + List_insert (mx, head, node); } - list_node *remove ( list_node *node) + void remove (list_node *node) { - if (!node || !head) - return NULL; - if (node == head) - return pop (); - - list_node *result_prev = head; - while (result_prev && result_prev->next && !(node == result_prev->next)) - result_prev = result_prev->next; - if (result_prev) - return (list_node *)InterlockedExchangePointer (&result_prev->next, result_prev->next->next); - return NULL; + List_remove (mx, head, node); } - list_node *pop () - { - return (list_node *) InterlockedExchangePointer (&head, head->next); - } - - /* poor mans generic programming. */ void for_each (void (list_node::*callback) ()) { - list_node *node = head; - while (node) + mx.lock (); + list_node *cur = head; + while (cur) { - (node->*callback) (); - node = node->next; + (cur->*callback) (); + cur = cur->next; } + mx.unlock (); } protected: + void mx_init () + { + if (!mx.init ()) + api_fatal ("Could not create mutex for list synchronisation."); + } + + fast_mutex mx; list_node *head; }; @@ -248,14 +315,15 @@ public: pthread_key (void (*)(void *)); ~pthread_key (); - static void fixup_before_fork() + static void fixup_before_fork () { - keys.for_each (&pthread_key::save_key_to_buffer); + keys.for_each (&pthread_key::_fixup_before_fork); } - static void fixup_after_fork() + static void fixup_after_fork () { - keys.for_each (&pthread_key::recreate_key_from_buffer); + keys.fixup_after_fork (); + keys.for_each (&pthread_key::_fixup_after_fork); } static void run_all_destructors () @@ -267,8 +335,8 @@ public: class pthread_key *next; private: static List keys; - void save_key_to_buffer (); - void recreate_key_from_buffer (); + void _fixup_before_fork (); + void _fixup_after_fork (); void (*destructor) (void *); void run_destructor (); void *fork_buf; @@ -361,6 +429,7 @@ public: class pthread_mutex * next; static void fixup_after_fork () { + mutexes.fixup_after_fork (); mutexes.for_each (&pthread_mutex::_fixup_after_fork); } @@ -373,7 +442,7 @@ private: void _fixup_after_fork (); static List mutexes; - static native_mutex mutex_initialization_lock; + static fast_mutex mutex_initialization_lock; }; #define WAIT_CANCELED (WAIT_OBJECT_0 + 1) @@ -447,6 +516,7 @@ public: class pthread *next; static void fixup_after_fork () { + threads.fixup_after_fork (); threads.for_each (&pthread::_fixup_after_fork); } @@ -533,6 +603,7 @@ public: class pthread_cond * next; static void fixup_after_fork () { + conds.fixup_after_fork (); conds.for_each (&pthread_cond::_fixup_after_fork); } @@ -540,7 +611,7 @@ private: void _fixup_after_fork (); static List conds; - static native_mutex cond_initialization_lock; + static fast_mutex cond_initialization_lock; }; class pthread_rwlockattr:public verifyable_object @@ -573,6 +644,7 @@ public: struct RWLOCK_READER *next; pthread_t thread; } *readers; + fast_mutex readers_mx; int rdlock (); int tryrdlock (); @@ -592,6 +664,7 @@ public: class pthread_rwlock * next; static void fixup_after_fork () { + rwlocks.fixup_after_fork (); rwlocks.for_each (&pthread_rwlock::_fixup_after_fork); } @@ -619,7 +692,7 @@ private: void _fixup_after_fork (); - static native_mutex rwlock_initialization_lock; + static fast_mutex rwlock_initialization_lock; }; class pthread_once @@ -651,6 +724,7 @@ public: class semaphore * next; static void fixup_after_fork () { + semaphores.fixup_after_fork (); semaphores.for_each (&semaphore::_fixup_after_fork); }