about summary refs log tree commit diff
path: root/src/thread/pthread_detach.c
diff options
context:
space:
mode:
authorJens Gustedt <Jens.Gustedt@inria.fr>2018-01-03 14:17:12 +0100
committerRich Felker <dalias@aerifal.cx>2018-01-09 13:10:12 -0500
commit47d0bcd4762f223364e5b58d5a381aaa0cbd7c38 (patch)
treee73dfc04306ff6f03f1e2712aa3c14321866df8a /src/thread/pthread_detach.c
parentb583c5d3b4cc2c54c68eef5eb7855ecfacee8bfc (diff)
downloadmusl-47d0bcd4762f223364e5b58d5a381aaa0cbd7c38.tar.gz
musl-47d0bcd4762f223364e5b58d5a381aaa0cbd7c38.tar.xz
musl-47d0bcd4762f223364e5b58d5a381aaa0cbd7c38.zip
new lock algorithm with state and congestion count in one atomic int
A variant of this new lock algorithm has been presented at SAC'16, see
https://hal.inria.fr/hal-01304108. A full version of that paper is
available at https://hal.inria.fr/hal-01236734.

The main motivation of this is to improve on the safety of the basic lock
implementation in musl. This is achieved by squeezing a lock flag and a
congestion count (= threads inside the critical section) into a single
int. Thereby an unlock operation does exactly one memory
transfer (a_fetch_add) and never touches the value again, but still
detects if a waiter has to be woken up.

This is a fix of a use-after-free bug in pthread_detach that had
temporarily been patched. Therefore this patch also reverts

         c1e27367a9b26b9baac0f37a12349fc36567c8b6

This is also the only place where internal knowledge of the lock
algorithm is used.

The main price for the improved safety is a little bit larger code.

Under high congestion, the scheduling behavior will be different
compared to the previous algorithm. In that case, a successful
put-to-sleep may appear out of order compared to the arrival in the
critical section.
Diffstat (limited to 'src/thread/pthread_detach.c')
-rw-r--r--src/thread/pthread_detach.c5
1 files changed, 2 insertions, 3 deletions
diff --git a/src/thread/pthread_detach.c b/src/thread/pthread_detach.c
index 13482607..d9c90d1c 100644
--- a/src/thread/pthread_detach.c
+++ b/src/thread/pthread_detach.c
@@ -6,11 +6,10 @@ int __pthread_join(pthread_t, void **);
 static int __pthread_detach(pthread_t t)
 {
 	/* Cannot detach a thread that's already exiting */
-	if (a_swap(t->exitlock, 1))
+	if (a_cas(t->exitlock, 0, INT_MIN + 1))
 		return __pthread_join(t, 0);
 	t->detached = 2;
-	a_store(t->exitlock, 0);
-	__wake(t->exitlock, 1, 1);
+	__unlock(t->exitlock);
 	return 0;
 }