Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20201227184032.22413-17-alobakin@pm.me>
Date: Sun, 27 Dec 2020 18:42:47 +0000
From: Alexander Lobakin <alobakin@...me>
To: Rich Felker <dalias@...ifal.cx>, musl@...ts.openwall.com
Cc: Alexander Lobakin <alobakin@...me>
Subject: [PATCH 17/18] futex: prefer time64 variant if available

Instead of using time64 variant "only when needed", use it as
a default and fallback to time32 only on -ENOSYS.
This also introduces a new shorthand, __futexcall(), for futex
calls without timespec argument.

Signed-off-by: Alexander Lobakin <alobakin@...me>
---
 src/internal/pthread_impl.h                | 22 ++++++++++++++++++----
 src/thread/__timedwait.c                   |  6 ++----
 src/thread/__wait.c                        |  4 ++--
 src/thread/pthread_barrier_wait.c          |  6 +++---
 src/thread/pthread_cond_timedwait.c        | 10 +++++-----
 src/thread/pthread_mutex_timedlock.c       |  8 +++-----
 src/thread/pthread_mutex_trylock.c         |  2 +-
 src/thread/pthread_mutex_unlock.c          |  2 +-
 src/thread/pthread_mutexattr_setprotocol.c |  2 +-
 9 files changed, 36 insertions(+), 26 deletions(-)

diff --git a/src/internal/pthread_impl.h b/src/internal/pthread_impl.h
index de2b9d8b477e..abb2a9a074a0 100644
--- a/src/internal/pthread_impl.h
+++ b/src/internal/pthread_impl.h
@@ -165,18 +165,32 @@ hidden void __unmapself(void *, size_t);
 hidden int __timedwait(volatile int *, int, clockid_t, const struct timespec *, int);
 hidden int __timedwait_cp(volatile int *, int, clockid_t, const struct timespec *, int);
 hidden void __wait(volatile int *, volatile int *, int, int);
+
+#ifdef SYS_futex_time64
+#define __futexcall(...) ({					\
+	int __r = __syscall(SYS_futex_time64, ##__VA_ARGS__);	\
+	if (!(SYS_futex == SYS_futex_time64 || __r != -ENOSYS))	\
+		__r = __syscall(SYS_futex, ##__VA_ARGS__);	\
+	__r;							\
+})
+#else
+#define __futexcall(...) ({					\
+	__syscall(SYS_futex, ##__VA_ARGS__);			\
+})
+#endif
+
 static inline void __wake(volatile void *addr, int cnt, int priv)
 {
 	if (priv) priv = FUTEX_PRIVATE;
 	if (cnt<0) cnt = INT_MAX;
-	__syscall(SYS_futex, addr, FUTEX_WAKE|priv, cnt) != -ENOSYS ||
-	__syscall(SYS_futex, addr, FUTEX_WAKE, cnt);
+	__futexcall(addr, FUTEX_WAKE|priv, cnt) != -ENOSYS ||
+	__futexcall(addr, FUTEX_WAKE, cnt);
 }
 static inline void __futexwait(volatile void *addr, int val, int priv)
 {
 	if (priv) priv = FUTEX_PRIVATE;
-	__syscall(SYS_futex, addr, FUTEX_WAIT|priv, val, 0) != -ENOSYS ||
-	__syscall(SYS_futex, addr, FUTEX_WAIT, val, 0);
+	__futexcall(addr, FUTEX_WAIT|priv, val, 0) != -ENOSYS ||
+	__futexcall(addr, FUTEX_WAIT, val, 0);
 }
 
 hidden void __acquire_ptc(void);
diff --git a/src/thread/__timedwait.c b/src/thread/__timedwait.c
index 666093be9851..38d326834c14 100644
--- a/src/thread/__timedwait.c
+++ b/src/thread/__timedwait.c
@@ -14,10 +14,8 @@ static int __futex4_cp(volatile void *addr, int op, int val, const struct timesp
 #ifdef SYS_futex_time64
 	time_t s = to ? to->tv_sec : 0;
 	long ns = to ? to->tv_nsec : 0;
-	r = -ENOSYS;
-	if (SYS_futex == SYS_futex_time64 || !IS32BIT(s))
-		r = __syscall_cp(SYS_futex_time64, addr, op, val,
-			to ? ((long long[]){s, ns}) : 0);
+	r = __syscall_cp(SYS_futex_time64, addr, op, val,
+		to ? ((long long[]){s, ns}) : 0);
 	if (SYS_futex == SYS_futex_time64 || r!=-ENOSYS) return r;
 	to = to ? (void *)(long[]){CLAMP(s), ns} : 0;
 #endif
diff --git a/src/thread/__wait.c b/src/thread/__wait.c
index dc33c1a30992..ba6397207649 100644
--- a/src/thread/__wait.c
+++ b/src/thread/__wait.c
@@ -10,8 +10,8 @@ void __wait(volatile int *addr, volatile int *waiters, int val, int priv)
 	}
 	if (waiters) a_inc(waiters);
 	while (*addr==val) {
-		__syscall(SYS_futex, addr, FUTEX_WAIT|priv, val, 0) != -ENOSYS
-		|| __syscall(SYS_futex, addr, FUTEX_WAIT, val, 0);
+		__futexcall(addr, FUTEX_WAIT|priv, val, 0) != -ENOSYS
+		|| __futexcall(addr, FUTEX_WAIT, val, 0);
 	}
 	if (waiters) a_dec(waiters);
 }
diff --git a/src/thread/pthread_barrier_wait.c b/src/thread/pthread_barrier_wait.c
index cc2a8bbf58a9..7e0b8cc9cbe2 100644
--- a/src/thread/pthread_barrier_wait.c
+++ b/src/thread/pthread_barrier_wait.c
@@ -33,7 +33,7 @@ static int pshared_barrier_wait(pthread_barrier_t *b)
 		while ((v=b->_b_count))
 			__wait(&b->_b_count, &b->_b_waiters2, v, 0);
 	}
-	
+
 	/* Perform a recursive unlock suitable for self-sync'd destruction */
 	do {
 		v = b->_b_lock;
@@ -84,8 +84,8 @@ int pthread_barrier_wait(pthread_barrier_t *b)
 			a_spin();
 		a_inc(&inst->finished);
 		while (inst->finished == 1)
-			__syscall(SYS_futex,&inst->finished,FUTEX_WAIT|FUTEX_PRIVATE,1,0) != -ENOSYS
-			|| __syscall(SYS_futex,&inst->finished,FUTEX_WAIT,1,0);
+			__futexcall(&inst->finished,FUTEX_WAIT|FUTEX_PRIVATE,1,0) != -ENOSYS
+			|| __futexcall(&inst->finished,FUTEX_WAIT,1,0);
 		return PTHREAD_BARRIER_SERIAL_THREAD;
 	}
 
diff --git a/src/thread/pthread_cond_timedwait.c b/src/thread/pthread_cond_timedwait.c
index 6b761455c47f..a4386761479b 100644
--- a/src/thread/pthread_cond_timedwait.c
+++ b/src/thread/pthread_cond_timedwait.c
@@ -49,8 +49,8 @@ static inline void unlock_requeue(volatile int *l, volatile int *r, int w)
 {
 	a_store(l, 0);
 	if (w) __wake(l, 1, 1);
-	else __syscall(SYS_futex, l, FUTEX_REQUEUE|FUTEX_PRIVATE, 0, 1, r) != -ENOSYS
-		|| __syscall(SYS_futex, l, FUTEX_REQUEUE, 0, 1, r);
+	else __futexcall(l, FUTEX_REQUEUE|FUTEX_PRIVATE, 0, 1, r) != -ENOSYS
+		|| __futexcall(l, FUTEX_REQUEUE, 0, 1, r);
 }
 
 enum {
@@ -121,12 +121,12 @@ int __pthread_cond_timedwait(pthread_cond_t *restrict c, pthread_mutex_t *restri
 		 * via the futex notify below. */
 
 		lock(&c->_c_lock);
-		
+
 		if (c->_c_head == &node) c->_c_head = node.next;
 		else if (node.prev) node.prev->next = node.next;
 		if (c->_c_tail == &node) c->_c_tail = node.prev;
 		else if (node.next) node.next->prev = node.prev;
-		
+
 		unlock(&c->_c_lock);
 
 		if (node.notify) {
@@ -156,7 +156,7 @@ relock:
 		if (val>0) a_cas(&m->_m_lock, val, val|0x80000000);
 		unlock_requeue(&node.prev->barrier, &m->_m_lock, m->_m_type & (8|128));
 	} else if (!(m->_m_type & 8)) {
-		a_dec(&m->_m_waiters);		
+		a_dec(&m->_m_waiters);
 	}
 
 	/* Since a signal was consumed, cancellation is not permitted. */
diff --git a/src/thread/pthread_mutex_timedlock.c b/src/thread/pthread_mutex_timedlock.c
index 9279fc54308a..1f2f1d862c69 100644
--- a/src/thread/pthread_mutex_timedlock.c
+++ b/src/thread/pthread_mutex_timedlock.c
@@ -8,10 +8,8 @@ static int __futex4(volatile void *addr, int op, int val, const struct timespec
 #ifdef SYS_futex_time64
 	time_t s = to ? to->tv_sec : 0;
 	long ns = to ? to->tv_nsec : 0;
-	int r = -ENOSYS;
-	if (SYS_futex == SYS_futex_time64 || !IS32BIT(s))
-		r = __syscall(SYS_futex_time64, addr, op, val,
-			to ? ((long long[]){s, ns}) : 0);
+	int r = __syscall(SYS_futex_time64, addr, op, val,
+		to ? ((long long[]){s, ns}) : 0);
 	if (SYS_futex == SYS_futex_time64 || r!=-ENOSYS) return r;
 	to = to ? (void *)(long[]){CLAMP(s), ns} : 0;
 #endif
@@ -66,7 +64,7 @@ int __pthread_mutex_timedlock(pthread_mutex_t *restrict m, const struct timespec
 	if (r != EBUSY) return r;
 
 	if (type&8) return pthread_mutex_timedlock_pi(m, at);
-	
+
 	int spins = 100;
 	while (spins-- && m->_m_lock && !m->_m_waiters) a_spin();
 
diff --git a/src/thread/pthread_mutex_trylock.c b/src/thread/pthread_mutex_trylock.c
index a24e7c58ac39..d2a92601b6d3 100644
--- a/src/thread/pthread_mutex_trylock.c
+++ b/src/thread/pthread_mutex_trylock.c
@@ -43,7 +43,7 @@ int __pthread_mutex_trylock_owner(pthread_mutex_t *m)
 success:
 	if ((type&8) && m->_m_waiters) {
 		int priv = (type & 128) ^ 128;
-		__syscall(SYS_futex, &m->_m_lock, FUTEX_UNLOCK_PI|priv);
+		__futexcall(&m->_m_lock, FUTEX_UNLOCK_PI|priv);
 		self->robust_list.pending = 0;
 		return (type&4) ? ENOTRECOVERABLE : EBUSY;
 	}
diff --git a/src/thread/pthread_mutex_unlock.c b/src/thread/pthread_mutex_unlock.c
index b66423e6c34f..0b7da563c516 100644
--- a/src/thread/pthread_mutex_unlock.c
+++ b/src/thread/pthread_mutex_unlock.c
@@ -33,7 +33,7 @@ int __pthread_mutex_unlock(pthread_mutex_t *m)
 	if (type&8) {
 		if (old<0 || a_cas(&m->_m_lock, old, new)!=old) {
 			if (new) a_store(&m->_m_waiters, -1);
-			__syscall(SYS_futex, &m->_m_lock, FUTEX_UNLOCK_PI|priv);
+			__futexcall(&m->_m_lock, FUTEX_UNLOCK_PI|priv);
 		}
 		cont = 0;
 		waiters = 0;
diff --git a/src/thread/pthread_mutexattr_setprotocol.c b/src/thread/pthread_mutexattr_setprotocol.c
index 8b80c1ce9b14..456fb9f48d2e 100644
--- a/src/thread/pthread_mutexattr_setprotocol.c
+++ b/src/thread/pthread_mutexattr_setprotocol.c
@@ -14,7 +14,7 @@ int pthread_mutexattr_setprotocol(pthread_mutexattr_t *a, int protocol)
 		r = check_pi_result;
 		if (r < 0) {
 			volatile int lk = 0;
-			r = -__syscall(SYS_futex, &lk, FUTEX_LOCK_PI, 0, 0);
+			r = -__futexcall(&lk, FUTEX_LOCK_PI, 0, 0);
 			a_store(&check_pi_result, r);
 		}
 		if (r) return r;
-- 
2.29.2


Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.