From 13264ca8fc70dccda2bfa617fac3033042624e25 Mon Sep 17 00:00:00 2001 From: Matt Page Date: Thu, 25 Apr 2024 16:06:46 -0700 Subject: [PATCH 1/2] Disable the function/code cache in free-threaded builds This is only used by the specializing interpreter and the tier 2 optimizer, both of which are disabled in free-threaded builds. [Sample race](https://gist.github.com/mpage/d05a1c4616eedc9337f3f335e6485f91) that is fixed. --- 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 24fbb3ddbee602..5b21eb96a3c45f 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 014632962bfcf3..14a12590361902 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 276b3db2970371..8a30213888ef87 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 e4ca32bebc5a22..06874d4982215c 100644 --- a/Tools/tsan/suppressions_free_threading.txt +++ b/Tools/tsan/suppressions_free_threading.txt @@ -16,7 +16,6 @@ race:_in_weak_set race:_mi_heap_delayed_free_partial race:_Py_IsOwnedByCurrentThread race:_PyEval_EvalFrameDefault -race:_PyFunction_SetVersion race:_PyImport_AcquireLock race:_PyImport_ReleaseLock race:_PyInterpreterState_SetNotRunningMain From 912fed24d8c3d2c81466ea27cd41ae6ce0e7ac83 Mon Sep 17 00:00:00 2001 From: Matt Page Date: Thu, 25 Apr 2024 18:24:24 -0700 Subject: [PATCH 2/2] Fix indentation --- Include/internal/pycore_function.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Include/internal/pycore_function.h b/Include/internal/pycore_function.h index 5b21eb96a3c45f..6d44e933e8a8cb 100644 --- a/Include/internal/pycore_function.h +++ b/Include/internal/pycore_function.h @@ -26,10 +26,10 @@ struct _func_version_cache_item { }; struct _py_func_state { - #ifdef Py_GIL_DISABLED +#ifdef Py_GIL_DISABLED // Protects next_version PyMutex mutex; - #endif +#endif uint32_t next_version; // Borrowed references to function and code objects whose pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy