summaryrefslogtreecommitdiff
path: root/pthread_key_delete.c
diff options
context:
space:
mode:
authorrpj <rpj>2005-05-08 16:55:02 +0000
committerrpj <rpj>2005-05-08 16:55:02 +0000
commitac8e3d247fa03af61b5411f92508481e7c3f49f8 (patch)
treef5d9c2a8bc58a2e6135e8aa2b207daab23de14a7 /pthread_key_delete.c
parent7523c7c4d75652f67cd31cb123e1268790394c8b (diff)
''
Diffstat (limited to 'pthread_key_delete.c')
-rw-r--r--pthread_key_delete.c47
1 files changed, 25 insertions, 22 deletions
diff --git a/pthread_key_delete.c b/pthread_key_delete.c
index 99b00b9..7da9b2f 100644
--- a/pthread_key_delete.c
+++ b/pthread_key_delete.c
@@ -74,42 +74,41 @@ pthread_key_delete (pthread_key_t key)
key->destructor != NULL &&
pthread_mutex_lock (&(key->keyLock)) == 0)
{
+ ThreadKeyAssoc *assoc;
/*
* Run through all Thread<-->Key associations
* for this key.
- * If the pthread_t still exists (ie the assoc->thread
- * is not NULL) then leave the assoc for the thread to
- * destroy.
- * Notes:
- * If assoc->thread is NULL, then the associated thread
- * is no longer referencing this assoc.
- * The association is only referenced
- * by this key and must be released; otherwise
- * the assoc will be destroyed when the thread is destroyed.
+ *
+ * While we hold at least one of the locks guarding
+ * the assoc, we know that the assoc pointed to by
+ * key->threads is valid.
*/
- ThreadKeyAssoc *assoc;
-
- assoc = (ThreadKeyAssoc *) key->threads;
-
- while (assoc != NULL)
+ while ((assoc = (ThreadKeyAssoc *) key->threads) != NULL)
{
- ThreadKeyAssoc *next;
ptw32_thread_t * thread = assoc->thread;
- if (thread != NULL
- && pthread_mutex_lock (&(thread->threadLock)) == 0)
+ if (assoc == NULL)
{
- next = assoc->nextThread;
+ /* Finished */
+ break;
+ }
+
+ if (pthread_mutex_lock (&(thread->threadLock)) == 0)
+ {
+ /*
+ * Since we are starting at the head of the key's threads
+ * chain, this will also point key->threads at the next assoc.
+ * While we hold key->keyLock, no other thread can insert
+ * a new assoc via pthread_setspecific.
+ */
ptw32_tkAssocDestroy (assoc);
(void) pthread_mutex_unlock (&(thread->threadLock));
}
else
{
- /* Thread or lock is no longer valid */
- next = assoc->nextThread;
+ /* Thread or lock is no longer valid? */
ptw32_tkAssocDestroy (assoc);
}
- assoc = next;
}
pthread_mutex_unlock (&(key->keyLock));
}
@@ -117,7 +116,11 @@ pthread_key_delete (pthread_key_t key)
TlsFree (key->key);
if (key->destructor != NULL)
{
- pthread_mutex_destroy (&(key->keyLock));
+ /* A thread could be holding the keyLock */
+ while (EBUSY == pthread_mutex_destroy (&(key->keyLock)))
+ {
+ Sleep(1); // Ugly.
+ }
}
#if defined( _DEBUG )