[Bug nptl/33704] RFE: Relax failing pthread_mutex_trylock to load with relaxed MO.
fweimer at redhat dot com
sourceware-bugzilla@sourceware.org
Wed Dec 10 18:41:54 GMT 2025
https://sourceware.org/bugzilla/show_bug.cgi?id=33704
--- Comment #11 from Florian Weimer <fweimer at redhat dot com> ---
My comment 10 is not correct, I will get to that in a minute. But here's what I
did to get a feel for how these functions are used.
I applied this patch:
diff --git a/nptl/pthread_mutex_trylock.c b/nptl/pthread_mutex_trylock.c
index 94621cc254..6ef9e9bedf 100644
--- a/nptl/pthread_mutex_trylock.c
+++ b/nptl/pthread_mutex_trylock.c
@@ -22,6 +22,8 @@
#include <lowlevellock.h>
#include <futex-internal.h>
+#include <stap-probe.h>
+
int
___pthread_mutex_trylock (pthread_mutex_t *mutex)
{
@@ -44,6 +46,7 @@ ___pthread_mutex_trylock (pthread_mutex_t *mutex)
return EAGAIN;
++mutex->__data.__count;
+ LIBC_PROBE (mutex_trylock_recursive_recurse, 1, mutex);
return 0;
}
@@ -53,20 +56,26 @@ ___pthread_mutex_trylock (pthread_mutex_t *mutex)
mutex->__data.__owner = id;
mutex->__data.__count = 1;
++mutex->__data.__nusers;
+ LIBC_PROBE (mutex_trylock_recursive_success, 1, mutex);
return 0;
}
+ LIBC_PROBE (mutex_trylock_recursive_fail, 1, mutex);
break;
case PTHREAD_MUTEX_TIMED_NP:
case PTHREAD_MUTEX_ADAPTIVE_NP:
case PTHREAD_MUTEX_ERRORCHECK_NP:
if (lll_trylock (mutex->__data.__lock) != 0)
- break;
+ {
+ LIBC_PROBE (mutex_trylock_fail, 1, mutex);
+ break;
+ }
/* Record the ownership. */
mutex->__data.__owner = id;
++mutex->__data.__nusers;
+ LIBC_PROBE (mutex_trylock_success, 1, mutex);
return 0;
case PTHREAD_MUTEX_ROBUST_RECURSIVE_NP:
Installed this glibc system-wide, and rebooted for good measure. Then run this
stap probe:
“
global success
global fail
global rec_success
global rec_recurse
global rec_fail
probe process("/lib64/libc.so.6").mark("mutex_trylock_success") {
success <<< 1
}
probe process("/lib64/libc.so.6").mark("mutex_trylock_fail") {
fail <<< 1
}
probe process("/lib64/libc.so.6").mark("mutex_trylock_recursive_recurse") {
rec_recurse <<< 1
}
probe process("/lib64/libc.so.6").mark("mutex_trylock_recursive_success") {
rec_success <<< 1
}
probe process("/lib64/libc.so.6").mark("mutex_trylock_recursive_fail") {
rec_fail <<< 1
}
probe timer.s(1) {
printf("success=%d fail=%d recurse=%d rec_success=%d rec_fail=%d\n",
@count(success),
@count(fail),
@count(rec_recurse),
@count(rec_success),
@count(rec_fail))
delete success
delete fail
delete rec_recurse
delete rec_success
delete rec_fail
}
“
My regular desktop does not show much of trylock activity. But running Gmail in
Chromium results in this:
success=223549 fail=919 recurse=0 rec_success=0 rec_fail=0
success=39439 fail=109 recurse=0 rec_success=1 rec_fail=0
success=61005 fail=179 recurse=0 rec_success=0 rec_fail=0
success=161705 fail=566 recurse=0 rec_success=0 rec_fail=0
success=284841 fail=1779 recurse=0 rec_success=1 rec_fail=0
After a while the background activity drops to this:
success=365 fail=0 recurse=0 rec_success=0 rec_fail=0
success=187 fail=0 recurse=0 rec_success=0 rec_fail=0
success=207 fail=0 recurse=0 rec_success=0 rec_fail=0
success=5983 fail=9 recurse=0 rec_success=0 rec_fail=0
success=1596 fail=2 recurse=0 rec_success=0 rec_fail=0
success=9831 fail=8 recurse=0 rec_success=0 rec_fail=0
success=530 fail=0 recurse=0 rec_success=0 rec_fail=0
Anyway, my point is that a succeeding trylock in common workloads is much, much
more common than a failing trylock, so it makes sense to optimize for a
successful trylock.
However, I'm still wrong because we first read the type of the mutex. So this
is likely to bring in the cache line in a shared configuration anyway. After
that, the extra check on the lock field before the CAS should be basically
free. So your patch doesn't seem unreasonable.
--
You are receiving this mail because:
You are on the CC list for the bug.
More information about the Glibc-bugs
mailing list