git: 99edcc3bd526 - main - libthr: Reorder pthread mutex to prevent false sharing
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 07 Oct 2026 17:06:35 UTC
The branch main has been updated by aokblast:
URL: https://cgit.FreeBSD.org/src/commit/?id=99edcc3bd52614c6cf972ea8424a7807ed3fe1e3
commit 99edcc3bd52614c6cf972ea8424a7807ed3fe1e3
Author: ShengYi Hung <aokblast@FreeBSD.org>
AuthorDate: 2026-10-07 07:22:13 +0000
Commit: ShengYi Hung <aokblast@FreeBSD.org>
CommitDate: 2026-10-07 17:05:58 +0000
libthr: Reorder pthread mutex to prevent false sharing
On a 64 byte cache line CPU (amd64), m_owner is contended by all of
the shared processes. However, after finding one winner, mtx is
enqueued, which trigger a cache refresh from other processors. Reorder
mtx so that m_lock and m_qu will not be in the same cache line.
Notice that this doesn't affet arch that expose 128 bytes cache line
line aarch64 or powerpc.
Reviewed by: kib, markj
MFC after: 2 weeks
Differential Revision: https://reviews.freebsd.org/D60434
---
lib/libthr/thread/thr_mutex.c | 9 +++++++++
lib/libthr/thread/thr_private.h | 6 +++++-
2 files changed, 14 insertions(+), 1 deletion(-)
diff --git a/lib/libthr/thread/thr_mutex.c b/lib/libthr/thread/thr_mutex.c
index ccb3094db16d..139dc768b7ba 100644
--- a/lib/libthr/thread/thr_mutex.c
+++ b/lib/libthr/thread/thr_mutex.c
@@ -53,6 +53,15 @@
_Static_assert(sizeof(struct pthread_mutex) <= THR_PAGE_SIZE_MIN,
"pthread_mutex is too large for off-page");
+/*
+ * Keep the thread-private linkage off the cache line holding the lock word;
+ * Only meaningful where cache line is 64 bytes.
+ */
+#if defined(__LP64__) && CACHE_LINE_SIZE == 64
+_Static_assert(offsetof(struct pthread_mutex, m_qe) >= CACHE_LINE_SIZE,
+ "m_qe must not share a cache line with m_lock.m_owner");
+#endif
+
/*
* For adaptive mutexes, how many times to spin doing trylock2
* before entering the kernel to block
diff --git a/lib/libthr/thread/thr_private.h b/lib/libthr/thread/thr_private.h
index 2edf09d761ae..cf90ac5bd4ef 100644
--- a/lib/libthr/thread/thr_private.h
+++ b/lib/libthr/thread/thr_private.h
@@ -171,6 +171,11 @@ struct pthread_mutex {
int m_spinloops;
int m_yieldloops;
int m_ps; /* pshared init stage */
+ /*
+ * Deliberately put m_qe and m_lock into different cache line to prevent
+ * false sharing.
+ */
+ struct pthread_mutex *m_rb_prev;
/*
* Link for all mutexes a thread currently owns, of the same
* prio type.
@@ -178,7 +183,6 @@ struct pthread_mutex {
TAILQ_ENTRY(pthread_mutex) m_qe;
/* Link for all private mutexes a thread currently owns. */
TAILQ_ENTRY(pthread_mutex) m_pqe;
- struct pthread_mutex *m_rb_prev;
};
struct pthread_mutex_attr {