Skip to content

gh-144438: Fix false sharing between QSBR and tlbc_index#144554

Open
colesbury wants to merge 2 commits intopython:mainfrom
colesbury:gh-144438-qsbr-alignment
Open

gh-144438: Fix false sharing between QSBR and tlbc_index#144554
colesbury wants to merge 2 commits intopython:mainfrom
colesbury:gh-144438-qsbr-alignment

Conversation

@colesbury
Copy link
Contributor

@colesbury colesbury commented Feb 6, 2026

Align the QSBR thread state array to a 64-byte cache line boundary and add padding at the end of _PyThreadStateImpl. Depending on heap layout, the QSBR array could end up sharing a cache line with a thread's tlbc_index, causing QSBR quiescent state updates to contend with reads of tlbc_index in RESUME_CHECK. This is sensitive to earlier allocations during interpreter init and can appear or disappear with seemingly unrelated changes.

Either change alone is sufficient to fix the specific issue, but both are worthwhile to avoid similar problems in the future.

Align the QSBR thread state array to a 64-byte cache line boundary
and add padding at the end of _PyThreadStateImpl. Depending on heap
layout, the QSBR array could end up sharing a cache line with a
thread's tlbc_index, causing QSBR quiescent state updates to contend
with reads of tlbc_index in RESUME_CHECK. This is sensitive to
earlier allocations during interpreter init and can appear or
disappear with seemingly unrelated changes.

Either change alone is sufficient to fix the specific issue, but both
are worthwhile to avoid similar problems in the future.
@colesbury colesbury marked this pull request as ready for review February 6, 2026 23:03
Comment on lines +90 to +96
// allocations.
size_t alloc_size = (size_t)new_size * sizeof(struct _qsbr_pad) + 63;
void *raw = PyMem_RawCalloc(1, alloc_size);
if (raw == NULL) {
return -1;
}
struct _qsbr_pad *array = _Py_ALIGN_UP(raw, 64);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// allocations.
size_t alloc_size = (size_t)new_size * sizeof(struct _qsbr_pad) + 63;
void *raw = PyMem_RawCalloc(1, alloc_size);
if (raw == NULL) {
return -1;
}
struct _qsbr_pad *array = _Py_ALIGN_UP(raw, 64);
// 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);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants