about summary refs log tree commit diff
path: root/src/thread
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2012-04-24 06:36:50 -0400
committerRich Felker <dalias@aerifal.cx>2012-04-24 06:36:50 -0400
commitf34d0ea511e552851c8c6148fb113816f41e6759 (patch)
tree51b1dbdf2058697ab51782b96c6317f2c6051d5a /src/thread
parent1b0ce9af6d2aa7b92edaf3e9c631cb635bae22bd (diff)
downloadmusl-f34d0ea511e552851c8c6148fb113816f41e6759.tar.gz
musl-f34d0ea511e552851c8c6148fb113816f41e6759.tar.xz
musl-f34d0ea511e552851c8c6148fb113816f41e6759.zip
new internal locking primitive; drop spinlocks
we use priority inheritance futexes if possible so that the library
cannot hit internal priority inversion deadlocks in the presence of
realtime priority scheduling (full support to be added later).
Diffstat (limited to 'src/thread')
-rw-r--r--src/thread/__lock.c33
1 files changed, 27 insertions, 6 deletions
diff --git a/src/thread/__lock.c b/src/thread/__lock.c
index d1717956..d1734096 100644
--- a/src/thread/__lock.c
+++ b/src/thread/__lock.c
@@ -1,11 +1,32 @@
 #include "pthread_impl.h"
 
+void __lock_2(volatile int *l)
+{
+	if (!__syscall(SYS_futex, l, FUTEX_LOCK_PI, 0, 0))
+		return;
+	int old, tid = __pthread_self()->tid;
+	while ((old = a_cas(l, 0, tid))) {
+		a_cas(l, old, old|INT_MIN);
+		__syscall(SYS_futex, l, FUTEX_WAIT, old|INT_MIN, 0);
+	}
+}
+
 void __lock(volatile int *l)
 {
-	int spins=10000;
-	/* Do not use futexes because we insist that unlocking is a simple
-	 * assignment to optimize non-pathological code with no contention. */
-	while (a_swap(l, 1))
-		if (spins) spins--, a_spin();
-		else __syscall(SYS_sched_yield);
+	if (a_cas(l, 0, __pthread_self()->tid)) __lock_2(l);
+}
+
+void __unlock_2(volatile int *l)
+{
+	if (__syscall(SYS_futex, l, FUTEX_UNLOCK_PI)) {
+		*l = 0;
+		__syscall(SYS_futex, l, FUTEX_WAKE, 1);
+	}
+}
+
+void __unlock(volatile int *l)
+{
+	int old = *l;
+	if (!(old & INT_MIN) && a_cas(l, old, 0)==old) return;
+	__unlock_2(l);
 }