diff --git a/Include/internal/pycore_backoff.h b/Include/internal/pycore_backoff.h index 38dd82f6fc8a140..9d1912cc28921c3 100644 --- a/Include/internal/pycore_backoff.h +++ b/Include/internal/pycore_backoff.h @@ -108,6 +108,12 @@ backoff_counter_triggers(_Py_BackoffCounter counter) return counter.value_and_backoff < UNREACHABLE_BACKOFF; } +static inline bool +backoff_counter_is_unreachable(_Py_BackoffCounter counter) +{ + return (counter.value_and_backoff & BACKOFF_MASK) == UNREACHABLE_BACKOFF; +} + static inline _Py_BackoffCounter trigger_backoff_counter(void) { diff --git a/Lib/test/test_thread_local_bytecode.py b/Lib/test/test_thread_local_bytecode.py index 6a1ae4064b5daf1..6f76f1bc33561fb 100644 --- a/Lib/test/test_thread_local_bytecode.py +++ b/Lib/test/test_thread_local_bytecode.py @@ -108,7 +108,6 @@ def f(a, b, q=None): """) assert_python_ok("-X", "tlbc=1", "-c", code) - @support.skip_if_sanitizer("gh-129752: data race on adaptive counter", thread=True) def test_no_copies_if_tlbc_disabled(self): code = textwrap.dedent(""" import queue diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-08-11-01-45-24.gh-issue-129752.Zo3OUx.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-08-11-01-45-24.gh-issue-129752.Zo3OUx.rst new file mode 100644 index 000000000000000..aad13dc0adef34f --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-08-11-01-45-24.gh-issue-129752.Zo3OUx.rst @@ -0,0 +1,2 @@ +Don't update adaptive counters in the free-threaded build when thread-local +bytecode is disabled (``-X tlbc=0``). Patch by Donghee Na. diff --git a/Python/ceval_macros.h b/Python/ceval_macros.h index f19adfa0cfcfc15..e8ce9d84bbff9c6 100644 --- a/Python/ceval_macros.h +++ b/Python/ceval_macros.h @@ -354,6 +354,23 @@ static void dtrace_function_return(_PyInterpreterFrame *); #define ADAPTIVE_COUNTER_TRIGGERS(COUNTER) \ backoff_counter_triggers(forge_backoff_counter((COUNTER))) +#ifdef Py_GIL_DISABLED +/* Counters are unreachable when thread-local bytecode is disabled, + * so there is no need to update them. */ +#define ADVANCE_ADAPTIVE_COUNTER(COUNTER) \ + do { \ + if (!backoff_counter_is_unreachable((COUNTER))) { \ + (COUNTER) = advance_backoff_counter((COUNTER)); \ + } \ + } while (0); + +#define PAUSE_ADAPTIVE_COUNTER(COUNTER) \ + do { \ + if (!backoff_counter_is_unreachable((COUNTER))) { \ + (COUNTER) = pause_backoff_counter((COUNTER)); \ + } \ + } while (0); +#else #define ADVANCE_ADAPTIVE_COUNTER(COUNTER) \ do { \ (COUNTER) = advance_backoff_counter((COUNTER)); \ @@ -363,6 +380,7 @@ static void dtrace_function_return(_PyInterpreterFrame *); do { \ (COUNTER) = pause_backoff_counter((COUNTER)); \ } while (0); +#endif #ifdef ENABLE_SPECIALIZATION /* Multiple threads may execute these concurrently if thread-local bytecode is