diff options
Diffstat (limited to 'lib/libkse/thread')
-rw-r--r-- | lib/libkse/thread/thr_create.c | 2 | ||||
-rw-r--r-- | lib/libkse/thread/thr_exit.c | 2 | ||||
-rw-r--r-- | lib/libkse/thread/thr_fork.c | 4 | ||||
-rw-r--r-- | lib/libkse/thread/thr_init.c | 2 | ||||
-rw-r--r-- | lib/libkse/thread/thr_private.h | 18 | ||||
-rw-r--r-- | lib/libkse/thread/thr_spec.c | 62 |
6 files changed, 54 insertions, 36 deletions
diff --git a/lib/libkse/thread/thr_create.c b/lib/libkse/thread/thr_create.c index 70227ea..f846789 100644 --- a/lib/libkse/thread/thr_create.c +++ b/lib/libkse/thread/thr_create.c @@ -179,7 +179,7 @@ _pthread_create(pthread_t * thread, const pthread_attr_t * attr, TAILQ_INIT(&new_thread->mutexq); /* Initialise hooks in the thread structure: */ - new_thread->specific_data = NULL; + new_thread->specific = NULL; new_thread->cleanup = NULL; new_thread->flags = 0; new_thread->poll_data.nfds = 0; diff --git a/lib/libkse/thread/thr_exit.c b/lib/libkse/thread/thr_exit.c index d916f5c..c9513cf 100644 --- a/lib/libkse/thread/thr_exit.c +++ b/lib/libkse/thread/thr_exit.c @@ -158,7 +158,7 @@ _pthread_exit(void *status) curthread->attr.cleanup_attr(curthread->attr.arg_attr); } /* Check if there is thread specific data: */ - if (curthread->specific_data != NULL) { + if (curthread->specific != NULL) { /* Run the thread-specific data destructors: */ _thread_cleanupspecific(); } diff --git a/lib/libkse/thread/thr_fork.c b/lib/libkse/thread/thr_fork.c index 9d9a647..dd6d3ff 100644 --- a/lib/libkse/thread/thr_fork.c +++ b/lib/libkse/thread/thr_fork.c @@ -233,8 +233,8 @@ free_thread_resources(struct pthread *thread) thread->attr.guardsize_attr); } - if (thread->specific_data != NULL) - free(thread->specific_data); + if (thread->specific != NULL) + free(thread->specific); if (thread->poll_data.fds != NULL) free(thread->poll_data.fds); diff --git a/lib/libkse/thread/thr_init.c b/lib/libkse/thread/thr_init.c index 689e85b..a3d62ae 100644 --- a/lib/libkse/thread/thr_init.c +++ b/lib/libkse/thread/thr_init.c @@ -340,7 +340,7 @@ _thread_init(void) _thread_initial->poll_data.fds = NULL; _thread_initial->sig_defer_count = 0; _thread_initial->yield_on_sig_undefer = 0; - _thread_initial->specific_data = NULL; + _thread_initial->specific = NULL; _thread_initial->cleanup = NULL; _thread_initial->flags = 0; _thread_initial->error = 0; diff --git a/lib/libkse/thread/thr_private.h b/lib/libkse/thread/thr_private.h index f49814b..ec15c3a 100644 --- a/lib/libkse/thread/thr_private.h +++ b/lib/libkse/thread/thr_private.h @@ -481,13 +481,6 @@ enum pthread_susp { } while (tv.tv_sec != _sched_tod.tv_sec) -struct pthread_key { - spinlock_t lock; - volatile int allocated; - volatile int count; - void (*destructor) (); -}; - struct pthread_rwlockattr { int pshared; }; @@ -631,6 +624,11 @@ struct pthread_signal_frame { siginfo_t siginfo; }; +struct pthread_specific_elem { + const void *data; + int seqno; +}; + /* * Thread structure. */ @@ -842,9 +840,9 @@ struct pthread { */ TAILQ_HEAD(, pthread_mutex) mutexq; - void *ret; - const void **specific_data; - int specific_data_count; + void *ret; + struct pthread_specific_elem *specific; + int specific_data_count; /* Cleanup handlers Link List */ struct pthread_cleanup *cleanup; diff --git a/lib/libkse/thread/thr_spec.c b/lib/libkse/thread/thr_spec.c index 2b359c8..e71f75f 100644 --- a/lib/libkse/thread/thr_spec.c +++ b/lib/libkse/thread/thr_spec.c @@ -38,6 +38,14 @@ #include <pthread.h> #include "pthread_private.h" +struct pthread_key { + spinlock_t lock; + volatile int allocated; + volatile int count; + int seqno; + void (*destructor) (); +}; + /* Static variables: */ static struct pthread_key key_table[PTHREAD_KEYS_MAX]; @@ -57,6 +65,7 @@ _pthread_key_create(pthread_key_t * key, void (*destructor) (void *)) if (key_table[(*key)].allocated == 0) { key_table[(*key)].allocated = 1; key_table[(*key)].destructor = destructor; + key_table[(*key)].seqno++; /* Unlock the key table entry: */ _SPINUNLOCK(&key_table[*key].lock); @@ -101,18 +110,20 @@ _thread_cleanupspecific(void) for (itr = 0; itr < PTHREAD_DESTRUCTOR_ITERATIONS; itr++) { for (key = 0; key < PTHREAD_KEYS_MAX; key++) { - if (curthread->specific_data_count) { + if (curthread->specific_data_count > 0) { /* Lock the key table entry: */ _SPINLOCK(&key_table[key].lock); destructor = NULL; - if (key_table[key].allocated) { - if (curthread->specific_data[key]) { - data = (void *) curthread->specific_data[key]; - curthread->specific_data[key] = NULL; - curthread->specific_data_count--; + if (key_table[key].allocated && + (curthread->specific[key].data != NULL)) { + if (curthread->specific[key].seqno == + key_table[key].seqno) { + data = (void *) curthread->specific[key].data; destructor = key_table[key].destructor; } + curthread->specific[key].data = NULL; + curthread->specific_data_count--; } /* Unlock the key table entry: */ @@ -125,22 +136,28 @@ _thread_cleanupspecific(void) if (destructor) destructor(data); } else { - free(curthread->specific_data); - curthread->specific_data = NULL; + free(curthread->specific); + curthread->specific = NULL; return; } } } - free(curthread->specific_data); - curthread->specific_data = NULL; + if (curthread->specific != NULL) { + free(curthread->specific); + curthread->specific = NULL; + } } -static inline const void ** +static inline struct pthread_specific_elem * pthread_key_allocate_data(void) { - const void **new_data; - if ((new_data = (const void **) malloc(sizeof(void *) * PTHREAD_KEYS_MAX)) != NULL) { - memset((void *) new_data, 0, sizeof(void *) * PTHREAD_KEYS_MAX); + struct pthread_specific_elem *new_data; + + new_data = (struct pthread_specific_elem *) + malloc(sizeof(struct pthread_specific_elem) * PTHREAD_KEYS_MAX); + if (new_data != NULL) { + memset((void *) new_data, 0, + sizeof(struct pthread_specific_elem) * PTHREAD_KEYS_MAX); } return (new_data); } @@ -154,18 +171,20 @@ _pthread_setspecific(pthread_key_t key, const void *value) /* Point to the running thread: */ pthread = _get_curthread(); - if ((pthread->specific_data) || - (pthread->specific_data = pthread_key_allocate_data())) { + if ((pthread->specific) || + (pthread->specific = pthread_key_allocate_data())) { if (key < PTHREAD_KEYS_MAX) { if (key_table[key].allocated) { - if (pthread->specific_data[key] == NULL) { + if (pthread->specific[key].data == NULL) { if (value != NULL) pthread->specific_data_count++; } else { if (value == NULL) pthread->specific_data_count--; } - pthread->specific_data[key] = value; + pthread->specific[key].data = value; + pthread->specific[key].seqno = + key_table[key].seqno; ret = 0; } else ret = EINVAL; @@ -186,11 +205,12 @@ _pthread_getspecific(pthread_key_t key) pthread = _get_curthread(); /* Check if there is specific data: */ - if (pthread->specific_data != NULL && key < PTHREAD_KEYS_MAX) { + if (pthread->specific != NULL && key < PTHREAD_KEYS_MAX) { /* Check if this key has been used before: */ - if (key_table[key].allocated) { + if (key_table[key].allocated && + (pthread->specific[key].seqno == key_table[key].seqno)) { /* Return the value: */ - data = (void *) pthread->specific_data[key]; + data = (void *) pthread->specific[key].data; } else { /* * This key has not been used before, so return NULL |