Fix is similar to libpthread. Also, use the spinlock and verify that key
has a valid value, the implementation is too flexible right now. (I
realize now that libpthread should also check for key < 0, I'll have to
go back and fix that too.)
Index: rthread_tls.c
===================================================================
RCS file: /home/tedu/cvs/src/lib/librthread/rthread_tls.c,v
retrieving revision 1.11
diff -u -r1.11 rthread_tls.c
--- rthread_tls.c 13 Oct 2008 05:42:46 -0000 1.11
+++ rthread_tls.c 2 Jul 2011 15:21:24 -0000
@@ -71,16 +71,33 @@
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 @@
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 @@
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 @@
{
struct rthread_storage *rs;
+ if (key < 0 || key >= PTHREAD_KEYS_MAX)
+ return (NULL);
+
rs = _rthread_findstorage(key);
if (!rs)
return (NULL);
@@ -124,6 +152,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)