aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Python/executor_cases.c.h
diff options
context:
space:
mode:
authorKirill Podoprigora <kirill.bast9@mail.ru>2024-11-22 19:00:35 +0200
committerGitHub <noreply@github.com>2024-11-22 19:00:35 +0200
commit27486c3365a1f628e2df9a0e88c7c51706a1282e (patch)
tree1bca57831f3a466325c48b94d1c0f52f977992f5 /Python/executor_cases.c.h
parent5ba67af006079915af0a1312735efc40fa36c4f3 (diff)
downloadcpython-27486c3365a1f628e2df9a0e88c7c51706a1282e.tar.gz
cpython-27486c3365a1f628e2df9a0e88c7c51706a1282e.zip
gh-115999: Add free-threaded specialization for `UNPACK_SEQUENCE` (#126600)
Add free-threaded specialization for `UNPACK_SEQUENCE` opcode. `UNPACK_SEQUENCE_TUPLE/UNPACK_SEQUENCE_TWO_TUPLE` are already thread safe since tuples are immutable. `UNPACK_SEQUENCE_LIST` is not thread safe because of nature of lists (there is nothing preventing another thread from adding items to or removing them the list while the instruction is executing). To achieve thread safety we add a critical section to the implementation of `UNPACK_SEQUENCE_LIST`, especially around the parts where we check the size of the list and push items onto the stack. --------- Co-authored-by: Matt Page <mpage@meta.com> Co-authored-by: mpage <mpage@cs.stanford.edu>
Diffstat (limited to 'Python/executor_cases.c.h')
-rw-r--r--Python/executor_cases.c.h22
1 files changed, 20 insertions, 2 deletions
diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h
index 5c7138a9421..22de7ca11cd 100644
--- a/Python/executor_cases.c.h
+++ b/Python/executor_cases.c.h
@@ -1711,15 +1711,33 @@
UOP_STAT_INC(uopcode, miss);
JUMP_TO_JUMP_TARGET();
}
+ #ifdef Py_GIL_DISABLED
+ PyCriticalSection cs;
+ _PyFrame_SetStackPointer(frame, stack_pointer);
+ PyCriticalSection_Begin(&cs, seq_o);
+ stack_pointer = _PyFrame_GetStackPointer(frame);
+ #endif
if (PyList_GET_SIZE(seq_o) != oparg) {
- UOP_STAT_INC(uopcode, miss);
- JUMP_TO_JUMP_TARGET();
+ #ifdef Py_GIL_DISABLED
+ _PyFrame_SetStackPointer(frame, stack_pointer);
+ PyCriticalSection_End(&cs);
+ stack_pointer = _PyFrame_GetStackPointer(frame);
+ #endif
+ if (true) {
+ UOP_STAT_INC(uopcode, miss);
+ JUMP_TO_JUMP_TARGET();
+ }
}
STAT_INC(UNPACK_SEQUENCE, hit);
PyObject **items = _PyList_ITEMS(seq_o);
for (int i = oparg; --i >= 0; ) {
*values++ = PyStackRef_FromPyObjectNew(items[i]);
}
+ #ifdef Py_GIL_DISABLED
+ _PyFrame_SetStackPointer(frame, stack_pointer);
+ PyCriticalSection_End(&cs);
+ stack_pointer = _PyFrame_GetStackPointer(frame);
+ #endif
PyStackRef_CLOSE(seq);
stack_pointer += -1 + oparg;
assert(WITHIN_STACK_BOUNDS());