This is similar to other futex wrappers on futex-internal.
Checked on x86_64-linux-gnu.
---
nptl/pthread_mutex_trylock.c | 9 +++-----
sysdeps/nptl/futex-internal.h | 36 +++++++++++++++++++++++++++++++
sysdeps/nptl/lowlevellock-futex.h | 5 +++++
3 files changed, 44 insertions(+), 6 deletions(-)
@@ -297,12 +297,9 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex)
int private = (robust
? PTHREAD_ROBUST_MUTEX_PSHARED (mutex)
: PTHREAD_MUTEX_PSHARED (mutex));
- int e = INTERNAL_SYSCALL_CALL (futex, &mutex->__data.__lock,
- __lll_private_flag (FUTEX_TRYLOCK_PI,
- private), 0, 0);
-
- if (INTERNAL_SYSCALL_ERROR_P (e)
- && INTERNAL_SYSCALL_ERRNO (e) == EWOULDBLOCK)
+ if (futex_trylock_pi ((unsigned int *) &mutex->__data.__lock,
+ private)
+ == -EWOULDBLOCK)
{
/* The kernel has not yet finished the mutex owner death.
We do not need to ensure ordering wrt another memory
@@ -483,6 +483,42 @@ futex_lock_pi64 (int *futex_word, const struct __timespec64 *abstime,
}
}
+/* This operaration is similar to futex_lock_pi and it is used when the lock
+ information contains stale state (FUTEX_WAITERS and/or FUTEX_OWNER_DIED).
+ User space can not handle this condition in a race-free manner, but kernel
+ might handle it and acquire the futex.
+
+ Returns:
+
+ - 0 if woken by a PI unlock operation or spuriously.
+ - EAGAIN if the futex owner thread ID is about to exit, but has not yet
+ handled the state cleanup.
+ - EDEADLK if the futex is already locked by the caller.
+ - ESRCH if the thread ID int he futex does not exist.
+ - EINVAL is the state is corrupted or if there is a waiter on the
+ futex.
+*/
+static __always_inline int
+futex_trylock_pi (unsigned int *futex_word, int private)
+{
+ int err = lll_futex_trylock_pi ((int *) futex_word, private);
+ switch (err)
+ {
+ case 0:
+ case -EAGAIN: /* EWOULDBLOCK */
+ case -EINTR:
+ case -ESRCH:
+ case -EDEADLK:
+ case -EPERM:
+ return -err;
+
+ case -EINVAL:
+ case -EFAULT:
+ default:
+ futex_fatal_error ();
+ }
+}
+
/* Wakes the top priority waiter that called a futex_lock_pi operation on
the futex.
@@ -144,6 +144,11 @@
__lll_private_flag (FUTEX_LOCK_PI, private), \
0, abstime)
+#define lll_futex_trylock_pi(futexp, private) \
+ lll_futex_syscall (4, futexp, \
+ __lll_private_flag (FUTEX_TRYLOCK_PI, private), \
+ 0, 0)
+
#define lll_futex_timed_unlock_pi(futexp, private) \
lll_futex_syscall (4, futexp, \
__lll_private_flag (FUTEX_UNLOCK_PI, private), \