Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorConrad Scott <conrad.scott@dsl.pipex.com>2002-09-21 12:13:47 +0400
committerConrad Scott <conrad.scott@dsl.pipex.com>2002-09-21 12:13:47 +0400
commitec01247bc632cfdeec4b9e6a44dab8d86bc8ba0f (patch)
tree1eae1c14b39c97a5723fa82126980172e9847b8f
parent336007d500ac110288bea11abba678e568a22d8b (diff)
Merged changes from HEAD
-rw-r--r--winsup/cygwin/ChangeLog89
-rw-r--r--winsup/cygwin/pthread.cc26
-rw-r--r--winsup/cygwin/thread.cc359
-rw-r--r--winsup/cygwin/thread.h157
4 files changed, 365 insertions, 266 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index cbd077440..66dc9c07f 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,5 +1,94 @@
2002-09-21 Robert Collins <rbtcollins@hotmail.com>
+ * pthread.cc: Use class::call for converted pthread and semaphore
+ calls.
+ * thread.cc: Convert various __pthread_call and __sem_call to
+ pthread::call and sem::call throughout.
+ * pthread.h (__pthread_cancel): Convert to pthread::cancel.
+ (__pthread_join): Convert to pthread::join.
+ (__pthread_detach): Convert to pthread::detach.
+ (__pthread_create): Convert to pthread::create.
+ (__pthread_once): Convert to pthread::once.
+ (__pthread_atfork): Convert to pthread::atfork.
+ (__pthread_suspend): Convert to pthread::suspend.
+ (__pthread_continue): Convert to pthread::resume.
+ (__sem_init): Convert to semaphore::init.
+ (__sem_destroy): Convert to semaphore::destroy.
+ (__sem_wait): Convert to semaphore::wait.
+ (__sem_trywait): Convert to semaphore::trywait.
+ (__sem_post): Convert to semaphore::post.
+
+2002-09-21 Robert Collins <rbtcollins@hotmail.com>
+
+ * thread.cc: Finish the removal of the separate pthread_key
+ destructor list.
+ Remove all pthread_key_destructor and pthread_key_destructor_list
+ references throughout.
+ (pthread::exit): Call the new pthread_key interface to activate
+ destructors.
+ (pthread_key::keys): Change into a list.
+ (pthread_key::saveAKey): New method, used via forEach.
+ (pthread_key::restoreAKey): Ditto.
+ (pthread_key::destroyAKey): Ditto.
+ (pthread_key::fixup_before_fork): Use the List::forEach functionality.
+ (pthread_key::fixup_after_fork): Ditto.
+ (pthread_key::runAllDestructors): New method implementation.
+ (pthread_key::pthread_key): Use List::Insert rather than custom list
+ code.
+ (pthread_key::~pthread_key): Use List::Remove for the same reason.
+ * thread.h: Remove all pthread_key_destructor and
+ pthread_key_destructor_list references throughout.
+ (List): Move the interface above pthread_key in the header.
+ Use atomic operations during insert and delete.
+ (List::forEach): A generic interface for doing something on each node.
+ (pthread_key::runAllDestructors): New method, run all destructors.
+ (pthread_key::fork_buf): Make private.
+ (pthread_key::run_destructor): Ditto.
+ (pthread_key::saveAKey): New method for clearer source.
+ (pthread_key::restoreAKey): Ditto.
+ (pthread_key::destroyAKey): Ditto.
+ (MTinterface::destructors): Remove.
+
+2002-09-21 Robert Collins <rbtcollins@hotmail.com>
+
+ * thread.cc: Partial refactoring of pthread_key destructor
+ handling. Loosely based on Thomas Pfaff's work.
+ (pthread_key_destructor_list::Insert): Remove.
+ (pthread_key_destructor_list::Pop): Remove.
+ (pthread_key_destructor_list::IterateNull): Call the key's
+ run_destructor method.
+ (pthread_key::pthread_key): Initialize new member.
+ (pthread_key::get): Mark as const for correctness.
+ (pthread_key::run_destructor): Implement.
+ * thread.h (pthread_key::get): Mark as const for correctness.
+ (pthread_key::run_destructor): Declare.
+ (List): New template class that implements a generic list.
+ (pthread_key_destructor_list): Inherit from List, and remove
+ now duplicate functions.
+
+2002-09-21 Robert Collins <rbtcollins@hotmail.com>
+
+ * thread.cc: Change verifyable_object_isvalid calls with
+ PTHREAD_CONDATTR_MAGIC, PTHREAD_MUTEXATTR_MAGIC, PTHREAD_COND_MAGIC,
+ SEM_MAGIC to objecttype::isGoodObject() calls throughout.
+ (pthread_condattr::isGoodObject): Implement.
+ (pthread_mutex::isGoodInitializer): Implement.
+ (pthread_mutex::isGoodInitializerOrObject): Minor bugfix in the
+ check for verifyable_object_isvalid result.
+ (pthread_mutexattr::isGoodObject): Implement.
+ (pthread_cond::isGoodObject): Ditto.
+ (pthread_cond::isGoodInitializer): Ditto.
+ (pthread_cond::isGoodInitializerOrObject): Ditto.
+ (semaphore::isGoodObject): Ditto.
+ * thread.h (pthread_mutex::isGoodInitializer): Declare.
+ (pthread_condattr::isGoodObject): Ditto.
+ (pthread_cond::isGoodObject): Const correctness.
+ (pthread_cond::isGoodInitializer): Declare.
+ (pthread_cond::isGoodInitializerOrObject): Ditto.
+ (semaphore::isGoodObject): Const correctness.
+
+2002-09-21 Robert Collins <rbtcollins@hotmail.com>
+
* thread.cc: Change verifyable_object_isvalid calls with
PTHREAD_MUTEX_MAGIC and PTHREAD_KEY_MAGIC and PTHREAD_ATTR_MAGIC to
::isGoodObject() calls throughout.
diff --git a/winsup/cygwin/pthread.cc b/winsup/cygwin/pthread.cc
index 90eb20f25..810fd1f20 100644
--- a/winsup/cygwin/pthread.cc
+++ b/winsup/cygwin/pthread.cc
@@ -21,19 +21,19 @@ int
pthread_create (pthread_t * thread, const pthread_attr_t * attr,
void *(*start_routine) (void *), void *arg)
{
- return __pthread_create (thread, attr, start_routine, arg);
+ return pthread::create (thread, attr, start_routine, arg);
}
int
pthread_once (pthread_once_t * once_control, void (*init_routine) (void))
{
- return __pthread_once (once_control, init_routine);
+ return pthread::once (once_control, init_routine);
}
int
pthread_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(void))
{
- return __pthread_atfork(prepare, parent, child);
+ return pthread::atfork(prepare, parent, child);
}
int
@@ -147,13 +147,13 @@ pthread_exit (void *value_ptr)
int
pthread_join (pthread_t thread, void **return_val)
{
- return __pthread_join (&thread, (void **) return_val);
+ return pthread::join (&thread, (void **) return_val);
}
int
pthread_detach (pthread_t thread)
{
- return __pthread_detach (&thread);
+ return pthread::detach (&thread);
}
@@ -161,14 +161,14 @@ pthread_detach (pthread_t thread)
int
pthread_suspend (pthread_t thread)
{
- return __pthread_suspend (&thread);
+ return pthread::suspend (&thread);
}
/* same */
int
pthread_continue (pthread_t thread)
{
- return __pthread_continue (&thread);
+ return pthread::resume (&thread);
}
unsigned long
@@ -425,7 +425,7 @@ pthread_setschedparam (pthread_t thread, int policy,
int
pthread_cancel (pthread_t thread)
{
- return __pthread_cancel (thread);
+ return pthread::cancel (thread);
}
int
@@ -462,31 +462,31 @@ _pthread_cleanup_pop (int execute)
int
sem_init (sem_t * sem, int pshared, unsigned int value)
{
- return __sem_init (sem, pshared, value);
+ return semaphore::init (sem, pshared, value);
}
int
sem_destroy (sem_t * sem)
{
- return __sem_destroy (sem);
+ return semaphore::destroy (sem);
}
int
sem_wait (sem_t * sem)
{
- return __sem_wait (sem);
+ return semaphore::wait (sem);
}
int
sem_trywait (sem_t * sem)
{
- return __sem_trywait (sem);
+ return semaphore::trywait (sem);
}
int
sem_post (sem_t * sem)
{
- return __sem_post (sem);
+ return semaphore::post (sem);
}
}
diff --git a/winsup/cygwin/thread.cc b/winsup/cygwin/thread.cc
index d54cc689b..e5e313044 100644
--- a/winsup/cygwin/thread.cc
+++ b/winsup/cygwin/thread.cc
@@ -46,92 +46,6 @@ details. */
extern int threadsafe;
-/*pthread_key_destructor_list class: to-be threadsafe single linked list
- *FIXME: Put me in a dedicated file, or a least a tools area !
- */
-
-pthread_key_destructor *
-pthread_key_destructor::InsertAfter (pthread_key_destructor *node)
-{
- pthread_key_destructor *temp = next;
- next = node;
- return temp;
-}
-
-pthread_key_destructor *
-pthread_key_destructor::UnlinkNext ()
-{
- pthread_key_destructor *temp = next;
- if (next)
- next = next->Next ();
- return temp;
-}
-
-pthread_key_destructor *
-pthread_key_destructor::Next ()
-{
- return next;
-}
-
-void
-pthread_key_destructor_list::Insert (pthread_key_destructor *node)
-{
- if (!node)
- return;
- head = node->InsertAfter (head);
- if (!head)
- head = node; /*first node special case */
-}
-
- /*remove a given dataitem, wherever in the list it is */
-pthread_key_destructor *
-pthread_key_destructor_list::Remove (pthread_key *key)
-{
- if (!key)
- return NULL;
- if (!head)
- return NULL;
- if (key == head->key)
- return Pop ();
- pthread_key_destructor *temp = head;
- while (temp && temp->Next () && !(key == temp->Next ()->key))
- {
- temp = temp->Next ();
- }
- if (temp)
- return temp->UnlinkNext ();
- return NULL;
-}
-
- /*get the first item and remove at the same time */
-pthread_key_destructor *
-pthread_key_destructor_list::Pop ()
-{
- pthread_key_destructor *temp = head;
- head = head->Next ();
- return temp;
-}
-
-pthread_key_destructor::
-pthread_key_destructor (void (*thedestructor) (void *), pthread_key *key)
-{
- destructor = thedestructor;
- next = NULL;
- this->key = key;
-}
-
-void
-pthread_key_destructor_list::IterateNull ()
-{
- pthread_key_destructor *temp = head;
- while (temp)
- {
- temp->destructor ((temp->key)->get ());
- temp = temp->Next ();
- }
-}
-
-
#define MT_INTERFACE user_data->threadinterface
struct _reent *
@@ -457,7 +371,7 @@ pthread::exit (void *value_ptr)
// run cleanup handlers
pop_all_cleanup_handlers ();
- MT_INTERFACE->destructors.IterateNull ();
+ pthread_key::runAllDestructors ();
mutex.Lock ();
// cleanup if thread is in detached state and not joined
@@ -822,6 +736,14 @@ pthread_attr::~pthread_attr ()
{
}
+bool
+pthread_condattr::isGoodObject (pthread_condattr_t const *attr)
+{
+ if (verifyable_object_isvalid (attr, PTHREAD_CONDATTR_MAGIC) != VALID_OBJECT)
+ return false;
+ return true;
+}
+
pthread_condattr::pthread_condattr ():verifyable_object
(PTHREAD_CONDATTR_MAGIC), shared (PTHREAD_PROCESS_PRIVATE)
{
@@ -1012,30 +934,42 @@ pthread_cond::fixup_after_fork ()
/* pthread_key */
/* static members */
-pthread_key *pthread_key::keys = NULL;
+List<pthread_key> pthread_key::keys;
+
+void
+pthread_key::saveAKey (pthread_key *key)
+{
+ key->saveKeyToBuffer ();
+}
void
pthread_key::fixup_before_fork ()
{
- pthread_key *key = keys;
- debug_printf ("keys is %x",keys);
- while (key)
- {
- key->saveKeyToBuffer ();
- key = key->next;
- }
+ keys.forEach (saveAKey);
+}
+
+void
+pthread_key::restoreAKey (pthread_key *key)
+{
+ key->recreateKeyFromBuffer ();
}
void
pthread_key::fixup_after_fork ()
{
- pthread_key *key = keys;
- debug_printf ("keys is %x",keys);
- while (key)
- {
- key->recreateKeyFromBuffer ();
- key = key->next;
- }
+ keys.forEach (restoreAKey);
+}
+
+void
+pthread_key::destroyAKey (pthread_key *key)
+{
+ key->run_destructor ();
+}
+
+void
+pthread_key::runAllDestructors ()
+{
+ keys.forEach (destroyAKey);
}
bool
@@ -1048,36 +982,23 @@ pthread_key::isGoodObject (pthread_key_t const *key)
/* non-static members */
-pthread_key::pthread_key (void (*destructor) (void *)):verifyable_object (PTHREAD_KEY_MAGIC)
+pthread_key::pthread_key (void (*aDestructor) (void *)):verifyable_object (PTHREAD_KEY_MAGIC), destructor (aDestructor)
{
dwTlsIndex = TlsAlloc ();
if (dwTlsIndex == TLS_OUT_OF_INDEXES)
magic = 0;
- else if (destructor)
- {
- MT_INTERFACE->destructors.
- Insert (new pthread_key_destructor (destructor, this));
- }
- /* threadsafe addition is easy */
- next = (pthread_key *) InterlockedExchangePointer (&keys, this);
+ else
+ keys.Insert (this);
}
pthread_key::~pthread_key ()
{
- if (pthread_key_destructor *dest = MT_INTERFACE->destructors.Remove (this))
- delete dest;
- TlsFree (dwTlsIndex);
-
- /* I'm not 100% sure the next bit is threadsafe. I think it is... */
- if (keys == this)
- InterlockedExchangePointer (keys, this->next);
- else
+ /* We may need to make the list code lock the list during operations
+ */
+ if (magic != 0)
{
- pthread_key *tempkey = keys;
- while (tempkey->next && tempkey->next != this)
- tempkey = tempkey->next;
- /* but there may be a race between the loop above and this statement */
- InterlockedExchangePointer (&tempkey->next, this->next);
+ keys.Remove (this);
+ TlsFree (dwTlsIndex);
}
}
@@ -1090,7 +1011,7 @@ pthread_key::set (const void *value)
}
void *
-pthread_key::get ()
+pthread_key::get () const
{
int savedError = ::GetLastError();
void *result = TlsGetValue (dwTlsIndex);
@@ -1113,6 +1034,13 @@ pthread_key::recreateKeyFromBuffer ()
set (fork_buf);
}
+void
+pthread_key::run_destructor () const
+{
+ if (destructor)
+ destructor (get());
+}
+
/*pshared mutexs:
* REMOVED FROM CURRENT. These can be reinstated with the daemon, when all the
@@ -1139,17 +1067,25 @@ pthread_key::recreateKeyFromBuffer ()
/* static members */
bool
-pthread_mutex::isGoodObject (pthread_mutex_t const *thread)
+pthread_mutex::isGoodObject (pthread_mutex_t const *mutex)
{
- if (verifyable_object_isvalid (thread, PTHREAD_MUTEX_MAGIC) != VALID_OBJECT)
+ if (verifyable_object_isvalid (mutex, PTHREAD_MUTEX_MAGIC) != VALID_OBJECT)
return false;
return true;
}
bool
-pthread_mutex::isGoodInitializerOrObject (pthread_mutex_t const *thread)
+pthread_mutex::isGoodInitializer (pthread_mutex_t const *mutex)
{
- if (verifyable_object_isvalid (thread, PTHREAD_MUTEX_MAGIC, PTHREAD_MUTEX_INITIALIZER) != VALID_OBJECT)
+ if (verifyable_object_isvalid (mutex, PTHREAD_MUTEX_MAGIC, PTHREAD_MUTEX_INITIALIZER) != VALID_STATIC_OBJECT)
+ return false;
+ return true;
+}
+
+bool
+pthread_mutex::isGoodInitializerOrObject (pthread_mutex_t const *mutex)
+{
+ if (verifyable_object_isvalid (mutex, PTHREAD_MUTEX_MAGIC, PTHREAD_MUTEX_INITIALIZER) == INVALID_OBJECT)
return false;
return true;
}
@@ -1257,6 +1193,14 @@ pthread_mutex::fixup_after_fork ()
#endif
}
+bool
+pthread_mutexattr::isGoodObject (pthread_mutexattr_t const * attr)
+{
+ if (verifyable_object_isvalid (attr, PTHREAD_MUTEXATTR_MAGIC) != VALID_OBJECT)
+ return false;
+ return true;
+}
+
pthread_mutexattr::pthread_mutexattr ():verifyable_object (PTHREAD_MUTEXATTR_MAGIC),
pshared (PTHREAD_PROCESS_PRIVATE), mutextype (PTHREAD_MUTEX_DEFAULT)
{
@@ -1454,7 +1398,7 @@ pthread::getsequence_np ()
}
int
-__pthread_create (pthread_t *thread, const pthread_attr_t *attr,
+pthread::create (pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg)
{
DECLARE_TLS_STORAGE;
@@ -1463,7 +1407,7 @@ __pthread_create (pthread_t *thread, const pthread_attr_t *attr,
*thread = new pthread ();
(*thread)->create (start_routine, attr ? *attr : NULL, arg);
- if (!pthread::isGoodObject (thread))
+ if (!isGoodObject (thread))
{
delete (*thread);
*thread = NULL;
@@ -1474,7 +1418,7 @@ __pthread_create (pthread_t *thread, const pthread_attr_t *attr,
}
int
-__pthread_once (pthread_once_t *once_control, void (*init_routine) (void))
+pthread::once (pthread_once_t *once_control, void (*init_routine) (void))
{
// already done ?
if (once_control->state)
@@ -1498,9 +1442,9 @@ __pthread_once (pthread_once_t *once_control, void (*init_routine) (void))
}
int
-__pthread_cancel (pthread_t thread)
+pthread::cancel (pthread_t thread)
{
- if (!pthread::isGoodObject (&thread))
+ if (!isGoodObject (&thread))
return ESRCH;
return thread->cancel ();
@@ -1566,7 +1510,7 @@ pthread::atforkchild (void)
*parent and child calls are called in FI-FC order.
*/
int
-__pthread_atfork (void (*prepare)(void), void (*parent)(void), void (*child)(void))
+pthread::atfork (void (*prepare)(void), void (*parent)(void), void (*child)(void))
{
callback *prepcb = NULL, *parentcb = NULL, *childcb = NULL;
if (prepare)
@@ -1782,16 +1726,16 @@ __pthread_attr_destroy (pthread_attr_t *attr)
}
int
-__pthread_join (pthread_t *thread, void **return_val)
+pthread::join (pthread_t *thread, void **return_val)
{
- pthread_t joiner = pthread::self ();
+ pthread_t joiner = self ();
// Initialize return val with NULL
if (return_val)
*return_val = NULL;
/*FIXME: wait on the thread cancellation event as well - we are a cancellation point*/
- if (!pthread::isGoodObject (thread))
+ if (!isGoodObject (thread))
return ESRCH;
if (__pthread_equal (thread,&joiner))
@@ -1822,9 +1766,9 @@ __pthread_join (pthread_t *thread, void **return_val)
}
int
-__pthread_detach (pthread_t *thread)
+pthread::detach (pthread_t *thread)
{
- if (!pthread::isGoodObject (thread))
+ if (!isGoodObject (thread))
return ESRCH;
(*thread)->mutex.Lock ();
@@ -1853,9 +1797,9 @@ __pthread_detach (pthread_t *thread)
}
int
-__pthread_suspend (pthread_t *thread)
+pthread::suspend (pthread_t *thread)
{
- if (!pthread::isGoodObject (thread))
+ if (!isGoodObject (thread))
return ESRCH;
if ((*thread)->suspended == false)
@@ -1869,9 +1813,9 @@ __pthread_suspend (pthread_t *thread)
int
-__pthread_continue (pthread_t *thread)
+pthread::resume (pthread_t *thread)
{
- if (!pthread::isGoodObject (thread))
+ if (!isGoodObject (thread))
return ESRCH;
if ((*thread)->suspended == true)
@@ -1986,13 +1930,36 @@ __pthread_getspecific (pthread_key_t key)
}
/*Thread synchronisation */
+bool
+pthread_cond::isGoodObject (pthread_cond_t const *cond)
+{
+ if (verifyable_object_isvalid (cond, PTHREAD_COND_MAGIC) != VALID_OBJECT)
+ return false;
+ return true;
+}
+
+bool
+pthread_cond::isGoodInitializer (pthread_cond_t const *cond)
+{
+ if (verifyable_object_isvalid (cond, PTHREAD_COND_MAGIC, PTHREAD_COND_INITIALIZER) != VALID_STATIC_OBJECT)
+ return false;
+ return true;
+}
+
+bool
+pthread_cond::isGoodInitializerOrObject (pthread_cond_t const *cond)
+{
+ if (verifyable_object_isvalid (cond, PTHREAD_COND_MAGIC, PTHREAD_COND_INITIALIZER) == INVALID_OBJECT)
+ return false;
+ return true;
+}
int
__pthread_cond_destroy (pthread_cond_t *cond)
{
- if (check_valid_pointer (cond) && (*cond == PTHREAD_COND_INITIALIZER))
+ if (pthread_cond::isGoodInitializer (cond))
return 0;
- if (verifyable_object_isvalid (cond, PTHREAD_COND_MAGIC) != VALID_OBJECT)
+ if (!pthread_cond::isGoodObject (cond))
return EINVAL;
/*reads are atomic */
@@ -2008,15 +1975,15 @@ __pthread_cond_destroy (pthread_cond_t *cond)
int
__pthread_cond_init (pthread_cond_t *cond, const pthread_condattr_t *attr)
{
- if (attr && verifyable_object_isvalid (attr, PTHREAD_CONDATTR_MAGIC) != VALID_OBJECT)
+ if (attr && !pthread_condattr::isGoodObject (attr))
return EINVAL;
- if (verifyable_object_isvalid (cond, PTHREAD_COND_MAGIC, PTHREAD_COND_INITIALIZER) == VALID_OBJECT)
+ if (pthread_cond::isGoodObject (cond))
return EBUSY;
*cond = new pthread_cond (attr ? (*attr) : NULL);
- if (verifyable_object_isvalid (cond, PTHREAD_COND_MAGIC) != VALID_OBJECT)
+ if (!pthread_cond::isGoodObject (cond))
{
delete (*cond);
*cond = NULL;
@@ -2029,9 +1996,9 @@ __pthread_cond_init (pthread_cond_t *cond, const pthread_condattr_t *attr)
int
__pthread_cond_broadcast (pthread_cond_t *cond)
{
- if (*cond == PTHREAD_COND_INITIALIZER)
+ if (pthread_cond::isGoodInitializer (cond))
__pthread_cond_init (cond, NULL);
- if (verifyable_object_isvalid (cond, PTHREAD_COND_MAGIC) != VALID_OBJECT)
+ if (!pthread_cond::isGoodObject (cond))
return EINVAL;
(*cond)->BroadCast ();
@@ -2042,9 +2009,9 @@ __pthread_cond_broadcast (pthread_cond_t *cond)
int
__pthread_cond_signal (pthread_cond_t *cond)
{
- if (*cond == PTHREAD_COND_INITIALIZER)
+ if (pthread_cond::isGoodInitializer (cond))
__pthread_cond_init (cond, NULL);
- if (verifyable_object_isvalid (cond, PTHREAD_COND_MAGIC) != VALID_OBJECT)
+ if (!pthread_cond::isGoodObject (cond))
return EINVAL;
(*cond)->Signal ();
@@ -2063,12 +2030,12 @@ __pthread_cond_dowait (pthread_cond_t *cond, pthread_mutex_t *mutex,
if (*mutex == PTHREAD_MUTEX_INITIALIZER)
__pthread_mutex_init (mutex, NULL);
themutex = mutex;
- if (*cond == PTHREAD_COND_INITIALIZER)
+ if (pthread_cond::isGoodInitializer (cond))
__pthread_cond_init (cond, NULL);
if (!pthread_mutex::isGoodObject (themutex))
return EINVAL;
- if (verifyable_object_isvalid (cond, PTHREAD_COND_MAGIC) != VALID_OBJECT)
+ if (!pthread_cond::isGoodObject (cond))
return EINVAL;
/*if the cond variable is blocked, then the above timer test maybe wrong. *shrug**/
@@ -2135,8 +2102,9 @@ pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex)
int
__pthread_condattr_init (pthread_condattr_t *condattr)
{
+ /* FIXME: we dereference blindly! */
*condattr = new pthread_condattr;
- if (verifyable_object_isvalid (condattr, PTHREAD_CONDATTR_MAGIC) != VALID_OBJECT)
+ if (!pthread_condattr::isGoodObject (condattr))
{
delete (*condattr);
*condattr = NULL;
@@ -2148,7 +2116,7 @@ __pthread_condattr_init (pthread_condattr_t *condattr)
int
__pthread_condattr_getpshared (const pthread_condattr_t *attr, int *pshared)
{
- if (verifyable_object_isvalid (attr, PTHREAD_CONDATTR_MAGIC) != VALID_OBJECT)
+ if (!pthread_condattr::isGoodObject (attr))
return EINVAL;
*pshared = (*attr)->shared;
return 0;
@@ -2157,7 +2125,7 @@ __pthread_condattr_getpshared (const pthread_condattr_t *attr, int *pshared)
int
__pthread_condattr_setpshared (pthread_condattr_t *attr, int pshared)
{
- if (verifyable_object_isvalid (attr, PTHREAD_CONDATTR_MAGIC) != VALID_OBJECT)
+ if (!pthread_condattr::isGoodObject (attr))
return EINVAL;
if ((pshared < 0) || (pshared > 1))
return EINVAL;
@@ -2171,7 +2139,7 @@ __pthread_condattr_setpshared (pthread_condattr_t *attr, int pshared)
int
__pthread_condattr_destroy (pthread_condattr_t *condattr)
{
- if (verifyable_object_isvalid (condattr, PTHREAD_CONDATTR_MAGIC) != VALID_OBJECT)
+ if (!pthread_condattr::isGoodObject (condattr))
return EINVAL;
delete (*condattr);
*condattr = NULL;
@@ -2238,10 +2206,11 @@ int
__pthread_mutex_init (pthread_mutex_t *mutex,
const pthread_mutexattr_t *attr)
{
- if (attr && verifyable_object_isvalid (attr, PTHREAD_MUTEXATTR_MAGIC) != VALID_OBJECT || check_valid_pointer (mutex))
+ if (attr && !pthread_mutexattr::isGoodObject (attr) || check_valid_pointer (mutex))
return EINVAL;
- if (pthread_mutex::isGoodInitializerOrObject (mutex))
+ /* FIXME: bugfix: we should check *mutex being a valid address */
+ if (pthread_mutex::isGoodObject (mutex))
return EBUSY;
*mutex = new pthread_mutex (attr ? (*attr) : NULL);
@@ -2259,7 +2228,7 @@ __pthread_mutex_getprioceiling (const pthread_mutex_t *mutex,
int *prioceiling)
{
pthread_mutex_t *themutex = (pthread_mutex_t *) mutex;
- if (*mutex == PTHREAD_MUTEX_INITIALIZER)
+ if (pthread_mutex::isGoodInitializer (mutex))
__pthread_mutex_init ((pthread_mutex_t *) mutex, NULL);
if (!pthread_mutex::isGoodObject (themutex))
return EINVAL;
@@ -2278,13 +2247,17 @@ int
__pthread_mutex_lock (pthread_mutex_t *mutex)
{
pthread_mutex_t *themutex = mutex;
+ /* This could be simplified via isGoodInitializerOrObject
+ and isGoodInitializer, 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 (*mutex == PTHREAD_MUTEX_INITIALIZER)
+ if (pthread_mutex::isGoodInitializer (mutex))
{
int rv = __pthread_mutex_init (mutex, NULL);
if (rv)
@@ -2302,7 +2275,7 @@ int
__pthread_mutex_trylock (pthread_mutex_t *mutex)
{
pthread_mutex_t *themutex = mutex;
- if (*mutex == PTHREAD_MUTEX_INITIALIZER)
+ if (pthread_mutex::isGoodInitializer (mutex))
__pthread_mutex_init (mutex, NULL);
if (!pthread_mutex::isGoodObject (themutex))
return EINVAL;
@@ -2314,7 +2287,7 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex)
int
__pthread_mutex_unlock (pthread_mutex_t *mutex)
{
- if (*mutex == PTHREAD_MUTEX_INITIALIZER)
+ if (pthread_mutex::isGoodInitializer (mutex))
__pthread_mutex_init (mutex, NULL);
if (!pthread_mutex::isGoodObject (mutex))
return EINVAL;
@@ -2325,7 +2298,7 @@ __pthread_mutex_unlock (pthread_mutex_t *mutex)
int
__pthread_mutex_destroy (pthread_mutex_t *mutex)
{
- if (check_valid_pointer (mutex) && (*mutex == PTHREAD_MUTEX_INITIALIZER))
+ if (pthread_mutex::isGoodInitializer (mutex))
return 0;
if (!pthread_mutex::isGoodObject (mutex))
return EINVAL;
@@ -2344,7 +2317,7 @@ __pthread_mutex_setprioceiling (pthread_mutex_t *mutex, int prioceiling,
int *old_ceiling)
{
pthread_mutex_t *themutex = mutex;
- if (*mutex == PTHREAD_MUTEX_INITIALIZER)
+ if (pthread_mutex::isGoodInitializer (mutex))
__pthread_mutex_init (mutex, NULL);
if (!pthread_mutex::isGoodObject (themutex))
return EINVAL;
@@ -2357,7 +2330,7 @@ int
__pthread_mutexattr_getprotocol (const pthread_mutexattr_t *attr,
int *protocol)
{
- if (verifyable_object_isvalid (attr, PTHREAD_MUTEXATTR_MAGIC) != VALID_OBJECT)
+ if (!pthread_mutexattr::isGoodObject (attr))
return EINVAL;
return ENOSYS;
}
@@ -2366,7 +2339,7 @@ int
__pthread_mutexattr_getpshared (const pthread_mutexattr_t *attr,
int *pshared)
{
- if (verifyable_object_isvalid (attr, PTHREAD_MUTEXATTR_MAGIC) != VALID_OBJECT)
+ if (!pthread_mutexattr::isGoodObject (attr))
return EINVAL;
*pshared = (*attr)->pshared;
return 0;
@@ -2379,7 +2352,7 @@ __pthread_mutexattr_getpshared (const pthread_mutexattr_t *attr,
int
__pthread_mutexattr_gettype (const pthread_mutexattr_t *attr, int *type)
{
- if (verifyable_object_isvalid (attr, PTHREAD_MUTEXATTR_MAGIC) != VALID_OBJECT)
+ if (!pthread_mutexattr::isGoodObject (attr))
return EINVAL;
*type = (*attr)->mutextype;
return 0;
@@ -2393,11 +2366,11 @@ __pthread_mutexattr_gettype (const pthread_mutexattr_t *attr, int *type)
int
__pthread_mutexattr_init (pthread_mutexattr_t *attr)
{
- if (verifyable_object_isvalid (attr, PTHREAD_MUTEXATTR_MAGIC) != INVALID_OBJECT)
+ if (pthread_mutexattr::isGoodObject (attr))
return EBUSY;
*attr = new pthread_mutexattr ();
- if (verifyable_object_isvalid (attr, PTHREAD_MUTEXATTR_MAGIC) != VALID_OBJECT)
+ if (!pthread_mutexattr::isGoodObject (attr))
{
delete (*attr);
*attr = NULL;
@@ -2409,7 +2382,7 @@ __pthread_mutexattr_init (pthread_mutexattr_t *attr)
int
__pthread_mutexattr_destroy (pthread_mutexattr_t *attr)
{
- if (verifyable_object_isvalid (attr, PTHREAD_MUTEXATTR_MAGIC) != VALID_OBJECT)
+ if (!pthread_mutexattr::isGoodObject (attr))
return EINVAL;
delete (*attr);
*attr = NULL;
@@ -2421,7 +2394,7 @@ __pthread_mutexattr_destroy (pthread_mutexattr_t *attr)
int
__pthread_mutexattr_setprotocol (pthread_mutexattr_t *attr, int protocol)
{
- if (verifyable_object_isvalid (attr, PTHREAD_MUTEXATTR_MAGIC) != VALID_OBJECT)
+ if (!pthread_mutexattr::isGoodObject (attr))
return EINVAL;
return ENOSYS;
}
@@ -2431,7 +2404,7 @@ int
__pthread_mutexattr_setprioceiling (pthread_mutexattr_t *attr,
int prioceiling)
{
- if (verifyable_object_isvalid (attr, PTHREAD_MUTEXATTR_MAGIC) != VALID_OBJECT)
+ if (!pthread_mutexattr::isGoodObject (attr))
return EINVAL;
return ENOSYS;
}
@@ -2440,7 +2413,7 @@ int
__pthread_mutexattr_getprioceiling (const pthread_mutexattr_t *attr,
int *prioceiling)
{
- if (verifyable_object_isvalid (attr, PTHREAD_MUTEXATTR_MAGIC) != VALID_OBJECT)
+ if (!pthread_mutexattr::isGoodObject (attr))
return EINVAL;
return ENOSYS;
}
@@ -2448,7 +2421,7 @@ __pthread_mutexattr_getprioceiling (const pthread_mutexattr_t *attr,
int
__pthread_mutexattr_setpshared (pthread_mutexattr_t *attr, int pshared)
{
- if (verifyable_object_isvalid (attr, PTHREAD_MUTEXATTR_MAGIC) != VALID_OBJECT)
+ if (!pthread_mutexattr::isGoodObject (attr))
return EINVAL;
/*we don't use pshared for anything as yet. We need to test PROCESS_SHARED
*functionality
@@ -2463,7 +2436,7 @@ __pthread_mutexattr_setpshared (pthread_mutexattr_t *attr, int pshared)
int
__pthread_mutexattr_settype (pthread_mutexattr_t *attr, int type)
{
- if (verifyable_object_isvalid (attr, PTHREAD_MUTEXATTR_MAGIC) != VALID_OBJECT)
+ if (!pthread_mutexattr::isGoodObject (attr))
return EINVAL;
if (type != PTHREAD_MUTEX_RECURSIVE)
return EINVAL;
@@ -2472,11 +2445,21 @@ __pthread_mutexattr_settype (pthread_mutexattr_t *attr, int type)
}
/*Semaphores */
+
+/* static members */
+bool
+semaphore::isGoodObject (sem_t const * sem)
+{
+ if (verifyable_object_isvalid (sem, SEM_MAGIC) != VALID_OBJECT)
+ return false;
+ return true;
+}
+
int
-__sem_init (sem_t *sem, int pshared, unsigned int value)
+semaphore::init (sem_t *sem, int pshared, unsigned int value)
{
/*opengroup calls this undefined */
- if (verifyable_object_isvalid (sem, SEM_MAGIC) != INVALID_OBJECT)
+ if (isGoodObject (sem))
return EBUSY;
if (value > SEM_VALUE_MAX)
@@ -2484,7 +2467,7 @@ __sem_init (sem_t *sem, int pshared, unsigned int value)
*sem = new semaphore (pshared, value);
- if (verifyable_object_isvalid (sem, SEM_MAGIC) != VALID_OBJECT)
+ if (!isGoodObject (sem))
{
delete (*sem);
*sem = NULL;
@@ -2494,9 +2477,9 @@ __sem_init (sem_t *sem, int pshared, unsigned int value)
}
int
-__sem_destroy (sem_t *sem)
+semaphore::destroy (sem_t *sem)
{
- if (verifyable_object_isvalid (sem, SEM_MAGIC) != VALID_OBJECT)
+ if (!isGoodObject (sem))
return EINVAL;
/*FIXME - new feature - test for busy against threads... */
@@ -2507,9 +2490,9 @@ __sem_destroy (sem_t *sem)
}
int
-__sem_wait (sem_t *sem)
+semaphore::wait (sem_t *sem)
{
- if (verifyable_object_isvalid (sem, SEM_MAGIC) != VALID_OBJECT)
+ if (!isGoodObject (sem))
{
set_errno (EINVAL);
return -1;
@@ -2520,9 +2503,9 @@ __sem_wait (sem_t *sem)
}
int
-__sem_trywait (sem_t *sem)
+semaphore::trywait (sem_t *sem)
{
- if (verifyable_object_isvalid (sem, SEM_MAGIC) != VALID_OBJECT)
+ if (!isGoodObject (sem))
{
set_errno (EINVAL);
return -1;
@@ -2532,9 +2515,9 @@ __sem_trywait (sem_t *sem)
}
int
-__sem_post (sem_t *sem)
+semaphore::post (sem_t *sem)
{
- if (verifyable_object_isvalid (sem, SEM_MAGIC) != VALID_OBJECT)
+ if (!isGoodObject (sem))
return EINVAL;
(*sem)->Post ();
diff --git a/winsup/cygwin/thread.h b/winsup/cygwin/thread.h
index 9238153ea..c36466020 100644
--- a/winsup/cygwin/thread.h
+++ b/winsup/cygwin/thread.h
@@ -173,58 +173,93 @@ 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));
+protected:
+ ListNode *head;
+};
+
class pthread_key:public verifyable_object
{
public:
static bool isGoodObject (pthread_key_t const *);
+ static void runAllDestructors ();
DWORD dwTlsIndex;
- void *fork_buf;
- class pthread_key *next;
int set (const void *);
- void *get ();
+ void *get () const;
- pthread_key (void (*)(void *));
+ pthread_key (void (*)(void *));
~pthread_key ();
static void fixup_before_fork();
static void fixup_after_fork();
+
+ /* List support calls */
+ class pthread_key *next;
private:
// lists of objects. USE THREADSAFE INSERTS AND DELETES.
- static pthread_key * keys;
+ static List<pthread_key> keys;
+ static void saveAKey (pthread_key *);
+ static void restoreAKey (pthread_key *);
+ static void destroyAKey (pthread_key *);
void saveKeyToBuffer ();
void recreateKeyFromBuffer ();
-};
-
-/* FIXME: test using multiple inheritance and merging key_destructor into pthread_key
- * for efficiency */
-class pthread_key_destructor
-{
-public:
void (*destructor) (void *);
- pthread_key_destructor *InsertAfter (pthread_key_destructor * node);
- pthread_key_destructor *UnlinkNext ();
- pthread_key_destructor *Next ();
-
- pthread_key_destructor (void (*thedestructor) (void *), pthread_key * key);
- pthread_key_destructor *next;
- pthread_key *key;
+ void run_destructor () const;
+ void *fork_buf;
};
-class pthread_key_destructor_list
+/* implementation */
+template <class ListNode>
+List<ListNode>::List<ListNode> () : head(NULL)
{
-public:
- void Insert (pthread_key_destructor * node);
-/* remove a given dataitem, wherever in the list it is */
- pthread_key_destructor *Remove (pthread_key_destructor * item);
-/* get the first item and remove at the same time */
- pthread_key_destructor *Pop ();
- pthread_key_destructor *Remove (pthread_key * key);
- void IterateNull ();
-private:
- pthread_key_destructor * head;
-};
-
+}
+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
{
@@ -254,6 +289,7 @@ class pthread_mutex:public verifyable_object
{
public:
static bool isGoodObject(pthread_mutex_t const *);
+ static bool isGoodInitializer(pthread_mutex_t const *);
static bool isGoodInitializerOrObject(pthread_mutex_t const *);
CRITICAL_SECTION criticalsection;
HANDLE win32_obj_id;
@@ -300,9 +336,21 @@ public:
static void atforkparent();
static void atforkchild();
+ /* API calls */
+ static int cancel (pthread_t);
+ static int join (pthread_t * thread, void **return_val);
+ static int detach (pthread_t * thread);
+ static int create (pthread_t * thread, const pthread_attr_t * attr,
+ void *(*start_routine) (void *), void *arg);
+ static int once (pthread_once_t *, void (*)(void));
+ static int atfork(void (*)(void), void (*)(void), void (*)(void));
+ static int suspend (pthread_t * thread);
+ static int resume (pthread_t * thread);
+
virtual void exit (void *value_ptr);
virtual int cancel ();
+
virtual void testcancel ();
static void static_cancel_self ();
@@ -322,9 +370,6 @@ private:
__pthread_cleanup_handler *cleanup_stack;
pthread_mutex mutex;
- friend int __pthread_join (pthread_t * thread, void **return_val);
- friend int __pthread_detach (pthread_t * thread);
-
void pop_all_cleanup_handlers (void);
void precreate (pthread_attr *);
void postcreate ();
@@ -361,7 +406,7 @@ class pthreadNull : public pthread
class pthread_condattr:public verifyable_object
{
public:
- static bool isGoodObject(pthread_condattr_t *);
+ static bool isGoodObject(pthread_condattr_t const *);
int shared;
pthread_condattr ();
@@ -371,7 +416,9 @@ public:
class pthread_cond:public verifyable_object
{
public:
- static bool isGoodObject(pthread_cond_t *);
+ static bool isGoodObject(pthread_cond_t const *);
+ static bool isGoodInitializer(pthread_cond_t const *);
+ static bool isGoodInitializerOrObject(pthread_cond_t const *);
int shared;
LONG waiting;
LONG ExitingWait;
@@ -400,7 +447,14 @@ public:
class semaphore:public verifyable_object
{
public:
- static bool isGoodObject(semaphore **);
+ static bool isGoodObject(sem_t const *);
+ /* API calls */
+ static int init (sem_t * sem, int pshared, unsigned int value);
+ static int destroy (sem_t * sem);
+ static int wait (sem_t * sem);
+ static int trywait (sem_t * sem);
+ static int post (sem_t * sem);
+
HANDLE win32_obj_id;
class semaphore * next;
int shared;
@@ -437,7 +491,6 @@ public:
struct _winsup_t winsup_reent;
pthread mainthread;
- pthread_key_destructor_list destructors;
callback *pthread_prepare;
callback *pthread_child;
callback *pthread_parent;
@@ -459,21 +512,8 @@ public:
}
};
-/* Cancellation */
-int __pthread_cancel (pthread_t thread);
-
-/* Thread Exit */
-int __pthread_join (pthread_t * thread, void **return_val);
-int __pthread_detach (pthread_t * thread);
-
extern "C"
{
-/* ThreadCreation */
-int __pthread_create (pthread_t * thread, const pthread_attr_t * attr,
- void *(*start_routine) (void *), void *arg);
-int __pthread_once (pthread_once_t *, void (*)(void));
-int __pthread_atfork(void (*)(void), void (*)(void), void (*)(void));
-
int __pthread_attr_init (pthread_attr_t * attr);
int __pthread_attr_destroy (pthread_attr_t * attr);
int __pthread_attr_setdetachstate (pthread_attr_t *, int);
@@ -494,10 +534,6 @@ int __pthread_attr_setschedpolicy (pthread_attr_t *, int);
int __pthread_attr_setscope (pthread_attr_t *, int);
int __pthread_attr_setstackaddr (pthread_attr_t *, void *);
-/* Thread suspend */
-int __pthread_suspend (pthread_t * thread);
-int __pthread_continue (pthread_t * thread);
-
/* Thread SpecificData */
int __pthread_key_create (pthread_key_t * key, void (*destructor) (void *));
int __pthread_key_delete (pthread_key_t key);
@@ -556,16 +592,7 @@ int __pthread_getschedparam (pthread_t thread, int *policy,
int __pthread_setschedparam (pthread_t thread, int policy,
const struct sched_param *param);
-/* cancelability states */
-
-/* Semaphores */
-int __sem_init (sem_t * sem, int pshared, unsigned int value);
-int __sem_destroy (sem_t * sem);
-int __sem_wait (sem_t * sem);
-int __sem_trywait (sem_t * sem);
-int __sem_post (sem_t * sem);
};
-
#endif // MT_SAFE
#endif // _CYGNUS_THREADS_