summaryrefslogtreecommitdiffstats
path: root/Python
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@python.org>2020-03-20 13:50:35 (GMT)
committerGitHub <noreply@github.com>2020-03-20 13:50:35 (GMT)
commitd83168854e19d0381fa57db25fca6c622917624f (patch)
treeb282c1b565d7ad97f789683dac78c2dfc767027f /Python
parentd2a8e5b42c5e9c4e745a0589043a8aebb49f8ca2 (diff)
downloadcpython-d83168854e19d0381fa57db25fca6c622917624f.zip
cpython-d83168854e19d0381fa57db25fca6c622917624f.tar.gz
cpython-d83168854e19d0381fa57db25fca6c622917624f.tar.bz2
bpo-40010: Optimize pending calls in multithreaded applications (GH-19091)
If a thread different than the main thread schedules a pending call (Py_AddPendingCall()), the bytecode evaluation loop is no longer interrupted at each bytecode instruction to check for pending calls which cannot be executed. Only the main thread can execute pending calls. Previously, the bytecode evaluation loop was interrupted at each instruction until the main thread executes pending calls. * Add _Py_ThreadCanHandlePendingCalls() function. * SIGNAL_PENDING_CALLS() now only sets eval_breaker to 1 if the current thread can execute pending calls. Only the main thread can execute pending calls.
Diffstat (limited to 'Python')
-rw-r--r--Python/ceval.c10
1 files changed, 6 insertions, 4 deletions
diff --git a/Python/ceval.c b/Python/ceval.c
index 86aa225..c80ee4b 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -149,7 +149,8 @@ COMPUTE_EVAL_BREAKER(PyThreadState *tstate,
_Py_atomic_load_relaxed(&ceval->gil_drop_request)
| (_Py_atomic_load_relaxed(&ceval->signals_pending)
&& _Py_ThreadCanHandleSignals(tstate))
- | _Py_atomic_load_relaxed(&ceval2->pending.calls_to_do)
+ | (_Py_atomic_load_relaxed(&ceval2->pending.calls_to_do)
+ && _Py_ThreadCanHandlePendingCalls())
| ceval2->pending.async_exc);
}
@@ -180,9 +181,10 @@ static inline void
SIGNAL_PENDING_CALLS(PyThreadState *tstate)
{
assert(is_tstate_valid(tstate));
+ struct _ceval_runtime_state *ceval = &tstate->interp->runtime->ceval;
struct _ceval_state *ceval2 = &tstate->interp->ceval;
_Py_atomic_store_relaxed(&ceval2->pending.calls_to_do, 1);
- _Py_atomic_store_relaxed(&ceval2->eval_breaker, 1);
+ COMPUTE_EVAL_BREAKER(tstate, ceval, ceval2);
}
@@ -606,8 +608,8 @@ handle_signals(PyThreadState *tstate)
static int
make_pending_calls(PyThreadState *tstate)
{
- /* only service pending calls on main thread */
- if (!_Py_IsMainThread()) {
+ /* only execute pending calls on main thread */
+ if (!_Py_ThreadCanHandlePendingCalls()) {
return 0;
}