Simplify the handling of thread specific data. Only track if a key

is allocated or not, rather than keeping a count and attempting to
know it it is in-use. POSIX says that once a key is deleted, using the
key again results in undefined behaviour.
This commit is contained in:
jb 1998-06-06 07:24:24 +00:00
parent 00f9c743b6
commit d78d3f941a
3 changed files with 99 additions and 135 deletions

View File

@ -40,54 +40,47 @@
/* Static variables: */
static struct pthread_key key_table[PTHREAD_KEYS_MAX];
static long key_table_lock = 0;
int
pthread_key_create(pthread_key_t * key, void (*destructor) (void *))
{
/* Lock the key table: */
_spinlock(&key_table_lock);
for ((*key) = 0; (*key) < PTHREAD_KEYS_MAX; (*key)++) {
if (key_table[(*key)].count == 0) {
key_table[(*key)].count++;
/* Lock the key table entry: */
_spinlock(&key_table[*key].access_lock);
if (key_table[(*key)].allocated == 0) {
key_table[(*key)].allocated = 1;
key_table[(*key)].destructor = destructor;
/* Unlock the key table: */
_atomic_unlock(&key_table_lock);
/* Unlock the key table entry: */
_atomic_unlock(&key_table[*key].access_lock);
return (0);
}
}
/* Unlock the key table: */
_atomic_unlock(&key_table_lock);
/* Unlock the key table entry: */
_atomic_unlock(&key_table[*key].access_lock);
}
return (EAGAIN);
}
int
pthread_key_delete(pthread_key_t key)
{
int ret;
/* Lock the key table: */
_spinlock(&key_table_lock);
int ret = 0;
if (key < PTHREAD_KEYS_MAX) {
switch (key_table[key].count) {
case 1:
key_table[key].destructor = NULL;
key_table[key].count = 0;
case 0:
ret = 0;
break;
default:
ret = EBUSY;
}
/* Lock the key table entry: */
_spinlock(&key_table[key].access_lock);
if (key_table[key].allocated)
key_table[key].allocated = 0;
else
ret = EINVAL;
/* Unlock the key table entry: */
_atomic_unlock(&key_table[key].access_lock);
} else
ret = EINVAL;
/* Unlock the key table: */
_atomic_unlock(&key_table_lock);
return (ret);
}
@ -104,14 +97,14 @@ _thread_cleanupspecific(void)
/* Lock the key table entry: */
_spinlock(&key_table[key].access_lock);
if (_thread_run->specific_data[key]) {
data = (void *) _thread_run->specific_data[key];
_thread_run->specific_data[key] = NULL;
_thread_run->specific_data_count--;
if (key_table[key].destructor) {
key_table[key].destructor(data);
if (key_table[key].allocated) {
if (_thread_run->specific_data[key]) {
data = (void *) _thread_run->specific_data[key];
_thread_run->specific_data[key] = NULL;
_thread_run->specific_data_count--;
if (key_table[key].destructor)
key_table[key].destructor(data);
}
key_table[key].count--;
}
/* Unlock the key table entry: */
@ -150,17 +143,13 @@ pthread_setspecific(pthread_key_t key, const void *value)
/* Lock the key table entry: */
_spinlock(&key_table[key].access_lock);
if (key_table[key].count) {
if (key_table[key].allocated) {
if (pthread->specific_data[key] == NULL) {
if (value != NULL) {
if (value != NULL)
pthread->specific_data_count++;
key_table[key].count++;
}
} else {
if (value == NULL) {
if (value == NULL)
pthread->specific_data_count--;
key_table[key].count--;
}
}
pthread->specific_data[key] = value;
ret = 0;
@ -187,13 +176,12 @@ pthread_getspecific(pthread_key_t key)
pthread = _thread_run;
/* Check if there is specific data: */
if (pthread->specific_data != NULL &&
(key < PTHREAD_KEYS_MAX) && (key_table)) {
if (pthread->specific_data != NULL && key < PTHREAD_KEYS_MAX) {
/* Lock the key table entry: */
_spinlock(&key_table[key].access_lock);
/* Check if this key has been used before: */
if (key_table[key].count) {
if (key_table[key].allocated) {
/* Return the value: */
data = (void *) pthread->specific_data[key];
} else {

View File

@ -40,54 +40,47 @@
/* Static variables: */
static struct pthread_key key_table[PTHREAD_KEYS_MAX];
static long key_table_lock = 0;
int
pthread_key_create(pthread_key_t * key, void (*destructor) (void *))
{
/* Lock the key table: */
_spinlock(&key_table_lock);
for ((*key) = 0; (*key) < PTHREAD_KEYS_MAX; (*key)++) {
if (key_table[(*key)].count == 0) {
key_table[(*key)].count++;
/* Lock the key table entry: */
_spinlock(&key_table[*key].access_lock);
if (key_table[(*key)].allocated == 0) {
key_table[(*key)].allocated = 1;
key_table[(*key)].destructor = destructor;
/* Unlock the key table: */
_atomic_unlock(&key_table_lock);
/* Unlock the key table entry: */
_atomic_unlock(&key_table[*key].access_lock);
return (0);
}
}
/* Unlock the key table: */
_atomic_unlock(&key_table_lock);
/* Unlock the key table entry: */
_atomic_unlock(&key_table[*key].access_lock);
}
return (EAGAIN);
}
int
pthread_key_delete(pthread_key_t key)
{
int ret;
/* Lock the key table: */
_spinlock(&key_table_lock);
int ret = 0;
if (key < PTHREAD_KEYS_MAX) {
switch (key_table[key].count) {
case 1:
key_table[key].destructor = NULL;
key_table[key].count = 0;
case 0:
ret = 0;
break;
default:
ret = EBUSY;
}
/* Lock the key table entry: */
_spinlock(&key_table[key].access_lock);
if (key_table[key].allocated)
key_table[key].allocated = 0;
else
ret = EINVAL;
/* Unlock the key table entry: */
_atomic_unlock(&key_table[key].access_lock);
} else
ret = EINVAL;
/* Unlock the key table: */
_atomic_unlock(&key_table_lock);
return (ret);
}
@ -104,14 +97,14 @@ _thread_cleanupspecific(void)
/* Lock the key table entry: */
_spinlock(&key_table[key].access_lock);
if (_thread_run->specific_data[key]) {
data = (void *) _thread_run->specific_data[key];
_thread_run->specific_data[key] = NULL;
_thread_run->specific_data_count--;
if (key_table[key].destructor) {
key_table[key].destructor(data);
if (key_table[key].allocated) {
if (_thread_run->specific_data[key]) {
data = (void *) _thread_run->specific_data[key];
_thread_run->specific_data[key] = NULL;
_thread_run->specific_data_count--;
if (key_table[key].destructor)
key_table[key].destructor(data);
}
key_table[key].count--;
}
/* Unlock the key table entry: */
@ -150,17 +143,13 @@ pthread_setspecific(pthread_key_t key, const void *value)
/* Lock the key table entry: */
_spinlock(&key_table[key].access_lock);
if (key_table[key].count) {
if (key_table[key].allocated) {
if (pthread->specific_data[key] == NULL) {
if (value != NULL) {
if (value != NULL)
pthread->specific_data_count++;
key_table[key].count++;
}
} else {
if (value == NULL) {
if (value == NULL)
pthread->specific_data_count--;
key_table[key].count--;
}
}
pthread->specific_data[key] = value;
ret = 0;
@ -187,13 +176,12 @@ pthread_getspecific(pthread_key_t key)
pthread = _thread_run;
/* Check if there is specific data: */
if (pthread->specific_data != NULL &&
(key < PTHREAD_KEYS_MAX) && (key_table)) {
if (pthread->specific_data != NULL && key < PTHREAD_KEYS_MAX) {
/* Lock the key table entry: */
_spinlock(&key_table[key].access_lock);
/* Check if this key has been used before: */
if (key_table[key].count) {
if (key_table[key].allocated) {
/* Return the value: */
data = (void *) pthread->specific_data[key];
} else {

View File

@ -40,54 +40,47 @@
/* Static variables: */
static struct pthread_key key_table[PTHREAD_KEYS_MAX];
static long key_table_lock = 0;
int
pthread_key_create(pthread_key_t * key, void (*destructor) (void *))
{
/* Lock the key table: */
_spinlock(&key_table_lock);
for ((*key) = 0; (*key) < PTHREAD_KEYS_MAX; (*key)++) {
if (key_table[(*key)].count == 0) {
key_table[(*key)].count++;
/* Lock the key table entry: */
_spinlock(&key_table[*key].access_lock);
if (key_table[(*key)].allocated == 0) {
key_table[(*key)].allocated = 1;
key_table[(*key)].destructor = destructor;
/* Unlock the key table: */
_atomic_unlock(&key_table_lock);
/* Unlock the key table entry: */
_atomic_unlock(&key_table[*key].access_lock);
return (0);
}
}
/* Unlock the key table: */
_atomic_unlock(&key_table_lock);
/* Unlock the key table entry: */
_atomic_unlock(&key_table[*key].access_lock);
}
return (EAGAIN);
}
int
pthread_key_delete(pthread_key_t key)
{
int ret;
/* Lock the key table: */
_spinlock(&key_table_lock);
int ret = 0;
if (key < PTHREAD_KEYS_MAX) {
switch (key_table[key].count) {
case 1:
key_table[key].destructor = NULL;
key_table[key].count = 0;
case 0:
ret = 0;
break;
default:
ret = EBUSY;
}
/* Lock the key table entry: */
_spinlock(&key_table[key].access_lock);
if (key_table[key].allocated)
key_table[key].allocated = 0;
else
ret = EINVAL;
/* Unlock the key table entry: */
_atomic_unlock(&key_table[key].access_lock);
} else
ret = EINVAL;
/* Unlock the key table: */
_atomic_unlock(&key_table_lock);
return (ret);
}
@ -104,14 +97,14 @@ _thread_cleanupspecific(void)
/* Lock the key table entry: */
_spinlock(&key_table[key].access_lock);
if (_thread_run->specific_data[key]) {
data = (void *) _thread_run->specific_data[key];
_thread_run->specific_data[key] = NULL;
_thread_run->specific_data_count--;
if (key_table[key].destructor) {
key_table[key].destructor(data);
if (key_table[key].allocated) {
if (_thread_run->specific_data[key]) {
data = (void *) _thread_run->specific_data[key];
_thread_run->specific_data[key] = NULL;
_thread_run->specific_data_count--;
if (key_table[key].destructor)
key_table[key].destructor(data);
}
key_table[key].count--;
}
/* Unlock the key table entry: */
@ -150,17 +143,13 @@ pthread_setspecific(pthread_key_t key, const void *value)
/* Lock the key table entry: */
_spinlock(&key_table[key].access_lock);
if (key_table[key].count) {
if (key_table[key].allocated) {
if (pthread->specific_data[key] == NULL) {
if (value != NULL) {
if (value != NULL)
pthread->specific_data_count++;
key_table[key].count++;
}
} else {
if (value == NULL) {
if (value == NULL)
pthread->specific_data_count--;
key_table[key].count--;
}
}
pthread->specific_data[key] = value;
ret = 0;
@ -187,13 +176,12 @@ pthread_getspecific(pthread_key_t key)
pthread = _thread_run;
/* Check if there is specific data: */
if (pthread->specific_data != NULL &&
(key < PTHREAD_KEYS_MAX) && (key_table)) {
if (pthread->specific_data != NULL && key < PTHREAD_KEYS_MAX) {
/* Lock the key table entry: */
_spinlock(&key_table[key].access_lock);
/* Check if this key has been used before: */
if (key_table[key].count) {
if (key_table[key].allocated) {
/* Return the value: */
data = (void *) pthread->specific_data[key];
} else {