https://github.com/python/cpython/commit/39bc958bf9beeb0eb5357d9d722a23ce7a6ce25d
commit: 39bc958bf9beeb0eb5357d9d722a23ce7a6ce25d
branch: main
author: Gr4ph0s <[email protected]>
committer: corona10 <[email protected]>
date: 2026-10-20T20:06:55Z
summary:

gh-159860: Adjust QSBR cache line size from 64 to 128 on AArch64 (gh-159862)

files:
A 
Misc/NEWS.d/next/Core_and_Builtins/2026-10-19-21-30-00.gh-issue-159860.qsbr128.rst
M Include/internal/pycore_qsbr.h
M Include/internal/pycore_tstate.h
M Python/qsbr.c

diff --git a/Include/internal/pycore_qsbr.h b/Include/internal/pycore_qsbr.h
index eeca6fc472be37..91d3415614b154 100644
--- a/Include/internal/pycore_qsbr.h
+++ b/Include/internal/pycore_qsbr.h
@@ -69,10 +69,25 @@ struct _qsbr_thread_state {
     struct _qsbr_thread_state *freelist_next;
 };
 
+// Size used to pad and align the per-thread QSBR states (and the end of
+// _PyThreadStateImpl) to avoid false sharing. Apple Silicon has 128-byte cache
+// lines:
+//   $ sysctl -a hw | grep cachelinesize
+//   hw.cachelinesize: 128
+// With 64-byte padding the `seq` fields of two threads share a line and the
+// stores in _Py_qsbr_quiescent_state() contend on every eval loop back-edge.
+// Use 128 bytes for all AArch64 targets: on cores with 64-byte lines this only
+// costs 64 bytes per thread.
+#if defined(__aarch64__) || defined(_M_ARM64)
+#  define _Py_QSBR_CACHE_LINE_SIZE 128
+#else
+#  define _Py_QSBR_CACHE_LINE_SIZE 64
+#endif
+
 // Padding to avoid false sharing
 struct _qsbr_pad {
     struct _qsbr_thread_state qsbr;
-    char __padding[64 - sizeof(struct _qsbr_thread_state)];
+    char __padding[_Py_QSBR_CACHE_LINE_SIZE - sizeof(struct 
_qsbr_thread_state)];
 };
 
 // Per-interpreter state
@@ -83,7 +98,7 @@ struct _qsbr_shared {
     // Minimum observed read sequence of all QSBR thread states
     uint64_t rd_seq;
 
-    // Array of QSBR thread states (aligned to 64 bytes).
+    // Array of QSBR thread states (aligned to _Py_QSBR_CACHE_LINE_SIZE).
     struct _qsbr_pad *array;
     void *array_raw;   // raw allocation pointer (for free)
     Py_ssize_t size;
diff --git a/Include/internal/pycore_tstate.h b/Include/internal/pycore_tstate.h
index 58dd66b69efc9d..f1d8c4ba0d04e5 100644
--- a/Include/internal/pycore_tstate.h
+++ b/Include/internal/pycore_tstate.h
@@ -109,7 +109,7 @@ typedef struct _PyThreadStateImpl {
 #ifdef Py_GIL_DISABLED
     // gh-144438: Add padding to ensure that the fields above don't share a
     // cache line with other allocations.
-    char __padding[64];
+    char __padding[_Py_QSBR_CACHE_LINE_SIZE];
 #endif
 } _PyThreadStateImpl;
 
diff --git 
a/Misc/NEWS.d/next/Core_and_Builtins/2026-10-19-21-30-00.gh-issue-159860.qsbr128.rst
 
b/Misc/NEWS.d/next/Core_and_Builtins/2026-10-19-21-30-00.gh-issue-159860.qsbr128.rst
new file mode 100644
index 00000000000000..fc0d6fca4f7996
--- /dev/null
+++ 
b/Misc/NEWS.d/next/Core_and_Builtins/2026-10-19-21-30-00.gh-issue-159860.qsbr128.rst
@@ -0,0 +1,4 @@
+Fix false sharing between the per-thread QSBR states in the
+:term:`free-threaded build` on AArch64 CPUs with 128-byte cache lines, such
+as Apple Silicon. CPU-bound threads that share no objects now scale like
+processes there.
diff --git a/Python/qsbr.c b/Python/qsbr.c
index e9d935bfb40d84..a50d66e3e9e7ae 100644
--- a/Python/qsbr.c
+++ b/Python/qsbr.c
@@ -85,10 +85,10 @@ grow_thread_array(struct _qsbr_shared *shared)
         new_size = MIN_ARRAY_SIZE;
     }
 
-    // Overallocate by 63 bytes so we can align to a 64-byte boundary.
+    // Overallocate so we can align to a cache line boundary.
     // This avoids potential false sharing between the first entry and other
     // allocations.
-    size_t alignment = 64;
+    size_t alignment = _Py_QSBR_CACHE_LINE_SIZE;
     size_t alloc_size = (size_t)new_size * sizeof(struct _qsbr_pad) + 
alignment - 1;
     void *raw = PyMem_RawCalloc(1, alloc_size);
     if (raw == NULL) {

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to