10000 gh-112087: Make PyList_{Append,GetItem,Size,GetSlice} to be thread-safe · python/cpython@393cbef · GitHub
[go: up one dir, main page]

Skip to content

Commit 393cbef

Browse files
committed
gh-112087: Make PyList_{Append,GetItem,Size,GetSlice} to be thread-safe
1 parent b6623d6 commit 393cbef

File tree

2 files changed

+33
-8
lines changed

2 files changed

+33
-8
lines changed

Include/object.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -428,7 +428,11 @@ static inline void Py_SET_TYPE(PyObject *ob, PyTypeObject *type) {
428428
static inline void Py_SET_SIZE(PyVarObject *ob, Py_ssize_t size) {
429429
assert(ob->ob_base.ob_type != &PyLong_Type);
430430
assert(ob->ob_base.ob_type != &PyBool_Type);
431+
#ifdef Py_GIL_DISABLED
432+
_Py_atomic_store_ssize_relaxed(&(_PyVarObject_CAST(ob)->ob_size), size);
433+
#else
431434
ob->ob_size = size;
435+
#endif
432436
}
433437
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000
434438
# define Py_SET_SIZE(ob, size) Py_SET_SIZE(_PyVarObject_CAST(ob), (size))

Objects/listobject.c

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,14 @@ get_list_state(void)
3030
}
3131
#endif
3232

33+
#ifdef Py_GIL_DISABLED
34+
#define _Py_SET_ITEMREF(op, i, v) \
35+
_Py_atomic_store_ptr_relaxed(&((PyListObject *)(op))->ob_item[i], Py_NewRef(v))
36+
#else
37+
#define _Py_SET_ITEMREF(op, i, v) \
38+
((PyListObject *)(op))->ob_item[i] = Py_NewRef(v)
39+
#endif
40+
3341

3442
/* Ensure ob_item has room for at least newsize elements, and set
3543
* ob_size to newsize. If newsize > ob_size on entry, the content
@@ -221,8 +229,9 @@ PyList_Size(PyObject *op)
221229
PyErr_BadInternalCall();
222230
return -1;
223231
}
224-
else
225-
return Py_SIZE(op);
232+
else {
233+
return PyList_GET_SIZE(op);
234+
}
226235
}
227236

228237
static inline int
@@ -245,12 +254,16 @@ PyList_GetItem(PyObject *op, Py_ssize_t i)
245254
PyErr_BadInternalCall();
246255
return NULL;
247256
}
248-
if (!valid_index(i, Py_SIZE(op))) {
257+
PyObject *ret = NULL;
258+
if (!valid_index(i, PyList_GET_SIZE(op))) {
249259
_Py_DECLARE_STR(list_err, "list index out of range");
250260
PyErr_SetObject(PyExc_IndexError, &_Py_STR(list_err));
251261
return NULL;
252262
}
253-
return ((PyListObject *)op) -> ob_item[i];
263+
Py_BEGIN_CRITICAL_SECTION(op);
264+
ret = ((PyListObject *)op) -> ob_item[i];
265+
Py_END_CRITICAL_SECTION();
266+
return ret;
254267
}
255268

256269
int
@@ -341,11 +354,15 @@ _PyList_AppendTakeRefListResize(PyListObject *self, PyObject *newitem)
341354
int
342355
PyList_Append(PyObject *op, PyObject *newitem)
343356
{
357+
int ret = -1;
344358
if (PyList_Check(op) && (newitem != NULL)) {
345-
return _PyList_AppendTakeRef((PyListObject *)op, Py_NewRef(newitem));
359+
Py_BEGIN_CRITICAL_SECTION(op);
360+
ret = _PyList_AppendTakeRef((PyListObject *)op, Py_NewRef(newitem));
361+
Py_END_CRITICAL_SECTION();
362+
return ret;
346363
}
347364
PyErr_BadInternalCall();
348-
return -1;
365+
return ret;
349366
}
350367

351368
/* Methods */
@@ -498,7 +515,7 @@ list_slice(PyListObject *a, Py_ssize_t ilow, Py_ssize_t ihigh)
498515
dest = np->ob_item;
499516
for (i = 0; i < len; i++) {
500517
PyObject *v = src[i];
501-
dest[i] = Py_NewRef(v);
518+
_Py_SET_ITEMREF(np, i, v);
502519
}
503520
Py_SET_SIZE(np, len);
504521
return (PyObject *)np;
@@ -511,6 +528,8 @@ PyList_GetSlice(PyObject *a, Py_ssize_t ilow, Py_ssize_t ihigh)
511528
PyErr_BadInternalCall();
512529
return NULL;
513530
}
531+
PyObject *ret;
532+
Py_BEGIN_CRITICAL_SECTION(a);
514533
if (ilow < 0) {
515534
ilow = 0;
516535
}
@@ -523,7 +542,9 @@ PyList_GetSlice(PyObject *a, Py_ssize_t ilow, Py_ssize_t ihigh)
523542
else if (ihigh > Py_SIZE(a)) {
524543
ihigh = Py_SIZE(a);
525544
}
526-
return list_slice((PyListObject *)a, ilow, ihigh);
545+
ret = list_slice((PyListObject *)a, ilow, ihigh);
546+
Py_END_CRITICAL_SECTION();
547+
return ret;
527548
}
528549

529550
static PyObject *

0 commit comments

Comments
 (0)
0