summaryrefslogtreecommitdiffstats
path: root/lib/libkse/thread/thr_kern.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libkse/thread/thr_kern.c')
-rw-r--r--lib/libkse/thread/thr_kern.c37
1 files changed, 27 insertions, 10 deletions
diff --git a/lib/libkse/thread/thr_kern.c b/lib/libkse/thread/thr_kern.c
index 6e0003a..5d7fabb 100644
--- a/lib/libkse/thread/thr_kern.c
+++ b/lib/libkse/thread/thr_kern.c
@@ -139,6 +139,9 @@ LIST_HEAD(thread_hash_head, pthread);
static struct thread_hash_head thr_hashtable[THREAD_HASH_QUEUES];
#define THREAD_HASH(thrd) ((unsigned long)thrd % THREAD_HASH_QUEUES)
+/* Lock for thread tcb constructor/destructor */
+static pthread_mutex_t _tcb_mutex;
+
#ifdef DEBUG_THREAD_KERN
static void dump_queues(struct kse *curkse);
#endif
@@ -166,7 +169,7 @@ static void thr_resume_check(struct pthread *curthread, ucontext_t *ucp,
struct pthread_sigframe *psf);
static int thr_timedout(struct pthread *thread, struct timespec *curtime);
static void thr_unlink(struct pthread *thread);
-static void thr_destroy(struct pthread *thread);
+static void thr_destroy(struct pthread *curthread, struct pthread *thread);
static void thread_gc(struct pthread *thread);
static void kse_gc(struct pthread *thread);
static void kseg_gc(struct pthread *thread);
@@ -240,7 +243,7 @@ _kse_single_thread(struct pthread *curthread)
_thr_stack_free(&thread->attr);
if (thread->specific != NULL)
free(thread->specific);
- thr_destroy(thread);
+ thr_destroy(curthread, thread);
}
}
@@ -285,14 +288,14 @@ _kse_single_thread(struct pthread *curthread)
/* Free the free threads. */
while ((thread = TAILQ_FIRST(&free_threadq)) != NULL) {
TAILQ_REMOVE(&free_threadq, thread, tle);
- thr_destroy(thread);
+ thr_destroy(curthread, thread);
}
free_thread_count = 0;
/* Free the to-be-gc'd threads. */
while ((thread = TAILQ_FIRST(&_thread_gc_list)) != NULL) {
TAILQ_REMOVE(&_thread_gc_list, thread, gcle);
- thr_destroy(thread);
+ thr_destroy(curthread, thread);
}
TAILQ_INIT(&gc_ksegq);
_gc_count = 0;
@@ -381,6 +384,7 @@ _kse_init(void)
if (_lock_init(&_thread_list_lock, LCK_ADAPTIVE,
_kse_lock_wait, _kse_lock_wakeup) != 0)
PANIC("Unable to initialize thread list lock");
+ _pthread_mutex_init(&_tcb_mutex, NULL);
active_kse_count = 0;
active_kseg_count = 0;
_gc_count = 0;
@@ -1207,7 +1211,6 @@ thr_cleanup(struct kse *curkse, struct pthread *thread)
thread->kseg = _kse_initial->k_kseg;
thread->kse = _kse_initial;
}
- thread->flags |= THR_FLAGS_GC_SAFE;
/*
* We can't hold the thread list lock while holding the
@@ -1216,6 +1219,7 @@ thr_cleanup(struct kse *curkse, struct pthread *thread)
KSE_SCHED_UNLOCK(curkse, curkse->k_kseg);
DBG_MSG("Adding thread %p to GC list\n", thread);
KSE_LOCK_ACQUIRE(curkse, &_thread_list_lock);
+ thread->tlflags |= TLFLAGS_GC_SAFE;
THR_GCLIST_ADD(thread);
KSE_LOCK_RELEASE(curkse, &_thread_list_lock);
if (sys_scope) {
@@ -1255,7 +1259,7 @@ thread_gc(struct pthread *curthread)
/* Check the threads waiting for GC. */
for (td = TAILQ_FIRST(&_thread_gc_list); td != NULL; td = td_next) {
td_next = TAILQ_NEXT(td, gcle);
- if ((td->flags & THR_FLAGS_GC_SAFE) == 0)
+ if ((td->tlflags & TLFLAGS_GC_SAFE) == 0)
continue;
else if (((td->attr.flags & PTHREAD_SCOPE_SYSTEM) != 0) &&
((td->kse->k_kcb->kcb_kmbx.km_flags & KMF_DONE) == 0)) {
@@ -2384,7 +2388,14 @@ _thr_alloc(struct pthread *curthread)
if ((thread == NULL) &&
((thread = malloc(sizeof(struct pthread))) != NULL)) {
bzero(thread, sizeof(struct pthread));
- if ((thread->tcb = _tcb_ctor(thread, curthread == NULL)) == NULL) {
+ if (curthread) {
+ _pthread_mutex_lock(&_tcb_mutex);
+ thread->tcb = _tcb_ctor(thread, 0 /* not initial tls */);
+ _pthread_mutex_unlock(&_tcb_mutex);
+ } else {
+ thread->tcb = _tcb_ctor(thread, 1 /* initial tls */);
+ }
+ if (thread->tcb == NULL) {
free(thread);
thread = NULL;
} else {
@@ -2420,7 +2431,7 @@ _thr_free(struct pthread *curthread, struct pthread *thread)
thread->name = NULL;
}
if ((curthread == NULL) || (free_thread_count >= MAX_CACHED_THREADS)) {
- thr_destroy(thread);
+ thr_destroy(curthread, thread);
} else {
/* Add the thread to the free thread list. */
crit = _kse_critical_enter();
@@ -2433,14 +2444,20 @@ _thr_free(struct pthread *curthread, struct pthread *thread)
}
static void
-thr_destroy(struct pthread *thread)
+thr_destroy(struct pthread *curthread, struct pthread *thread)
{
int i;
for (i = 0; i < MAX_THR_LOCKLEVEL; i++)
_lockuser_destroy(&thread->lockusers[i]);
_lock_destroy(&thread->lock);
- _tcb_dtor(thread->tcb);
+ if (curthread) {
+ _pthread_mutex_lock(&_tcb_mutex);
+ _tcb_dtor(thread->tcb);
+ _pthread_mutex_unlock(&_tcb_mutex);
+ } else {
+ _tcb_dtor(thread->tcb);
+ }
free(thread->siginfo);
free(thread);
}
OpenPOWER on IntegriCloud