diff -urp cygwin.org/include/pthread.h cygwin/include/pthread.h --- cygwin.org/include/pthread.h 2004-02-19 08:39:17.438017600 +0100 +++ cygwin/include/pthread.h 2004-02-19 08:44:38.890243200 +0100 @@ -55,7 +55,10 @@ extern "C" #define PTHREAD_MUTEX_NORMAL 2 #define PTHREAD_MUTEX_DEFAULT PTHREAD_MUTEX_ERRORCHECK /* this should be too low to ever be a valid address */ -#define PTHREAD_MUTEX_INITIALIZER (pthread_mutex_t)20 +#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP (pthread_mutex_t)18 +#define PTHREAD_NORMAL_MUTEX_INITIALIZER_NP (pthread_mutex_t)19 +#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP (pthread_mutex_t)20 +#define PTHREAD_MUTEX_INITIALIZER PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP #define PTHREAD_ONCE_INIT { PTHREAD_MUTEX_INITIALIZER, 0 } #define PTHREAD_PRIO_INHERIT #define PTHREAD_PRIO_NONE diff -urp cygwin.org/thread.cc cygwin/thread.cc --- cygwin.org/thread.cc 2004-02-19 08:38:58.490772800 +0100 +++ cygwin/thread.cc 2004-02-19 08:44:38.970358400 +0100 @@ -1354,7 +1354,10 @@ pthread_mutex::is_good_object (pthread_m bool pthread_mutex::is_good_initializer (pthread_mutex_t const *mutex) { - if (verifyable_object_isvalid (mutex, PTHREAD_MUTEX_MAGIC, PTHREAD_MUTEX_INITIALIZER) != VALID_STATIC_OBJECT) + if (verifyable_object_isvalid (mutex, PTHREAD_MUTEX_MAGIC, + PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP, + PTHREAD_NORMAL_MUTEX_INITIALIZER_NP, + PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP) != VALID_STATIC_OBJECT) return false; return true; } @@ -1362,7 +1365,10 @@ pthread_mutex::is_good_initializer (pthr bool pthread_mutex::is_good_initializer_or_object (pthread_mutex_t const *mutex) { - if (verifyable_object_isvalid (mutex, PTHREAD_MUTEX_MAGIC, PTHREAD_MUTEX_INITIALIZER) == INVALID_OBJECT) + if (verifyable_object_isvalid (mutex, PTHREAD_MUTEX_MAGIC, + PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP, + PTHREAD_NORMAL_MUTEX_INITIALIZER_NP, + PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP) == INVALID_OBJECT) return false; return true; } @@ -1370,9 +1376,11 @@ pthread_mutex::is_good_initializer_or_ob bool pthread_mutex::is_good_initializer_or_bad_object (pthread_mutex_t const *mutex) { - verifyable_object_state objectState = verifyable_object_isvalid (mutex, PTHREAD_MUTEX_MAGIC, PTHREAD_MUTEX_INITIALIZER); - if (objectState == VALID_OBJECT) - return false; + if (verifyable_object_isvalid (mutex, PTHREAD_MUTEX_MAGIC, + PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP, + PTHREAD_NORMAL_MUTEX_INITIALIZER_NP, + PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP) == VALID_OBJECT) + return false; return true; } @@ -1756,12 +1764,15 @@ check_valid_pointer (void const *pointer } verifyable_object_state -verifyable_object_isvalid (void const * objectptr, long magic, void *static_ptr) +verifyable_object_isvalid (void const * objectptr, long magic, void *static_ptr1, + void *static_ptr2, void *static_ptr3) { verifyable_object **object = (verifyable_object **)objectptr; if (check_valid_pointer (object)) return INVALID_OBJECT; - if (static_ptr && *object == static_ptr) + if ((static_ptr1 && *object == static_ptr1) || + (static_ptr2 && *object == static_ptr2) || + (static_ptr3 && *object == static_ptr3)) return VALID_STATIC_OBJECT; if (!*object) return INVALID_OBJECT; @@ -1772,12 +1783,6 @@ verifyable_object_isvalid (void const * return VALID_OBJECT; } -verifyable_object_state -verifyable_object_isvalid (void const * objectptr, long magic) -{ - return verifyable_object_isvalid (objectptr, magic, NULL); -} - DWORD WINAPI pthread::thread_init_wrapper (void *arg) { @@ -2371,9 +2376,8 @@ pthread_cond::is_good_initializer_or_obj bool pthread_cond::is_good_initializer_or_bad_object (pthread_cond_t const *cond) { - verifyable_object_state objectState = verifyable_object_isvalid (cond, PTHREAD_COND_MAGIC, PTHREAD_COND_INITIALIZER); - if (objectState == VALID_OBJECT) - return false; + if (verifyable_object_isvalid (cond, PTHREAD_COND_MAGIC, PTHREAD_COND_INITIALIZER) == VALID_OBJECT) + return false; return true; } @@ -2398,6 +2402,9 @@ pthread_cond_destroy (pthread_cond_t *co int pthread_cond::init (pthread_cond_t *cond, const pthread_condattr_t *attr) { + + pthread_cond_t new_cond; + if (attr && !pthread_condattr::is_good_object (attr)) return EINVAL; @@ -2409,15 +2416,17 @@ pthread_cond::init (pthread_cond_t *cond return EBUSY; } - *cond = new pthread_cond (attr ? (*attr) : NULL); - if (!is_good_object (cond)) + new_cond = new pthread_cond (attr ? (*attr) : NULL); + if (!is_good_object (&new_cond)) { - delete (*cond); - *cond = NULL; + delete new_cond; cond_initialization_lock.unlock (); return EAGAIN; } + + *cond = new_cond; cond_initialization_lock.unlock (); + return 0; } @@ -2569,9 +2578,8 @@ pthread_rwlock::is_good_initializer_or_o bool pthread_rwlock::is_good_initializer_or_bad_object (pthread_rwlock_t const *rwlock) { - verifyable_object_state objectState = verifyable_object_isvalid (rwlock, PTHREAD_RWLOCK_MAGIC, PTHREAD_RWLOCK_INITIALIZER); - if (objectState == VALID_OBJECT) - return false; + if (verifyable_object_isvalid (rwlock, PTHREAD_RWLOCK_MAGIC, PTHREAD_RWLOCK_INITIALIZER) == VALID_OBJECT) + return false; return true; } @@ -2596,6 +2604,8 @@ pthread_rwlock_destroy (pthread_rwlock_t int pthread_rwlock::init (pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr) { + pthread_rwlock_t new_rwlock; + if (attr && !pthread_rwlockattr::is_good_object (attr)) return EINVAL; @@ -2607,15 +2617,17 @@ pthread_rwlock::init (pthread_rwlock_t * return EBUSY; } - *rwlock = new pthread_rwlock (attr ? (*attr) : NULL); - if (!is_good_object (rwlock)) + new_rwlock = new pthread_rwlock (attr ? (*attr) : NULL); + if (!is_good_object (&new_rwlock)) { - delete (*rwlock); - *rwlock = NULL; + delete new_rwlock; rwlock_initialization_lock.unlock (); return EAGAIN; } + + *rwlock = new_rwlock; rwlock_initialization_lock.unlock (); + return 0; } @@ -2764,18 +2776,13 @@ pthread_equal (pthread_t t1, pthread_t t /* Mutexes */ -/* FIXME: there's a potential race with PTHREAD_MUTEX_INITALIZER: - the mutex is not actually inited until the first use. - So two threads trying to lock/trylock may collide. - Solution: we need a global mutex on mutex creation, or possibly simply - on all constructors that allow INITIALIZER macros. - the lock should be very small: only around the init routine, not - every test, or all mutex access will be synchronised. */ - int pthread_mutex::init (pthread_mutex_t *mutex, - const pthread_mutexattr_t *attr) + const pthread_mutexattr_t *attr, + const pthread_mutex_t initializer) { + pthread_mutex_t new_mutex; + if (attr && !pthread_mutexattr::is_good_object (attr) || check_valid_pointer (mutex)) return EINVAL; @@ -2787,15 +2794,27 @@ pthread_mutex::init (pthread_mutex_t *mu return EBUSY; } - *mutex = new pthread_mutex (attr ? (*attr) : NULL); - if (!is_good_object (mutex)) + new_mutex = new pthread_mutex (attr ? (*attr) : NULL); + if (!is_good_object (&new_mutex)) { - delete (*mutex); - *mutex = NULL; + delete new_mutex; mutex_initialization_lock.unlock (); return EAGAIN; } + + if (!attr && initializer) + { + if (initializer == PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP) + new_mutex->type = PTHREAD_MUTEX_RECURSIVE; + else if (initializer == PTHREAD_NORMAL_MUTEX_INITIALIZER_NP) + new_mutex->type = PTHREAD_MUTEX_NORMAL; + else if (initializer == PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP) + new_mutex->type = PTHREAD_MUTEX_ERRORCHECK; + } + + *mutex = new_mutex; mutex_initialization_lock.unlock (); + return 0; } @@ -2803,11 +2822,6 @@ extern "C" int pthread_mutex_getprioceiling (const pthread_mutex_t *mutex, int *prioceiling) { - pthread_mutex_t *themutex = (pthread_mutex_t *) mutex; - if (pthread_mutex::is_good_initializer (mutex)) - pthread_mutex::init ((pthread_mutex_t *) mutex, NULL); - if (!pthread_mutex::is_good_object (themutex)) - return EINVAL; /* We don't define _POSIX_THREAD_PRIO_PROTECT because we do't currently support mutex priorities. @@ -2821,47 +2835,28 @@ pthread_mutex_getprioceiling (const pthr extern "C" int pthread_mutex_lock (pthread_mutex_t *mutex) { - pthread_mutex_t *themutex = mutex; - /* This could be simplified via is_good_initializer_or_object - and is_good_initializer, but in a performance critical call like this.... - no. */ - switch (verifyable_object_isvalid (themutex, PTHREAD_MUTEX_MAGIC, PTHREAD_MUTEX_INITIALIZER)) - { - case INVALID_OBJECT: - return EINVAL; - break; - case VALID_STATIC_OBJECT: - if (pthread_mutex::is_good_initializer (mutex)) - { - int rv = pthread_mutex::init (mutex, NULL); - if (rv && rv != EBUSY) - return rv; - } - /* No else needed. If it's been initialized while we waited, - we can just attempt to lock it */ - break; - case VALID_OBJECT: - break; - } - return (*themutex)->lock (); + if (pthread_mutex::is_good_initializer (mutex)) + pthread_mutex::init (mutex, NULL, *mutex); + if (!pthread_mutex::is_good_object (mutex)) + return EINVAL; + return (*mutex)->lock (); } extern "C" int pthread_mutex_trylock (pthread_mutex_t *mutex) { - pthread_mutex_t *themutex = mutex; if (pthread_mutex::is_good_initializer (mutex)) - pthread_mutex::init (mutex, NULL); - if (!pthread_mutex::is_good_object (themutex)) + pthread_mutex::init (mutex, NULL, *mutex); + if (!pthread_mutex::is_good_object (mutex)) return EINVAL; - return (*themutex)->trylock (); + return (*mutex)->trylock (); } extern "C" int pthread_mutex_unlock (pthread_mutex_t *mutex) { if (pthread_mutex::is_good_initializer (mutex)) - pthread_mutex::init (mutex, NULL); + return EPERM; if (!pthread_mutex::is_good_object (mutex)) return EINVAL; return (*mutex)->unlock (); @@ -2889,11 +2884,6 @@ extern "C" int pthread_mutex_setprioceiling (pthread_mutex_t *mutex, int prioceiling, int *old_ceiling) { - pthread_mutex_t *themutex = mutex; - if (pthread_mutex::is_good_initializer (mutex)) - pthread_mutex::init (mutex, NULL); - if (!pthread_mutex::is_good_object (themutex)) - return EINVAL; return ENOSYS; } diff -urp cygwin.org/thread.h cygwin/thread.h --- cygwin.org/thread.h 2004-02-19 08:38:33.875377600 +0100 +++ cygwin/thread.h 2004-02-19 08:44:39.110560000 +0100 @@ -120,8 +120,10 @@ typedef enum VALID_STATIC_OBJECT } verifyable_object_state; -verifyable_object_state verifyable_object_isvalid (void const *, long); -verifyable_object_state verifyable_object_isvalid (void const *, long, void *); +verifyable_object_state verifyable_object_isvalid (void const * objectptr, long magic, + void *static_ptr1 = NULL, + void *static_ptr2 = NULL, + void *static_ptr3 = NULL); template inline void List_insert (list_node *&head, list_node *node) @@ -276,7 +278,8 @@ public: static bool is_good_initializer_or_bad_object (pthread_mutex_t const *mutex); static bool can_be_unlocked (pthread_mutex_t const *mutex); static void init_mutex (); - static int init (pthread_mutex_t *, const pthread_mutexattr_t *); + static int init (pthread_mutex_t *mutex, const pthread_mutexattr_t *attr, + const pthread_mutex_t initializer = NULL); unsigned long lock_counter; HANDLE win32_obj_id;