diff --git a/Doc/data/python3.14.abi b/Doc/data/python3.14.abi index 486c54565c45ae..4f86100cef30a9 100644 --- a/Doc/data/python3.14.abi +++ b/Doc/data/python3.14.abi @@ -1816,7 +1816,7 @@ - + @@ -7136,190 +7136,190 @@ - - + + - - - + + + - - - - + + + + - - - - - + + + + + - - - + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - - - - + + + + - - - - - + + + + + - - + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - + + - - - + + + - - - + + + - - - - + + + + - - - + + + - - - - + + + + - - - + + + - - + + - - - + + + - - - + + + - - + + - - + + - - - - - - + + + + + + @@ -7814,11 +7814,6 @@ - - - - - @@ -7915,37 +7910,37 @@ - - - - + + + + - - - - + + + + - - - - + + + + - - - + + + - - - + + + - - - + + + @@ -7991,6 +7986,10 @@ + + + + @@ -8006,7 +8005,7 @@ - + @@ -8053,69 +8052,69 @@ - + - - - - - - + + + + + + - - - + + + - - - + + + - - + + - - + + - - - + + + - - + + - - + + - - - + + + - - + + - - + + - - + + - - + + - - + + @@ -8139,7 +8138,7 @@ - + @@ -8220,30 +8219,30 @@ - - + + - - + + - + - + - + @@ -8252,6 +8251,11 @@ + + + + + @@ -8274,9 +8278,9 @@ - - - + + + @@ -8290,7 +8294,7 @@ - + @@ -8305,13 +8309,13 @@ - + - + - + @@ -8325,7 +8329,7 @@ - + @@ -8340,22 +8344,22 @@ - + - + - - - - - - - + + + + + + + - + @@ -8368,18 +8372,18 @@ - + - + - + @@ -8388,15 +8392,15 @@ - - + + - + - + @@ -8409,7 +8413,7 @@ - + @@ -8425,11 +8429,11 @@ - + - + @@ -8441,13 +8445,13 @@ - + - + @@ -8455,24 +8459,24 @@ - + - + - - + + - + @@ -8487,7 +8491,7 @@ - + @@ -8514,10 +8518,10 @@ - + - + @@ -8577,7 +8581,7 @@ - + @@ -8607,11 +8611,6 @@ - - - - - @@ -8667,10 +8666,10 @@ - + - + @@ -8918,6 +8917,11 @@ + + + + + @@ -10286,7 +10290,7 @@ - + @@ -10620,31 +10624,31 @@ - - - + + + - - - + + + - - + + - - + + - - - + + + - - + + @@ -10701,7 +10705,7 @@ - + @@ -11120,23 +11124,23 @@ - - - + + + - + - - + + - - - - - + + + + + @@ -11440,13 +11444,13 @@ - + - + @@ -11469,7 +11473,7 @@ - + @@ -11806,7 +11810,7 @@ - + @@ -11819,7 +11823,7 @@ - + @@ -12746,7 +12750,7 @@ - + @@ -12775,18 +12779,18 @@ - + - + - + - + @@ -14478,7 +14482,7 @@ - + @@ -14512,10 +14516,10 @@ - + - + @@ -14632,10 +14636,10 @@ - + - + @@ -14716,7 +14720,7 @@ - + @@ -15088,7 +15092,7 @@ - + @@ -15834,7 +15838,7 @@ - + @@ -15891,7 +15895,7 @@ - + @@ -15960,7 +15964,7 @@ - + @@ -18095,10 +18099,10 @@ - + - + @@ -20663,7 +20667,7 @@ - + @@ -20671,7 +20675,7 @@ - + @@ -21467,7 +21471,7 @@ - + @@ -21588,127 +21592,127 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -21732,12 +21736,12 @@ - + - + @@ -21752,7 +21756,7 @@ - + @@ -22032,7 +22036,7 @@ - + @@ -22043,13 +22047,16 @@ - + - + - + + + + @@ -22195,7 +22202,7 @@ - + @@ -22459,12 +22466,12 @@ - + - + @@ -22591,7 +22598,7 @@ - + @@ -23119,7 +23126,7 @@ - + @@ -23578,7 +23585,7 @@ - + @@ -23622,10 +23629,10 @@ - + - + @@ -24087,7 +24094,7 @@ - + @@ -24117,7 +24124,7 @@ - + @@ -24761,7 +24768,7 @@ - + @@ -25423,20 +25430,20 @@ - + - + - + @@ -25444,7 +25451,7 @@ - + @@ -25452,7 +25459,7 @@ - + @@ -25460,7 +25467,7 @@ - + @@ -25469,24 +25476,24 @@ - + - + - + - + @@ -25548,7 +25555,7 @@ - + @@ -25556,7 +25563,7 @@ - + @@ -25618,11 +25625,11 @@ - + - + @@ -25639,7 +25646,7 @@ - + @@ -25649,11 +25656,11 @@ - - + + - + @@ -25670,7 +25677,7 @@ - + @@ -25703,7 +25710,7 @@ - + @@ -25727,7 +25734,7 @@ - + @@ -25802,7 +25809,7 @@ - + @@ -26231,10 +26238,10 @@ - + - + @@ -27103,41 +27110,41 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -27369,97 +27376,97 @@ - - + + - - + + - - + + - - + + - + - - + + - - + + - - - - + + + + - - - - + + + + - + - - + + - - - - - + + + + + - - - - + + + + - - - + + + - - - - - + + + + + - - - + + + - - + + - - - - - + + + + + - - - - + + + + @@ -27633,42 +27640,42 @@ - - + + - - - + + + - - - - - - + + + + + + - - - - + + + + - - - + + + - + - - - + + + @@ -27937,22 +27944,18 @@ - + - + - + - - - - @@ -28433,104 +28436,104 @@ - - + + - - + + - - + + - - + + - - - - + + + + - - - + + + - - + + - - - + + + - - + + - - - + + + - + - + - - - + + + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - - + + - - + + - - + + - - + + - - - + + + - + @@ -29529,35 +29532,35 @@ - - - - + + + + - - - - + + + + - - + + - - + + - - + + - - + + - + @@ -30539,41 +30542,41 @@ - + - + - - + + - - - + + + - - + + - - + + - - - + + + - - + + - - - + + + @@ -30668,7 +30671,7 @@ - + diff --git a/Include/internal/pycore_qsbr.h b/Include/internal/pycore_qsbr.h index 1f9b3fcf777493..eeca6fc472be37 100644 --- a/Include/internal/pycore_qsbr.h +++ b/Include/internal/pycore_qsbr.h @@ -83,8 +83,9 @@ struct _qsbr_shared { // Minimum observed read sequence of all QSBR thread states uint64_t rd_seq; - // Array of QSBR thread states. + // Array of QSBR thread states (aligned to 64 bytes). struct _qsbr_pad *array; + void *array_raw; // raw allocation pointer (for free) Py_ssize_t size; // Freelist of unused _qsbr_thread_states (protected by mutex) diff --git a/Include/internal/pycore_tstate.h b/Include/internal/pycore_tstate.h index c3ac52bd76613e..87f59c274ac747 100644 --- a/Include/internal/pycore_tstate.h +++ b/Include/internal/pycore_tstate.h @@ -80,6 +80,11 @@ typedef struct _PyThreadStateImpl { uintptr_t c_stack_init_base; uintptr_t c_stack_init_top; +#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]; +#endif } _PyThreadStateImpl; #ifdef __cplusplus diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-06-21-45-52.gh-issue-144438.GI_uB1LR.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-06-21-45-52.gh-issue-144438.GI_uB1LR.rst new file mode 100644 index 00000000000000..3e33e461ae8b5a --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-06-21-45-52.gh-issue-144438.GI_uB1LR.rst @@ -0,0 +1,2 @@ +Align the QSBR thread state array to a 64-byte cache line boundary to +avoid false sharing in the :term:`free-threaded build`. diff --git a/Python/qsbr.c b/Python/qsbr.c index c9fad5c05ef108..203daa0d307172 100644 --- a/Python/qsbr.c +++ b/Python/qsbr.c @@ -84,22 +84,29 @@ grow_thread_array(struct _qsbr_shared *shared) new_size = MIN_ARRAY_SIZE; } - struct _qsbr_pad *array = PyMem_RawCalloc(new_size, sizeof(*array)); - if (array == NULL) { + // Overallocate by 63 bytes so we can align to a 64-byte boundary. + // This avoids potential false sharing between the first entry and other + // allocations. + size_t alignment = 64; + size_t alloc_size = (size_t)new_size * sizeof(struct _qsbr_pad) + alignment - 1; + void *raw = PyMem_RawCalloc(1, alloc_size); + if (raw == NULL) { return -1; } + struct _qsbr_pad *array = _Py_ALIGN_UP(raw, alignment); - struct _qsbr_pad *old = shared->array; - if (old != NULL) { + void *old_raw = shared->array_raw; + if (shared->array != NULL) { memcpy(array, shared->array, shared->size * sizeof(*array)); } shared->array = array; + shared->array_raw = raw; shared->size = new_size; shared->freelist = NULL; initialize_new_array(shared); - PyMem_RawFree(old); + PyMem_RawFree(old_raw); return 0; } @@ -256,8 +263,9 @@ void _Py_qsbr_fini(PyInterpreterState *interp) { struct _qsbr_shared *shared = &interp->qsbr; - PyMem_RawFree(shared->array); + PyMem_RawFree(shared->array_raw); shared->array = NULL; + shared->array_raw = NULL; shared->size = 0; shared->freelist = NULL; }