summaryrefslogtreecommitdiffstats
path: root/lib/libthr/thread/thr_list.c
diff options
context:
space:
mode:
authordavidxu <davidxu@FreeBSD.org>2010-09-13 07:03:01 +0000
committerdavidxu <davidxu@FreeBSD.org>2010-09-13 07:03:01 +0000
commite87e922f3125332f002638f5f231acc7544b7ebf (patch)
tree82f35174d92e7167b6c95a574f45720b60ded582 /lib/libthr/thread/thr_list.c
parent8ff2afea3997418eb503ad0843ed126e994fe54b (diff)
downloadFreeBSD-src-e87e922f3125332f002638f5f231acc7544b7ebf.zip
FreeBSD-src-e87e922f3125332f002638f5f231acc7544b7ebf.tar.gz
Convert thread list lock from mutex to rwlock.
Diffstat (limited to 'lib/libthr/thread/thr_list.c')
-rw-r--r--lib/libthr/thread/thr_list.c77
1 files changed, 41 insertions, 36 deletions
diff --git a/lib/libthr/thread/thr_list.c b/lib/libthr/thread/thr_list.c
index e23e57d..7541fd3 100644
--- a/lib/libthr/thread/thr_list.c
+++ b/lib/libthr/thread/thr_list.c
@@ -79,7 +79,7 @@ _thr_list_init(void)
_gc_count = 0;
total_threads = 1;
- _thr_umutex_init(&_thr_list_lock);
+ _thr_urwlock_init(&_thr_list_lock);
TAILQ_INIT(&_thread_list);
TAILQ_INIT(&free_threadq);
_thr_umutex_init(&free_thread_lock);
@@ -98,7 +98,7 @@ _thr_gc(struct pthread *curthread)
TAILQ_HEAD(, pthread) worklist;
TAILQ_INIT(&worklist);
- THREAD_LIST_LOCK(curthread);
+ THREAD_LIST_WRLOCK(curthread);
/* Check the threads waiting for GC. */
TAILQ_FOREACH_SAFE(td, &_thread_gc_list, gcle, td_next) {
@@ -107,17 +107,8 @@ _thr_gc(struct pthread *curthread)
continue;
}
_thr_stack_free(&td->attr);
- if (((td->tlflags & TLFLAGS_DETACHED) != 0) &&
- (td->refcount == 0)) {
- THR_GCLIST_REMOVE(td);
- /*
- * The thread has detached and is no longer
- * referenced. It is safe to remove all
- * remnants of the thread.
- */
- THR_LIST_REMOVE(td);
- TAILQ_INSERT_HEAD(&worklist, td, gcle);
- }
+ THR_GCLIST_REMOVE(td);
+ TAILQ_INSERT_HEAD(&worklist, td, gcle);
}
THREAD_LIST_UNLOCK(curthread);
@@ -228,10 +219,10 @@ thr_destroy(struct pthread *curthread __unused, struct pthread *thread)
void
_thr_link(struct pthread *curthread, struct pthread *thread)
{
- THREAD_LIST_LOCK(curthread);
+ THREAD_LIST_WRLOCK(curthread);
THR_LIST_ADD(thread);
- _thread_active_threads++;
THREAD_LIST_UNLOCK(curthread);
+ atomic_add_int(&_thread_active_threads, 1);
}
/*
@@ -240,10 +231,10 @@ _thr_link(struct pthread *curthread, struct pthread *thread)
void
_thr_unlink(struct pthread *curthread, struct pthread *thread)
{
- THREAD_LIST_LOCK(curthread);
+ THREAD_LIST_WRLOCK(curthread);
THR_LIST_REMOVE(thread);
- _thread_active_threads--;
THREAD_LIST_UNLOCK(curthread);
+ atomic_add_int(&_thread_active_threads, -1);
}
void
@@ -290,12 +281,11 @@ _thr_ref_add(struct pthread *curthread, struct pthread *thread,
/* Invalid thread: */
return (EINVAL);
- THREAD_LIST_LOCK(curthread);
if ((ret = _thr_find_thread(curthread, thread, include_dead)) == 0) {
thread->refcount++;
THR_CRITICAL_ENTER(curthread);
+ THR_THREAD_UNLOCK(curthread, thread);
}
- THREAD_LIST_UNLOCK(curthread);
/* Return zero if the thread exists: */
return (ret);
@@ -304,41 +294,56 @@ _thr_ref_add(struct pthread *curthread, struct pthread *thread,
void
_thr_ref_delete(struct pthread *curthread, struct pthread *thread)
{
- THREAD_LIST_LOCK(curthread);
- _thr_ref_delete_unlocked(curthread, thread);
- THREAD_LIST_UNLOCK(curthread);
+ THR_THREAD_LOCK(curthread, thread);
+ thread->refcount--;
+ _thr_try_gc(curthread, thread);
+ THR_CRITICAL_LEAVE(curthread);
}
+/* entered with thread lock held, exit with thread lock released */
void
-_thr_ref_delete_unlocked(struct pthread *curthread,
- struct pthread *thread)
+_thr_try_gc(struct pthread *curthread, struct pthread *thread)
{
- if (thread != NULL) {
- thread->refcount--;
- if ((thread->refcount == 0) && thread->state == PS_DEAD &&
- (thread->tlflags & TLFLAGS_DETACHED) != 0)
+ if (THR_SHOULD_GC(thread)) {
+ THR_REF_ADD(curthread, thread);
+ THR_THREAD_UNLOCK(curthread, thread);
+ THREAD_LIST_WRLOCK(curthread);
+ THR_THREAD_LOCK(curthread, thread);
+ THR_REF_DEL(curthread, thread);
+ if (THR_SHOULD_GC(thread)) {
+ THR_LIST_REMOVE(thread);
THR_GCLIST_ADD(thread);
- THR_CRITICAL_LEAVE(curthread);
+ }
+ THR_THREAD_UNLOCK(curthread, thread);
+ THREAD_LIST_UNLOCK(curthread);
+ } else {
+ THR_THREAD_UNLOCK(curthread, thread);
}
}
+/* return with thread lock held if thread is found */
int
-_thr_find_thread(struct pthread *curthread __unused, struct pthread *thread,
+_thr_find_thread(struct pthread *curthread, struct pthread *thread,
int include_dead)
{
struct pthread *pthread;
+ int ret;
if (thread == NULL)
- /* Invalid thread: */
return (EINVAL);
+ ret = 0;
+ THREAD_LIST_RDLOCK(curthread);
pthread = _thr_hash_find(thread);
if (pthread) {
+ THR_THREAD_LOCK(curthread, pthread);
if (include_dead == 0 && pthread->state == PS_DEAD) {
- pthread = NULL;
- }
+ THR_THREAD_UNLOCK(curthread, pthread);
+ ret = ESRCH;
+ }
+ } else {
+ ret = ESRCH;
}
-
- /* Return zero if the thread exists: */
- return ((pthread != NULL) ? 0 : ESRCH);
+ THREAD_LIST_UNLOCK(curthread);
+ return (ret);
}
OpenPOWER on IntegriCloud