summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2019-02-22 02:29:21 -0500
committerRich Felker <dalias@aerifal.cx>2019-02-22 02:29:21 -0500
commit7865d569de7b29dd90b94b5680ec7a2a86ed27af (patch)
tree9aaf8f7eea813788d5236c2730e7fdce598ac1a5 /src
parent609dd57c4e32d68433a062a7ad8004ace90baf06 (diff)
downloadmusl-7865d569de7b29dd90b94b5680ec7a2a86ed27af.tar.gz
make thread list lock a recursive lock
this is a prerequisite for factoring the membarrier fallback code into a function that can be called from a context with the thread list already locked or independently.
Diffstat (limited to 'src')
-rw-r--r--src/thread/pthread_create.c32
1 files changed, 21 insertions, 11 deletions
diff --git a/src/thread/pthread_create.c b/src/thread/pthread_create.c
index 0142b347..54c03554 100644
--- a/src/thread/pthread_create.c
+++ b/src/thread/pthread_create.c
@@ -17,28 +17,38 @@ weak_alias(dummy_0, __do_orphaned_stdio_locks);
weak_alias(dummy_0, __dl_thread_cleanup);
weak_alias(dummy_0, __dl_prepare_for_threads);
+static int tl_lock_count;
+static int tl_lock_waiters;
+
void __tl_lock(void)
{
- if (!a_cas(&__thread_list_lock, 0, 1)) return;
- do {
- a_cas(&__thread_list_lock, 1, 2);
- __futexwait(&__thread_list_lock, 2, 0);
- } while (a_cas(&__thread_list_lock, 0, 2));
+ int tid = __pthread_self()->tid;
+ int val = __thread_list_lock;
+ if (val == tid) {
+ tl_lock_count++;
+ return;
+ }
+ while ((val = a_cas(&__thread_list_lock, 0, tid)))
+ __wait(&__thread_list_lock, &tl_lock_waiters, val, 0);
}
void __tl_unlock(void)
{
- if (a_swap(&__thread_list_lock, 0)==2)
- __wake(&__thread_list_lock, 1, 0);
+ if (tl_lock_count) {
+ tl_lock_count--;
+ return;
+ }
+ a_store(&__thread_list_lock, 0);
+ if (tl_lock_waiters) __wake(&__thread_list_lock, 1, 0);
}
void __tl_sync(pthread_t td)
{
a_barrier();
- if (!__thread_list_lock) return;
- a_cas(&__thread_list_lock, 1, 2);
- __wait(&__thread_list_lock, 0, 2, 0);
- __wake(&__thread_list_lock, 1, 0);
+ int val = __thread_list_lock;
+ if (!val) return;
+ __wait(&__thread_list_lock, &tl_lock_waiters, val, 0);
+ if (tl_lock_waiters) __wake(&__thread_list_lock, 1, 0);
}
_Noreturn void __pthread_exit(void *result)