]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-117657: Disable the function/code cache in free-threaded builds (#118301)
authormpage <mpage@meta.com>
Fri, 3 May 2024 20:21:04 +0000 (13:21 -0700)
committerGitHub <noreply@github.com>
Fri, 3 May 2024 20:21:04 +0000 (16:21 -0400)
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
Objects/codeobject.c
Objects/funcobject.c
Tools/tsan/suppressions_free_threading.txt

index 24fbb3ddbee602c1f9b5395be963c712abd1e334..6d44e933e8a8cb3ad03291f47a891f60b1938277 100644 (file)
@@ -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
index 810f847485acdab30390325df7172a43638d5e4f..7d02b038cf52caf631a620b2661451d75dc3a13c 100644 (file)
@@ -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 */
index 276b3db29703711e8f1b0a62c0e18402fe9b7a97..8a30213888ef870f4c36907574bd1d45f7129e11 100644 (file)
@@ -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
index 4f6648a7573184002512492c27b3372d3a37cd2b..74dbf4bb1cb6882cad8f2861d41274a414966773 100644 (file)
@@ -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