make thread list lock a recursive lock
authorRich Felker <dalias@aerifal.cx>
Fri, 22 Feb 2019 07:29:21 +0000 (02:29 -0500)
committerRich Felker <dalias@aerifal.cx>
Fri, 22 Feb 2019 07:29:21 +0000 (02:29 -0500)
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.

src/thread/pthread_create.c

index 0142b347b5509db16fe1a286c0b17ab0a3a63982..54c035545003bf98c8d4d8197484a5295f8e2e10 100644 (file)
@@ -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)