bpo-33608: Factor out a private, per-interpreter _Py_AddPendingCall()… · python/cpython@6a150bc (original) (raw)
10 files changed
lines changed
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -12,19 +12,22 @@ extern "C" { | ||
12 | 12 | #include "pycore_pystate.h" |
13 | 13 | #include "pythread.h" |
14 | 14 | |
15 | -PyAPI_FUNC(void) _Py_FinishPendingCalls(_PyRuntimeState *runtime); | |
16 | 15 | PyAPI_FUNC(void) _PyEval_Initialize(struct _ceval_runtime_state *); |
17 | 16 | PyAPI_FUNC(void) _PyEval_FiniThreads( |
18 | -struct _ceval_runtime_state *ceval); | |
17 | +struct _ceval_runtime_state *); | |
19 | 18 | PyAPI_FUNC(void) _PyEval_SignalReceived( |
20 | -struct _ceval_runtime_state *ceval); | |
19 | +struct _ceval_runtime_state *); | |
21 | 20 | PyAPI_FUNC(int) _PyEval_AddPendingCall( |
22 | 21 | PyThreadState *tstate, |
23 | -struct _ceval_runtime_state *ceval, | |
22 | +struct _ceval_runtime_state *, | |
23 | +struct _ceval_interpreter_state *, | |
24 | +unsigned long thread_id, | |
24 | 25 | int (*func)(void *), |
25 | 26 | void *arg); |
27 | +PyAPI_FUNC(void) _PyEval_FinishPendingCalls(PyInterpreterState *); | |
26 | 28 | PyAPI_FUNC(void) _PyEval_SignalAsyncExc( |
27 | -struct _ceval_runtime_state *ceval); | |
29 | +struct _ceval_runtime_state *, | |
30 | +struct _ceval_interpreter_state *); | |
28 | 31 | PyAPI_FUNC(void) _PyEval_ReInitThreads( |
29 | 32 | _PyRuntimeState *runtime); |
30 | 33 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -25,7 +25,7 @@ struct pyruntimestate; | ||
25 | 25 | |
26 | 26 | /* ceval state */ |
27 | 27 | |
28 | -struct _pending_calls { | |
28 | +struct _ceval_pending_calls { | |
29 | 29 | int finishing; |
30 | 30 | PyThread_type_lock lock; |
31 | 31 | /* Request for running pending calls. */ |
@@ -36,6 +36,7 @@ struct _pending_calls { | ||
36 | 36 | int async_exc; |
37 | 37 | #define NPENDINGCALLS 32 |
38 | 38 | struct { |
39 | +unsigned long thread_id; | |
39 | 40 | int (*func)(void *); |
40 | 41 | void *arg; |
41 | 42 | } calls[NPENDINGCALLS]; |
@@ -53,15 +54,21 @@ struct _ceval_runtime_state { | ||
53 | 54 | int tracing_possible; |
54 | 55 | /* This single variable consolidates all requests to break out of |
55 | 56 | the fast path in the eval loop. */ |
57 | +// XXX This can move to _ceval_interpreter_state once all parts | |
58 | +// from COMPUTE_EVAL_BREAKER have moved under PyInterpreterState. | |
56 | 59 | _Py_atomic_int eval_breaker; |
57 | 60 | /* Request for dropping the GIL */ |
58 | 61 | _Py_atomic_int gil_drop_request; |
59 | -struct _pending_calls pending; | |
60 | 62 | /* Request for checking signals. */ |
61 | 63 | _Py_atomic_int signals_pending; |
62 | 64 | struct _gil_runtime_state gil; |
63 | 65 | }; |
64 | 66 | |
67 | +struct _ceval_interpreter_state { | |
68 | +struct _ceval_pending_calls pending; | |
69 | +}; | |
70 | + | |
71 | + | |
65 | 72 | /* interpreter state */ |
66 | 73 | |
67 | 74 | typedef PyObject* (*_PyFrameEvalFunction)(struct _frame *, int); |
@@ -136,6 +143,7 @@ struct _is { | ||
136 | 143 | |
137 | 144 | uint64_t tstate_next_unique_id; |
138 | 145 | |
146 | +struct _ceval_interpreter_state ceval; | |
139 | 147 | struct _warnings_runtime_state warnings; |
140 | 148 | |
141 | 149 | PyObject *audit_hooks; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -431,7 +431,7 @@ def pendingcalls_wait(self, l, n, context = None): | ||
431 | 431 | def test_pendingcalls_threaded(self): |
432 | 432 | |
433 | 433 | #do every callback on a separate thread |
434 | -n = 32 #total callbacks | |
434 | +n = 32 #total callbacks (see NPENDINGCALLS in pycore_ceval.h) | |
435 | 435 | threads = [] |
436 | 436 | class foo(object):pass |
437 | 437 | context = foo() |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
1 | +We added a new internal _Py_AddPendingCall() that operates relative to the | |
2 | +provided interpreter. This allows us to use the existing implementation to | |
3 | +ask another interpreter to do work that cannot be done in the current | |
4 | +interpreter, like decref an object the other interpreter owns. The existing | |
5 | +Py_AddPendingCall() only operates relative to the main interpreter. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -2677,6 +2677,7 @@ pending_threadfunc(PyObject *self, PyObject *arg) | ||
2677 | 2677 | Py_INCREF(callable); |
2678 | 2678 | |
2679 | 2679 | Py_BEGIN_ALLOW_THREADS |
2680 | +/* XXX Use the internal _Py_AddPendingCall(). */ | |
2680 | 2681 | r = Py_AddPendingCall(&_pending_callback, callable); |
2681 | 2682 | Py_END_ALLOW_THREADS |
2682 | 2683 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -21,6 +21,7 @@ | ||
21 | 21 | #include <process.h> |
22 | 22 | #endif |
23 | 23 | #endif |
24 | +#include "internal/pycore_pystate.h" | |
24 | 25 | |
25 | 26 | #ifdef HAVE_SIGNAL_H |
26 | 27 | #include <signal.h> |
@@ -259,6 +260,7 @@ trip_signal(int sig_num) | ||
259 | 260 | /* Notify ceval.c */ |
260 | 261 | _PyRuntimeState *runtime = &_PyRuntime; |
261 | 262 | PyThreadState *tstate = _PyRuntimeState_GetThreadState(runtime); |
263 | +PyInterpreterState *interp = runtime->interpreters.main; | |
262 | 264 | _PyEval_SignalReceived(&runtime->ceval); |
263 | 265 | |
264 | 266 | /* And then write to the wakeup fd *after* setting all the globals and |
@@ -299,7 +301,10 @@ trip_signal(int sig_num) | ||
299 | 301 | { |
300 | 302 | /* Py_AddPendingCall() isn't signal-safe, but we |
301 | 303 | still use it for this exceptional case. */ |
302 | -_PyEval_AddPendingCall(tstate, &runtime->ceval, | |
304 | +_PyEval_AddPendingCall(tstate, | |
305 | +&runtime->ceval, | |
306 | +&interp->ceval, | |
307 | +runtime->main_thread, | |
303 | 308 | report_wakeup_send_error, |
304 | 309 | (void *)(intptr_t) last_error); |
305 | 310 | } |
@@ -318,7 +323,10 @@ trip_signal(int sig_num) | ||
318 | 323 | { |
319 | 324 | /* Py_AddPendingCall() isn't signal-safe, but we |
320 | 325 | still use it for this exceptional case. */ |
321 | -_PyEval_AddPendingCall(tstate, &runtime->ceval, | |
326 | +_PyEval_AddPendingCall(tstate, | |
327 | +&runtime->ceval, | |
328 | +&interp->ceval, | |
329 | +runtime->main_thread, | |
322 | 330 | report_wakeup_write_error, |
323 | 331 | (void *)(intptr_t)errno); |
324 | 332 | } |