mirror of
https://github.com/python/cpython.git
synced 2025-10-31 21:51:50 +00:00
gh-137514: Add a free-threading wrapper for mutexes (GH-137515)
Add `FT_MUTEX_LOCK`/`FT_MUTEX_UNLOCK`, which call `PyMutex_Lock` and `PyMutex_Unlock` on the free-threaded build, and no-op otherwise.
This commit is contained in:
parent
dec624e0af
commit
082f370cdd
9 changed files with 44 additions and 88 deletions
|
|
@ -111,6 +111,8 @@ extern "C" {
|
||||||
_Py_atomic_load_ullong_relaxed(&value)
|
_Py_atomic_load_ullong_relaxed(&value)
|
||||||
#define FT_ATOMIC_ADD_SSIZE(value, new_value) \
|
#define FT_ATOMIC_ADD_SSIZE(value, new_value) \
|
||||||
(void)_Py_atomic_add_ssize(&value, new_value)
|
(void)_Py_atomic_add_ssize(&value, new_value)
|
||||||
|
#define FT_MUTEX_LOCK(lock) PyMutex_Lock(lock)
|
||||||
|
#define FT_MUTEX_UNLOCK(lock) PyMutex_Unlock(lock)
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#define FT_ATOMIC_LOAD_PTR(value) value
|
#define FT_ATOMIC_LOAD_PTR(value) value
|
||||||
|
|
@ -159,6 +161,8 @@ extern "C" {
|
||||||
#define FT_ATOMIC_LOAD_ULLONG_RELAXED(value) value
|
#define FT_ATOMIC_LOAD_ULLONG_RELAXED(value) value
|
||||||
#define FT_ATOMIC_STORE_ULLONG_RELAXED(value, new_value) value = new_value
|
#define FT_ATOMIC_STORE_ULLONG_RELAXED(value, new_value) value = new_value
|
||||||
#define FT_ATOMIC_ADD_SSIZE(value, new_value) (void)(value += new_value)
|
#define FT_ATOMIC_ADD_SSIZE(value, new_value) (void)(value += new_value)
|
||||||
|
#define FT_MUTEX_LOCK(lock) do {} while (0)
|
||||||
|
#define FT_MUTEX_UNLOCK(lock) do {} while (0)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,11 +30,6 @@
|
||||||
|
|
||||||
#ifdef Py_GIL_DISABLED
|
#ifdef Py_GIL_DISABLED
|
||||||
static PyMutex malloc_closure_lock;
|
static PyMutex malloc_closure_lock;
|
||||||
# define MALLOC_CLOSURE_LOCK() PyMutex_Lock(&malloc_closure_lock)
|
|
||||||
# define MALLOC_CLOSURE_UNLOCK() PyMutex_Unlock(&malloc_closure_lock)
|
|
||||||
#else
|
|
||||||
# define MALLOC_CLOSURE_LOCK() ((void)0)
|
|
||||||
# define MALLOC_CLOSURE_UNLOCK() ((void)0)
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef union _tagITEM {
|
typedef union _tagITEM {
|
||||||
|
|
@ -120,11 +115,11 @@ void Py_ffi_closure_free(void *p)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
MALLOC_CLOSURE_LOCK();
|
FT_MUTEX_LOCK(&malloc_closure_lock);
|
||||||
ITEM *item = (ITEM *)p;
|
ITEM *item = (ITEM *)p;
|
||||||
item->next = free_list;
|
item->next = free_list;
|
||||||
free_list = item;
|
free_list = item;
|
||||||
MALLOC_CLOSURE_UNLOCK();
|
FT_MUTEX_UNLOCK(&malloc_closure_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* return one item from the free list, allocating more if needed */
|
/* return one item from the free list, allocating more if needed */
|
||||||
|
|
@ -143,13 +138,13 @@ void *Py_ffi_closure_alloc(size_t size, void** codeloc)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
MALLOC_CLOSURE_LOCK();
|
FT_MUTEX_LOCK(&malloc_closure_lock);
|
||||||
ITEM *item;
|
ITEM *item;
|
||||||
if (!free_list) {
|
if (!free_list) {
|
||||||
more_core();
|
more_core();
|
||||||
}
|
}
|
||||||
if (!free_list) {
|
if (!free_list) {
|
||||||
MALLOC_CLOSURE_UNLOCK();
|
FT_MUTEX_UNLOCK(&malloc_closure_lock);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
item = free_list;
|
item = free_list;
|
||||||
|
|
@ -160,6 +155,6 @@ void *Py_ffi_closure_alloc(size_t size, void** codeloc)
|
||||||
#else
|
#else
|
||||||
*codeloc = (void *)item;
|
*codeloc = (void *)item;
|
||||||
#endif
|
#endif
|
||||||
MALLOC_CLOSURE_UNLOCK();
|
FT_MUTEX_UNLOCK(&malloc_closure_lock);
|
||||||
return (void *)item;
|
return (void *)item;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -550,16 +550,12 @@ init_code(PyCodeObject *co, struct _PyCodeConstructor *con)
|
||||||
co->co_framesize = nlocalsplus + con->stacksize + FRAME_SPECIALS_SIZE;
|
co->co_framesize = nlocalsplus + con->stacksize + FRAME_SPECIALS_SIZE;
|
||||||
co->co_ncellvars = ncellvars;
|
co->co_ncellvars = ncellvars;
|
||||||
co->co_nfreevars = nfreevars;
|
co->co_nfreevars = nfreevars;
|
||||||
#ifdef Py_GIL_DISABLED
|
FT_MUTEX_LOCK(&interp->func_state.mutex);
|
||||||
PyMutex_Lock(&interp->func_state.mutex);
|
|
||||||
#endif
|
|
||||||
co->co_version = interp->func_state.next_version;
|
co->co_version = interp->func_state.next_version;
|
||||||
if (interp->func_state.next_version != 0) {
|
if (interp->func_state.next_version != 0) {
|
||||||
interp->func_state.next_version++;
|
interp->func_state.next_version++;
|
||||||
}
|
}
|
||||||
#ifdef Py_GIL_DISABLED
|
FT_MUTEX_UNLOCK(&interp->func_state.mutex);
|
||||||
PyMutex_Unlock(&interp->func_state.mutex);
|
|
||||||
#endif
|
|
||||||
co->_co_monitoring = NULL;
|
co->_co_monitoring = NULL;
|
||||||
co->_co_instrumentation_version = 0;
|
co->_co_instrumentation_version = 0;
|
||||||
/* not set */
|
/* not set */
|
||||||
|
|
@ -689,7 +685,7 @@ intern_code_constants(struct _PyCodeConstructor *con)
|
||||||
#ifdef Py_GIL_DISABLED
|
#ifdef Py_GIL_DISABLED
|
||||||
PyInterpreterState *interp = _PyInterpreterState_GET();
|
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||||
struct _py_code_state *state = &interp->code_state;
|
struct _py_code_state *state = &interp->code_state;
|
||||||
PyMutex_Lock(&state->mutex);
|
FT_MUTEX_LOCK(&state->mutex);
|
||||||
#endif
|
#endif
|
||||||
if (intern_strings(con->names) < 0) {
|
if (intern_strings(con->names) < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
|
|
@ -700,15 +696,11 @@ intern_code_constants(struct _PyCodeConstructor *con)
|
||||||
if (intern_strings(con->localsplusnames) < 0) {
|
if (intern_strings(con->localsplusnames) < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
#ifdef Py_GIL_DISABLED
|
FT_MUTEX_UNLOCK(&state->mutex);
|
||||||
PyMutex_Unlock(&state->mutex);
|
|
||||||
#endif
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
#ifdef Py_GIL_DISABLED
|
FT_MUTEX_UNLOCK(&state->mutex);
|
||||||
PyMutex_Unlock(&state->mutex);
|
|
||||||
#endif
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -114,14 +114,6 @@ NOTE: In the interpreter's initialization phase, some globals are currently
|
||||||
# define _PyUnicode_CHECK(op) PyUnicode_Check(op)
|
# define _PyUnicode_CHECK(op) PyUnicode_Check(op)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef Py_GIL_DISABLED
|
|
||||||
# define LOCK_INTERNED(interp) PyMutex_Lock(&_Py_INTERP_CACHED_OBJECT(interp, interned_mutex))
|
|
||||||
# define UNLOCK_INTERNED(interp) PyMutex_Unlock(&_Py_INTERP_CACHED_OBJECT(interp, interned_mutex))
|
|
||||||
#else
|
|
||||||
# define LOCK_INTERNED(interp)
|
|
||||||
# define UNLOCK_INTERNED(interp)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static inline char* _PyUnicode_UTF8(PyObject *op)
|
static inline char* _PyUnicode_UTF8(PyObject *op)
|
||||||
{
|
{
|
||||||
return FT_ATOMIC_LOAD_PTR_ACQUIRE(_PyCompactUnicodeObject_CAST(op)->utf8);
|
return FT_ATOMIC_LOAD_PTR_ACQUIRE(_PyCompactUnicodeObject_CAST(op)->utf8);
|
||||||
|
|
@ -15988,14 +15980,16 @@ intern_common(PyInterpreterState *interp, PyObject *s /* stolen */,
|
||||||
/* Do a setdefault on the per-interpreter cache. */
|
/* Do a setdefault on the per-interpreter cache. */
|
||||||
PyObject *interned = get_interned_dict(interp);
|
PyObject *interned = get_interned_dict(interp);
|
||||||
assert(interned != NULL);
|
assert(interned != NULL);
|
||||||
|
#ifdef Py_GIL_DISABLED
|
||||||
LOCK_INTERNED(interp);
|
# define INTERN_MUTEX &_Py_INTERP_CACHED_OBJECT(interp, interned_mutex)
|
||||||
|
#endif
|
||||||
|
FT_MUTEX_LOCK(INTERN_MUTEX);
|
||||||
PyObject *t;
|
PyObject *t;
|
||||||
{
|
{
|
||||||
int res = PyDict_SetDefaultRef(interned, s, s, &t);
|
int res = PyDict_SetDefaultRef(interned, s, s, &t);
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
PyErr_Clear();
|
PyErr_Clear();
|
||||||
UNLOCK_INTERNED(interp);
|
FT_MUTEX_UNLOCK(INTERN_MUTEX);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
else if (res == 1) {
|
else if (res == 1) {
|
||||||
|
|
@ -16005,7 +15999,7 @@ intern_common(PyInterpreterState *interp, PyObject *s /* stolen */,
|
||||||
PyUnicode_CHECK_INTERNED(t) == SSTATE_INTERNED_MORTAL) {
|
PyUnicode_CHECK_INTERNED(t) == SSTATE_INTERNED_MORTAL) {
|
||||||
immortalize_interned(t);
|
immortalize_interned(t);
|
||||||
}
|
}
|
||||||
UNLOCK_INTERNED(interp);
|
FT_MUTEX_UNLOCK(INTERN_MUTEX);
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
@ -16038,7 +16032,7 @@ intern_common(PyInterpreterState *interp, PyObject *s /* stolen */,
|
||||||
immortalize_interned(s);
|
immortalize_interned(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
UNLOCK_INTERNED(interp);
|
FT_MUTEX_UNLOCK(INTERN_MUTEX);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
#include "pycore_pyerrors.h" // PyExc_IncompleteInputError
|
#include "pycore_pyerrors.h" // PyExc_IncompleteInputError
|
||||||
#include "pycore_runtime.h" // _PyRuntime
|
#include "pycore_runtime.h" // _PyRuntime
|
||||||
#include "pycore_unicodeobject.h" // _PyUnicode_InternImmortal
|
#include "pycore_unicodeobject.h" // _PyUnicode_InternImmortal
|
||||||
|
#include "pycore_pyatomic_ft_wrappers.h"
|
||||||
#include <errcode.h>
|
#include <errcode.h>
|
||||||
|
|
||||||
#include "lexer/lexer.h"
|
#include "lexer/lexer.h"
|
||||||
|
|
@ -299,22 +300,14 @@ _PyPegen_fill_token(Parser *p)
|
||||||
#define NSTATISTICS _PYPEGEN_NSTATISTICS
|
#define NSTATISTICS _PYPEGEN_NSTATISTICS
|
||||||
#define memo_statistics _PyRuntime.parser.memo_statistics
|
#define memo_statistics _PyRuntime.parser.memo_statistics
|
||||||
|
|
||||||
#ifdef Py_GIL_DISABLED
|
|
||||||
#define MUTEX_LOCK() PyMutex_Lock(&_PyRuntime.parser.mutex)
|
|
||||||
#define MUTEX_UNLOCK() PyMutex_Unlock(&_PyRuntime.parser.mutex)
|
|
||||||
#else
|
|
||||||
#define MUTEX_LOCK()
|
|
||||||
#define MUTEX_UNLOCK()
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void
|
void
|
||||||
_PyPegen_clear_memo_statistics(void)
|
_PyPegen_clear_memo_statistics(void)
|
||||||
{
|
{
|
||||||
MUTEX_LOCK();
|
FT_MUTEX_LOCK(&_PyRuntime.parser.mutex);
|
||||||
for (int i = 0; i < NSTATISTICS; i++) {
|
for (int i = 0; i < NSTATISTICS; i++) {
|
||||||
memo_statistics[i] = 0;
|
memo_statistics[i] = 0;
|
||||||
}
|
}
|
||||||
MUTEX_UNLOCK();
|
FT_MUTEX_UNLOCK(&_PyRuntime.parser.mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject *
|
PyObject *
|
||||||
|
|
@ -325,22 +318,22 @@ _PyPegen_get_memo_statistics(void)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
MUTEX_LOCK();
|
FT_MUTEX_LOCK(&_PyRuntime.parser.mutex);
|
||||||
for (int i = 0; i < NSTATISTICS; i++) {
|
for (int i = 0; i < NSTATISTICS; i++) {
|
||||||
PyObject *value = PyLong_FromLong(memo_statistics[i]);
|
PyObject *value = PyLong_FromLong(memo_statistics[i]);
|
||||||
if (value == NULL) {
|
if (value == NULL) {
|
||||||
MUTEX_UNLOCK();
|
FT_MUTEX_UNLOCK(&_PyRuntime.parser.mutex);
|
||||||
Py_DECREF(ret);
|
Py_DECREF(ret);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
// PyList_SetItem borrows a reference to value.
|
// PyList_SetItem borrows a reference to value.
|
||||||
if (PyList_SetItem(ret, i, value) < 0) {
|
if (PyList_SetItem(ret, i, value) < 0) {
|
||||||
MUTEX_UNLOCK();
|
FT_MUTEX_UNLOCK(&_PyRuntime.parser.mutex);
|
||||||
Py_DECREF(ret);
|
Py_DECREF(ret);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MUTEX_UNLOCK();
|
FT_MUTEX_UNLOCK(&_PyRuntime.parser.mutex);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -366,9 +359,9 @@ _PyPegen_is_memoized(Parser *p, int type, void *pres)
|
||||||
if (count <= 0) {
|
if (count <= 0) {
|
||||||
count = 1;
|
count = 1;
|
||||||
}
|
}
|
||||||
MUTEX_LOCK();
|
FT_MUTEX_LOCK(&_PyRuntime.parser.mutex);
|
||||||
memo_statistics[type] += count;
|
memo_statistics[type] += count;
|
||||||
MUTEX_UNLOCK();
|
FT_MUTEX_UNLOCK(&_PyRuntime.parser.mutex);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
p->mark = m->mark;
|
p->mark = m->mark;
|
||||||
|
|
|
||||||
|
|
@ -907,13 +907,9 @@ unsignal_pending_calls(PyThreadState *tstate, PyInterpreterState *interp)
|
||||||
static void
|
static void
|
||||||
clear_pending_handling_thread(struct _pending_calls *pending)
|
clear_pending_handling_thread(struct _pending_calls *pending)
|
||||||
{
|
{
|
||||||
#ifdef Py_GIL_DISABLED
|
FT_MUTEX_LOCK(&pending->mutex);
|
||||||
PyMutex_Lock(&pending->mutex);
|
|
||||||
pending->handling_thread = NULL;
|
pending->handling_thread = NULL;
|
||||||
PyMutex_Unlock(&pending->mutex);
|
FT_MUTEX_UNLOCK(&pending->mutex);
|
||||||
#else
|
|
||||||
pending->handling_thread = NULL;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ Copyright (c) Corporation for National Research Initiatives.
|
||||||
#include "pycore_runtime.h" // _Py_ID()
|
#include "pycore_runtime.h" // _Py_ID()
|
||||||
#include "pycore_ucnhash.h" // _PyUnicode_Name_CAPI
|
#include "pycore_ucnhash.h" // _PyUnicode_Name_CAPI
|
||||||
#include "pycore_unicodeobject.h" // _PyUnicode_InternMortal()
|
#include "pycore_unicodeobject.h" // _PyUnicode_InternMortal()
|
||||||
|
#include "pycore_pyatomic_ft_wrappers.h"
|
||||||
|
|
||||||
static const char *codecs_builtin_error_handlers[] = {
|
static const char *codecs_builtin_error_handlers[] = {
|
||||||
"strict", "ignore", "replace",
|
"strict", "ignore", "replace",
|
||||||
|
|
@ -40,13 +40,10 @@ int PyCodec_Register(PyObject *search_function)
|
||||||
PyErr_SetString(PyExc_TypeError, "argument must be callable");
|
PyErr_SetString(PyExc_TypeError, "argument must be callable");
|
||||||
goto onError;
|
goto onError;
|
||||||
}
|
}
|
||||||
#ifdef Py_GIL_DISABLED
|
FT_MUTEX_LOCK(&interp->codecs.search_path_mutex);
|
||||||
PyMutex_Lock(&interp->codecs.search_path_mutex);
|
|
||||||
#endif
|
|
||||||
int ret = PyList_Append(interp->codecs.search_path, search_function);
|
int ret = PyList_Append(interp->codecs.search_path, search_function);
|
||||||
#ifdef Py_GIL_DISABLED
|
FT_MUTEX_UNLOCK(&interp->codecs.search_path_mutex);
|
||||||
PyMutex_Unlock(&interp->codecs.search_path_mutex);
|
|
||||||
#endif
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
onError:
|
onError:
|
||||||
|
|
@ -66,9 +63,7 @@ PyCodec_Unregister(PyObject *search_function)
|
||||||
PyObject *codec_search_path = interp->codecs.search_path;
|
PyObject *codec_search_path = interp->codecs.search_path;
|
||||||
assert(PyList_CheckExact(codec_search_path));
|
assert(PyList_CheckExact(codec_search_path));
|
||||||
for (Py_ssize_t i = 0; i < PyList_GET_SIZE(codec_search_path); i++) {
|
for (Py_ssize_t i = 0; i < PyList_GET_SIZE(codec_search_path); i++) {
|
||||||
#ifdef Py_GIL_DISABLED
|
FT_MUTEX_LOCK(&interp->codecs.search_path_mutex);
|
||||||
PyMutex_Lock(&interp->codecs.search_path_mutex);
|
|
||||||
#endif
|
|
||||||
PyObject *item = PyList_GetItemRef(codec_search_path, i);
|
PyObject *item = PyList_GetItemRef(codec_search_path, i);
|
||||||
int ret = 1;
|
int ret = 1;
|
||||||
if (item == search_function) {
|
if (item == search_function) {
|
||||||
|
|
@ -76,9 +71,7 @@ PyCodec_Unregister(PyObject *search_function)
|
||||||
// while we hold search_path_mutex.
|
// while we hold search_path_mutex.
|
||||||
ret = PyList_SetSlice(codec_search_path, i, i+1, NULL);
|
ret = PyList_SetSlice(codec_search_path, i, i+1, NULL);
|
||||||
}
|
}
|
||||||
#ifdef Py_GIL_DISABLED
|
FT_MUTEX_UNLOCK(&interp->codecs.search_path_mutex);
|
||||||
PyMutex_Unlock(&interp->codecs.search_path_mutex);
|
|
||||||
#endif
|
|
||||||
Py_DECREF(item);
|
Py_DECREF(item);
|
||||||
if (ret != 1) {
|
if (ret != 1) {
|
||||||
assert(interp->codecs.search_cache != NULL);
|
assert(interp->codecs.search_cache != NULL);
|
||||||
|
|
|
||||||
|
|
@ -20,13 +20,6 @@ typedef struct _PyLegacyEventHandler {
|
||||||
|
|
||||||
#define _PyLegacyEventHandler_CAST(op) ((_PyLegacyEventHandler *)(op))
|
#define _PyLegacyEventHandler_CAST(op) ((_PyLegacyEventHandler *)(op))
|
||||||
|
|
||||||
#ifdef Py_GIL_DISABLED
|
|
||||||
#define LOCK_SETUP() PyMutex_Lock(&_PyRuntime.ceval.sys_trace_profile_mutex);
|
|
||||||
#define UNLOCK_SETUP() PyMutex_Unlock(&_PyRuntime.ceval.sys_trace_profile_mutex);
|
|
||||||
#else
|
|
||||||
#define LOCK_SETUP()
|
|
||||||
#define UNLOCK_SETUP()
|
|
||||||
#endif
|
|
||||||
/* The Py_tracefunc function expects the following arguments:
|
/* The Py_tracefunc function expects the following arguments:
|
||||||
* obj: the trace object (PyObject *)
|
* obj: the trace object (PyObject *)
|
||||||
* frame: the current frame (PyFrameObject *)
|
* frame: the current frame (PyFrameObject *)
|
||||||
|
|
@ -509,9 +502,9 @@ _PyEval_SetProfile(PyThreadState *tstate, Py_tracefunc func, PyObject *arg)
|
||||||
|
|
||||||
// needs to be decref'd outside of the lock
|
// needs to be decref'd outside of the lock
|
||||||
PyObject *old_profileobj;
|
PyObject *old_profileobj;
|
||||||
LOCK_SETUP();
|
FT_MUTEX_LOCK(&_PyRuntime.ceval.sys_trace_profile_mutex);
|
||||||
Py_ssize_t profiling_threads = setup_profile(tstate, func, arg, &old_profileobj);
|
Py_ssize_t profiling_threads = setup_profile(tstate, func, arg, &old_profileobj);
|
||||||
UNLOCK_SETUP();
|
FT_MUTEX_UNLOCK(&_PyRuntime.ceval.sys_trace_profile_mutex);
|
||||||
Py_XDECREF(old_profileobj);
|
Py_XDECREF(old_profileobj);
|
||||||
|
|
||||||
uint32_t events = 0;
|
uint32_t events = 0;
|
||||||
|
|
@ -605,10 +598,10 @@ _PyEval_SetTrace(PyThreadState *tstate, Py_tracefunc func, PyObject *arg)
|
||||||
}
|
}
|
||||||
// needs to be decref'd outside of the lock
|
// needs to be decref'd outside of the lock
|
||||||
PyObject *old_traceobj;
|
PyObject *old_traceobj;
|
||||||
LOCK_SETUP();
|
FT_MUTEX_LOCK(&_PyRuntime.ceval.sys_trace_profile_mutex);
|
||||||
assert(tstate->interp->sys_tracing_threads >= 0);
|
assert(tstate->interp->sys_tracing_threads >= 0);
|
||||||
Py_ssize_t tracing_threads = setup_tracing(tstate, func, arg, &old_traceobj);
|
Py_ssize_t tracing_threads = setup_tracing(tstate, func, arg, &old_traceobj);
|
||||||
UNLOCK_SETUP();
|
FT_MUTEX_UNLOCK(&_PyRuntime.ceval.sys_trace_profile_mutex);
|
||||||
Py_XDECREF(old_traceobj);
|
Py_XDECREF(old_traceobj);
|
||||||
if (tracing_threads < 0) {
|
if (tracing_threads < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
||||||
|
|
@ -1689,9 +1689,7 @@ PyThreadState_Clear(PyThreadState *tstate)
|
||||||
"PyThreadState_Clear: warning: thread still has a generator\n");
|
"PyThreadState_Clear: warning: thread still has a generator\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef Py_GIL_DISABLED
|
FT_MUTEX_LOCK(&_PyRuntime.ceval.sys_trace_profile_mutex);
|
||||||
PyMutex_Lock(&_PyRuntime.ceval.sys_trace_profile_mutex);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (tstate->c_profilefunc != NULL) {
|
if (tstate->c_profilefunc != NULL) {
|
||||||
tstate->interp->sys_profiling_threads--;
|
tstate->interp->sys_profiling_threads--;
|
||||||
|
|
@ -1702,9 +1700,7 @@ PyThreadState_Clear(PyThreadState *tstate)
|
||||||
tstate->c_tracefunc = NULL;
|
tstate->c_tracefunc = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef Py_GIL_DISABLED
|
FT_MUTEX_UNLOCK(&_PyRuntime.ceval.sys_trace_profile_mutex);
|
||||||
PyMutex_Unlock(&_PyRuntime.ceval.sys_trace_profile_mutex);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Py_CLEAR(tstate->c_profileobj);
|
Py_CLEAR(tstate->c_profileobj);
|
||||||
Py_CLEAR(tstate->c_traceobj);
|
Py_CLEAR(tstate->c_traceobj);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue