From 37d095002216a4e45b4e82539ca0421ded8aaae3 Mon Sep 17 00:00:00 2001 From: mpage Date: Fri, 3 May 2024 13:21:04 -0700 Subject: [PATCH] gh-117657: Disable the function/code cache in free-threaded builds (#118301) This is only used by the specializing interpreter and the tier 2 optimizer, both of which are disabled in free-threaded builds. --- Include/internal/pycore_function.h | 7 +++++++ Objects/codeobject.c | 6 ++++++ Objects/funcobject.c | 10 ++++++++++ Tools/tsan/suppressions_free_threading.txt | 1 - 4 files changed, 23 insertions(+), 1 deletion(-) diff --git a/Include/internal/pycore_function.h b/Include/internal/pycore_function.h index 24fbb3ddbee..6d44e933e8a 100644 --- a/Include/internal/pycore_function.h +++ b/Include/internal/pycore_function.h @@ -4,6 +4,8 @@ extern "C" { #endif +#include "pycore_lock.h" + #ifndef Py_BUILD_CORE # error "this header requires Py_BUILD_CORE define" #endif @@ -24,6 +26,11 @@ struct _func_version_cache_item { }; struct _py_func_state { +#ifdef Py_GIL_DISABLED + // Protects next_version + PyMutex mutex; +#endif + uint32_t next_version; // Borrowed references to function and code objects whose // func_version % FUNC_VERSION_CACHE_SIZE diff --git a/Objects/codeobject.c b/Objects/codeobject.c index 810f847485a..7d02b038cf5 100644 --- a/Objects/codeobject.c +++ b/Objects/codeobject.c @@ -416,10 +416,16 @@ init_code(PyCodeObject *co, struct _PyCodeConstructor *con) co->co_ncellvars = ncellvars; co->co_nfreevars = nfreevars; PyInterpreterState *interp = _PyInterpreterState_GET(); +#ifdef Py_GIL_DISABLED + PyMutex_Lock(&interp->func_state.mutex); +#endif co->co_version = interp->func_state.next_version; if (interp->func_state.next_version != 0) { interp->func_state.next_version++; } +#ifdef Py_GIL_DISABLED + PyMutex_Unlock(&interp->func_state.mutex); +#endif co->_co_monitoring = NULL; co->_co_instrumentation_version = 0; /* not set */ diff --git a/Objects/funcobject.c b/Objects/funcobject.c index 276b3db2970..8a30213888e 100644 --- a/Objects/funcobject.c +++ b/Objects/funcobject.c @@ -287,6 +287,7 @@ functions is running. void _PyFunction_SetVersion(PyFunctionObject *func, uint32_t version) { +#ifndef Py_GIL_DISABLED PyInterpreterState *interp = _PyInterpreterState_GET(); if (func->func_version != 0) { struct _func_version_cache_item *slot = @@ -297,7 +298,9 @@ _PyFunction_SetVersion(PyFunctionObject *func, uint32_t version) // Leave slot->code alone, there may be use for it. } } +#endif func->func_version = version; +#ifndef Py_GIL_DISABLED if (version != 0) { struct _func_version_cache_item *slot = interp->func_state.func_version_cache @@ -305,11 +308,13 @@ _PyFunction_SetVersion(PyFunctionObject *func, uint32_t version) slot->func = func; slot->code = func->func_code; } +#endif } void _PyFunction_ClearCodeByVersion(uint32_t version) { +#ifndef Py_GIL_DISABLED PyInterpreterState *interp = _PyInterpreterState_GET(); struct _func_version_cache_item *slot = interp->func_state.func_version_cache @@ -322,11 +327,15 @@ _PyFunction_ClearCodeByVersion(uint32_t version) slot->func = NULL; } } +#endif } PyFunctionObject * _PyFunction_LookupByVersion(uint32_t version, PyObject **p_code) { +#ifdef Py_GIL_DISABLED + return NULL; +#else PyInterpreterState *interp = _PyInterpreterState_GET(); struct _func_version_cache_item *slot = interp->func_state.func_version_cache @@ -346,6 +355,7 @@ _PyFunction_LookupByVersion(uint32_t version, PyObject **p_code) return slot->func; } return NULL; +#endif } uint32_t diff --git a/Tools/tsan/suppressions_free_threading.txt b/Tools/tsan/suppressions_free_threading.txt index 4f6648a7573..74dbf4bb1cb 100644 --- a/Tools/tsan/suppressions_free_threading.txt +++ b/Tools/tsan/suppressions_free_threading.txt @@ -15,7 +15,6 @@ race:_add_to_weak_set race:_in_weak_set race:_mi_heap_delayed_free_partial race:_PyEval_EvalFrameDefault -race:_PyFunction_SetVersion race:_PyImport_AcquireLock race:_PyImport_ReleaseLock race:_PyInterpreterState_SetNotRunningMain