|
|
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.