Skip to content

Commit 9ac11f1

Browse files
Run per-interpreter pending calls in any thread.
1 parent 3611c58 commit 9ac11f1

File tree

1 file changed

+32
-15
lines changed

1 file changed

+32
-15
lines changed

Python/ceval_gil.c

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,9 @@ COMPUTE_EVAL_BREAKER(PyInterpreterState *interp,
6868
_Py_atomic_load_relaxed_int32(&ceval2->gil_drop_request)
6969
| (_Py_atomic_load_relaxed_int32(&ceval->signals_pending)
7070
&& _Py_ThreadCanHandleSignals(interp))
71-
| (_Py_atomic_load_relaxed_int32(&ceval2->pending.calls_to_do)
72-
&& _Py_ThreadCanHandlePendingCalls())
71+
| (_Py_atomic_load_relaxed_int32(&ceval2->pending.calls_to_do))
72+
| (_Py_IsMainThread()
73+
&&_Py_atomic_load_relaxed_int32(&ceval->pending_mainthread.calls_to_do))
7374
| ceval2->pending.async_exc
7475
| _Py_atomic_load_relaxed_int32(&ceval2->gc_scheduled));
7576
}
@@ -95,11 +96,11 @@ RESET_GIL_DROP_REQUEST(PyInterpreterState *interp)
9596

9697

9798
static inline void
98-
SIGNAL_PENDING_CALLS(PyInterpreterState *interp)
99+
SIGNAL_PENDING_CALLS(struct _pending_calls *pending, PyInterpreterState *interp)
99100
{
100101
struct _ceval_runtime_state *ceval = &interp->runtime->ceval;
101102
struct _ceval_state *ceval2 = &interp->ceval;
102-
_Py_atomic_store_relaxed(&ceval2->pending.calls_to_do, 1);
103+
_Py_atomic_store_relaxed(&pending->calls_to_do, 1);
103104
COMPUTE_EVAL_BREAKER(interp, ceval, ceval2);
104105
}
105106

@@ -109,6 +110,9 @@ UNSIGNAL_PENDING_CALLS(PyInterpreterState *interp)
109110
{
110111
struct _ceval_runtime_state *ceval = &interp->runtime->ceval;
111112
struct _ceval_state *ceval2 = &interp->ceval;
113+
if (_Py_IsMainInterpreter(interp)) {
114+
_Py_atomic_store_relaxed(&ceval->pending_mainthread.calls_to_do, 0);
115+
}
112116
_Py_atomic_store_relaxed(&ceval2->pending.calls_to_do, 0);
113117
COMPUTE_EVAL_BREAKER(interp, ceval, ceval2);
114118
}
@@ -804,6 +808,11 @@ _PyEval_AddPendingCall(PyInterpreterState *interp,
804808
{
805809
assert(!mainthreadonly || _Py_IsMainInterpreter(interp));
806810
struct _pending_calls *pending = &interp->ceval.pending;
811+
if (mainthreadonly) {
812+
/* The main thread only exists in the main interpreter. */
813+
assert(_Py_IsMainInterpreter(interp));
814+
pending = &_PyRuntime.ceval.pending_mainthread;
815+
}
807816
/* Ensure that _PyEval_InitState() was called
808817
and that _PyEval_FiniState() is not called yet. */
809818
assert(pending->lock != NULL);
@@ -813,7 +822,7 @@ _PyEval_AddPendingCall(PyInterpreterState *interp,
813822
PyThread_release_lock(pending->lock);
814823

815824
/* signal main loop */
816-
SIGNAL_PENDING_CALLS(interp);
825+
SIGNAL_PENDING_CALLS(pending, interp);
817826
return result;
818827
}
819828

@@ -845,10 +854,15 @@ handle_signals(PyThreadState *tstate)
845854
static inline int
846855
has_pending_calls(PyInterpreterState *interp)
847856
{
848-
if (_Py_atomic_load_relaxed_int32(&interp->ceval.pending.calls_to_do)) {
857+
struct _pending_calls *pending = &interp->ceval.pending;
858+
if (_Py_atomic_load_relaxed_int32(&pending->calls_to_do)) {
849859
return 1;
850860
}
851-
return 0;
861+
if (!_Py_IsMainThread()) {
862+
return 0;
863+
}
864+
pending = &_PyRuntime.ceval.pending_mainthread;
865+
return _Py_atomic_load_relaxed_int32(&pending->calls_to_do);
852866
}
853867

854868
static int
@@ -879,11 +893,7 @@ static int
879893
make_pending_calls(PyInterpreterState *interp)
880894
{
881895
struct _pending_calls *pending = &interp->ceval.pending;
882-
883-
/* only execute pending calls on main thread */
884-
if (!_Py_ThreadCanHandlePendingCalls()) {
885-
return 0;
886-
}
896+
struct _pending_calls *pending_main = &_PyRuntime.ceval.pending_mainthread;
887897

888898
/* don't perform recursive pending calls */
889899
if (pending->busy) {
@@ -895,13 +905,20 @@ make_pending_calls(PyInterpreterState *interp)
895905
added in-between re-signals */
896906
UNSIGNAL_PENDING_CALLS(interp);
897907

898-
int res = _make_pending_calls(pending);
899-
if (res < 0) {
908+
if (_make_pending_calls(pending) != 0) {
900909
pending->busy = 0;
901-
SIGNAL_PENDING_CALLS(interp);
910+
SIGNAL_PENDING_CALLS(pending, interp);
902911
return -1;
903912
}
904913

914+
if (_Py_IsMainThread()) {
915+
if (_make_pending_calls(pending_main) != 0) {
916+
pending->busy = 0;
917+
SIGNAL_PENDING_CALLS(pending_main, interp);
918+
return -1;
919+
}
920+
}
921+
905922
pending->busy = 0;
906923
return 0;
907924
}

0 commit comments

Comments
 (0)