diff options
author | Ted Unangst <tedu@cvs.openbsd.org> | 2011-07-05 00:23:41 +0000 |
---|---|---|
committer | Ted Unangst <tedu@cvs.openbsd.org> | 2011-07-05 00:23:41 +0000 |
commit | aa4d6a3e6c5e8c4e4837409c7f331324d620a9c9 (patch) | |
tree | d7677cda2fe8dc3398c477a332718b741e2bacf0 | |
parent | f17051621fe5f212b673ad665c91f756ab6857c8 (diff) |
fix a few bugs in the thread specific data functions
-rw-r--r-- | lib/librthread/rthread_tls.c | 41 |
1 files changed, 36 insertions, 5 deletions
diff --git a/lib/librthread/rthread_tls.c b/lib/librthread/rthread_tls.c index 1e415872386..572c3ba83c7 100644 --- a/lib/librthread/rthread_tls.c +++ b/lib/librthread/rthread_tls.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rthread_tls.c,v 1.11 2008/10/13 05:42:46 kevlo Exp $ */ +/* $OpenBSD: rthread_tls.c,v 1.12 2011/07/05 00:23:40 tedu Exp $ */ /* * Copyright (c) 2004,2005 Ted Unangst <tedu@openbsd.org> * All Rights Reserved. @@ -71,16 +71,33 @@ pthread_key_create(pthread_key_t *key, void (*destructor)(void*)) int pthread_key_delete(pthread_key_t key) { + pthread_t thread; + struct rthread_storage *rs; + int rv = 0; - if (!rkeys[key].used) + if (key < 0 || key >= PTHREAD_KEYS_MAX) return (EINVAL); _spinlock(&rkeyslock); + if (!rkeys[key].used) { + rv = EINVAL; + goto out; + } + rkeys[key].used = 0; rkeys[key].destructor = NULL; - _spinunlock(&rkeyslock); + _spinlock(&_thread_lock); + LIST_FOREACH(thread, &_thread_list, threads) { + for (rs = thread->local_storage; rs; rs = rs->next) { + if (rs->keyid == key) + rs->data = NULL; + } + } + _spinunlock(&_thread_lock); - return (0); +out: + _spinunlock(&rkeyslock); + return (rv); } static struct rthread_storage * @@ -89,6 +106,12 @@ _rthread_findstorage(pthread_key_t key) struct rthread_storage *rs; pthread_t self; + _spinlock(&rkeyslock); + if (!rkeys[key].used) { + rs = NULL; + goto out; + } + self = pthread_self(); for (rs = self->local_storage; rs; rs = rs->next) { @@ -98,13 +121,15 @@ _rthread_findstorage(pthread_key_t key) if (!rs) { rs = calloc(1, sizeof(*rs)); if (!rs) - return (NULL); + goto out; rs->keyid = key; rs->data = NULL; rs->next = self->local_storage; self->local_storage = rs; } +out: + _spinunlock(&rkeyslock); return (rs); } @@ -113,6 +138,9 @@ pthread_getspecific(pthread_key_t key) { struct rthread_storage *rs; + if (key < 0 || key >= PTHREAD_KEYS_MAX) + return (NULL); + rs = _rthread_findstorage(key); if (!rs) return (NULL); @@ -125,6 +153,9 @@ pthread_setspecific(pthread_key_t key, const void *data) { struct rthread_storage *rs; + if (key < 0 || key >= PTHREAD_KEYS_MAX) + return (EINVAL); + rs = _rthread_findstorage(key); if (!rs) return (ENOMEM); |