mirror of
https://github.com/python/cpython.git
synced 2025-11-02 11:08:57 +00:00
gh-117323: Make cell thread-safe in free-threaded builds (#117330)
Use critical sections to lock around accesses to cell contents. The critical sections are no-ops in the default (with GIL) build.
This commit is contained in:
parent
397d88db5e
commit
19c1dd60c5
11 changed files with 83 additions and 43 deletions
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include "Python.h"
|
||||
#include "pycore_abstract.h" // _PyIndex_Check()
|
||||
#include "pycore_cell.h" // PyCell_GetRef()
|
||||
#include "pycore_code.h"
|
||||
#include "pycore_emscripten_signal.h" // _Py_CHECK_EMSCRIPTEN_SIGNALS
|
||||
#include "pycore_function.h"
|
||||
|
|
@ -1523,14 +1524,13 @@ dummy_func(
|
|||
|
||||
inst(DELETE_DEREF, (--)) {
|
||||
PyObject *cell = GETLOCAL(oparg);
|
||||
PyObject *oldobj = PyCell_GET(cell);
|
||||
// Can't use ERROR_IF here.
|
||||
// Fortunately we don't need its superpower.
|
||||
PyObject *oldobj = PyCell_SwapTakeRef((PyCellObject *)cell, NULL);
|
||||
if (oldobj == NULL) {
|
||||
_PyEval_FormatExcUnbound(tstate, _PyFrame_GetCode(frame), oparg);
|
||||
ERROR_NO_POP();
|
||||
}
|
||||
PyCell_SET(cell, NULL);
|
||||
Py_DECREF(oldobj);
|
||||
}
|
||||
|
||||
|
|
@ -1543,32 +1543,28 @@ dummy_func(
|
|||
ERROR_NO_POP();
|
||||
}
|
||||
if (!value) {
|
||||
PyObject *cell = GETLOCAL(oparg);
|
||||
value = PyCell_GET(cell);
|
||||
PyCellObject *cell = (PyCellObject *)GETLOCAL(oparg);
|
||||
value = PyCell_GetRef(cell);
|
||||
if (value == NULL) {
|
||||
_PyEval_FormatExcUnbound(tstate, _PyFrame_GetCode(frame), oparg);
|
||||
ERROR_NO_POP();
|
||||
}
|
||||
Py_INCREF(value);
|
||||
}
|
||||
Py_DECREF(class_dict);
|
||||
}
|
||||
|
||||
inst(LOAD_DEREF, ( -- value)) {
|
||||
PyObject *cell = GETLOCAL(oparg);
|
||||
value = PyCell_GET(cell);
|
||||
PyCellObject *cell = (PyCellObject *)GETLOCAL(oparg);
|
||||
value = PyCell_GetRef(cell);
|
||||
if (value == NULL) {
|
||||
_PyEval_FormatExcUnbound(tstate, _PyFrame_GetCode(frame), oparg);
|
||||
ERROR_IF(true, error);
|
||||
}
|
||||
Py_INCREF(value);
|
||||
}
|
||||
|
||||
inst(STORE_DEREF, (v --)) {
|
||||
PyObject *cell = GETLOCAL(oparg);
|
||||
PyObject *oldobj = PyCell_GET(cell);
|
||||
PyCell_SET(cell, v);
|
||||
Py_XDECREF(oldobj);
|
||||
PyCellObject *cell = (PyCellObject *)GETLOCAL(oparg);
|
||||
PyCell_SetTakeRef(cell, v);
|
||||
}
|
||||
|
||||
inst(COPY_FREE_VARS, (--)) {
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
#include "Python.h"
|
||||
#include "pycore_abstract.h" // _PyIndex_Check()
|
||||
#include "pycore_call.h" // _PyObject_CallNoArgs()
|
||||
#include "pycore_cell.h" // PyCell_GetRef()
|
||||
#include "pycore_ceval.h"
|
||||
#include "pycore_code.h"
|
||||
#include "pycore_emscripten_signal.h" // _Py_CHECK_EMSCRIPTEN_SIGNALS
|
||||
|
|
|
|||
19
Python/executor_cases.c.h
generated
19
Python/executor_cases.c.h
generated
|
|
@ -1362,14 +1362,13 @@
|
|||
case _DELETE_DEREF: {
|
||||
oparg = CURRENT_OPARG();
|
||||
PyObject *cell = GETLOCAL(oparg);
|
||||
PyObject *oldobj = PyCell_GET(cell);
|
||||
// Can't use ERROR_IF here.
|
||||
// Fortunately we don't need its superpower.
|
||||
PyObject *oldobj = PyCell_SwapTakeRef((PyCellObject *)cell, NULL);
|
||||
if (oldobj == NULL) {
|
||||
_PyEval_FormatExcUnbound(tstate, _PyFrame_GetCode(frame), oparg);
|
||||
JUMP_TO_ERROR();
|
||||
}
|
||||
PyCell_SET(cell, NULL);
|
||||
Py_DECREF(oldobj);
|
||||
break;
|
||||
}
|
||||
|
|
@ -1387,13 +1386,12 @@
|
|||
JUMP_TO_ERROR();
|
||||
}
|
||||
if (!value) {
|
||||
PyObject *cell = GETLOCAL(oparg);
|
||||
value = PyCell_GET(cell);
|
||||
PyCellObject *cell = (PyCellObject *)GETLOCAL(oparg);
|
||||
value = PyCell_GetRef(cell);
|
||||
if (value == NULL) {
|
||||
_PyEval_FormatExcUnbound(tstate, _PyFrame_GetCode(frame), oparg);
|
||||
JUMP_TO_ERROR();
|
||||
}
|
||||
Py_INCREF(value);
|
||||
}
|
||||
Py_DECREF(class_dict);
|
||||
stack_pointer[-1] = value;
|
||||
|
|
@ -1403,13 +1401,12 @@
|
|||
case _LOAD_DEREF: {
|
||||
PyObject *value;
|
||||
oparg = CURRENT_OPARG();
|
||||
PyObject *cell = GETLOCAL(oparg);
|
||||
value = PyCell_GET(cell);
|
||||
PyCellObject *cell = (PyCellObject *)GETLOCAL(oparg);
|
||||
value = PyCell_GetRef(cell);
|
||||
if (value == NULL) {
|
||||
_PyEval_FormatExcUnbound(tstate, _PyFrame_GetCode(frame), oparg);
|
||||
if (true) JUMP_TO_ERROR();
|
||||
}
|
||||
Py_INCREF(value);
|
||||
stack_pointer[0] = value;
|
||||
stack_pointer += 1;
|
||||
break;
|
||||
|
|
@ -1419,10 +1416,8 @@
|
|||
PyObject *v;
|
||||
oparg = CURRENT_OPARG();
|
||||
v = stack_pointer[-1];
|
||||
PyObject *cell = GETLOCAL(oparg);
|
||||
PyObject *oldobj = PyCell_GET(cell);
|
||||
PyCell_SET(cell, v);
|
||||
Py_XDECREF(oldobj);
|
||||
PyCellObject *cell = (PyCellObject *)GETLOCAL(oparg);
|
||||
PyCell_SetTakeRef(cell, v);
|
||||
stack_pointer += -1;
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
19
Python/generated_cases.c.h
generated
19
Python/generated_cases.c.h
generated
|
|
@ -2320,14 +2320,13 @@
|
|||
next_instr += 1;
|
||||
INSTRUCTION_STATS(DELETE_DEREF);
|
||||
PyObject *cell = GETLOCAL(oparg);
|
||||
PyObject *oldobj = PyCell_GET(cell);
|
||||
// Can't use ERROR_IF here.
|
||||
// Fortunately we don't need its superpower.
|
||||
PyObject *oldobj = PyCell_SwapTakeRef((PyCellObject *)cell, NULL);
|
||||
if (oldobj == NULL) {
|
||||
_PyEval_FormatExcUnbound(tstate, _PyFrame_GetCode(frame), oparg);
|
||||
goto error;
|
||||
}
|
||||
PyCell_SET(cell, NULL);
|
||||
Py_DECREF(oldobj);
|
||||
DISPATCH();
|
||||
}
|
||||
|
|
@ -4096,13 +4095,12 @@
|
|||
next_instr += 1;
|
||||
INSTRUCTION_STATS(LOAD_DEREF);
|
||||
PyObject *value;
|
||||
PyObject *cell = GETLOCAL(oparg);
|
||||
value = PyCell_GET(cell);
|
||||
PyCellObject *cell = (PyCellObject *)GETLOCAL(oparg);
|
||||
value = PyCell_GetRef(cell);
|
||||
if (value == NULL) {
|
||||
_PyEval_FormatExcUnbound(tstate, _PyFrame_GetCode(frame), oparg);
|
||||
if (true) goto error;
|
||||
}
|
||||
Py_INCREF(value);
|
||||
stack_pointer[0] = value;
|
||||
stack_pointer += 1;
|
||||
DISPATCH();
|
||||
|
|
@ -4186,13 +4184,12 @@
|
|||
goto error;
|
||||
}
|
||||
if (!value) {
|
||||
PyObject *cell = GETLOCAL(oparg);
|
||||
value = PyCell_GET(cell);
|
||||
PyCellObject *cell = (PyCellObject *)GETLOCAL(oparg);
|
||||
value = PyCell_GetRef(cell);
|
||||
if (value == NULL) {
|
||||
_PyEval_FormatExcUnbound(tstate, _PyFrame_GetCode(frame), oparg);
|
||||
goto error;
|
||||
}
|
||||
Py_INCREF(value);
|
||||
}
|
||||
Py_DECREF(class_dict);
|
||||
stack_pointer[-1] = value;
|
||||
|
|
@ -5436,10 +5433,8 @@
|
|||
INSTRUCTION_STATS(STORE_DEREF);
|
||||
PyObject *v;
|
||||
v = stack_pointer[-1];
|
||||
PyObject *cell = GETLOCAL(oparg);
|
||||
PyObject *oldobj = PyCell_GET(cell);
|
||||
PyCell_SET(cell, v);
|
||||
Py_XDECREF(oldobj);
|
||||
PyCellObject *cell = (PyCellObject *)GETLOCAL(oparg);
|
||||
PyCell_SetTakeRef(cell, v);
|
||||
stack_pointer += -1;
|
||||
DISPATCH();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue