8000 bpo-33608: Factor out a private, per-interpreter _Py_AddPendingCall()… · stackless-dev/stackless@6a150bc · GitHub
[go: up one dir, main page]

Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
This repository was archived by the owner on Feb 13, 2025. It is now read-only.

Commit 6a150bc

Browse files
bpo-33608: Factor out a private, per-interpreter _Py_AddPendingCall(). (pythongh-13714)
1 parent 218e47b commit 6a150bc

File tree

10 files changed

+320
-186
lines changed

10 files changed

+320
-186
lines changed

Include/internal/pycore_ceval.h

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,22 @@ extern "C" {
1212
#include "pycore_pystate.h"
1313
#include "pythread.h"
1414

15-
PyAPI_FUNC(void) _Py_FinishPendingCalls(_PyRuntimeState *runtime);
1615
PyAPI_FUNC(void) _PyEval_Initialize(struct _ceval_runtime_state *);
1716
PyAPI_FUNC(void) _PyEval_FiniThreads(
18-
struct _ceval_runtime_state *ceval);
17+
struct _ceval_runtime_state *);
1918
PyAPI_FUNC(void) _PyEval_SignalReceived(
20-
struct _ceval_runtime_state *ceval);
19+
struct _ceval_runtime_state *);
2120
PyAPI_FUNC(int) _PyEval_AddPendingCall(
2221
PyThreadState *tstate,
23-
struct _ceval_runtime_state *ceval,
22+
struct _ceval_runtime_state *,
23+
struct _ceval_interpreter_state *,
24+
unsigned long thread_id,
2425
int (*func)(void *),
2526
void *arg);
27+
PyAPI_FUNC(void) _PyEval_FinishPendingCalls(PyInterpreterState *);
2628
PyAPI_FUNC(void) _PyEval_SignalAsyncExc(
27-
struct _ceval_runtime_state *ceval);
29+
struct _ceval_runtime_state *,
30+
struct _ceval_interpreter_state *);
2831
PyAPI_FUNC(void) _PyEval_ReInitThreads(
2932
_PyRuntimeState *runtime);
3033

Include/internal/pycore_pystate.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ struct pyruntimestate;
2525

2626
/* ceval state */
2727

28-
struct _pending_calls {
28+
struct _ceval_pending_calls {
2929
int finishing;
3030
PyThread_type_lock lock;
3131
/* Request for running pending calls. */
@@ -36,6 +36,7 @@ struct _pending_calls {
3636
int async_exc;
3737
#define NPENDINGCALLS 32
3838
struct {
39+
unsigned long thread_id;
3940
int (*func)(void *);
4041
void *arg;
4142
} calls[NPENDINGCALLS];
@@ -53,15 +54,21 @@ struct _ceval_runtime_state {
5354
int tracing_possible;
5455
/* This single variable consolidates all requests to break out of
5556
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.
5659
_Py_atomic_int eval_breaker;
5760
/* Request for dropping the GIL */
5861
_Py_atomic_int gil_drop_request;
59-
struct _pending_calls pending;
6062
/* Request for checking signals. */
6163
_Py_atomic_int signals_pending;
6264
struct _gil_runtime_state gil;
6365
};
6466

67+
struct _ceval_interpreter_state {
68+
struct _ceval_pending_calls pending;
69+
};
70+
71+
6572
/* interpreter state */
6673

6774
typedef PyObject* (*_PyFrameEvalFunction)(struct _frame *, int);
@@ -136,6 +143,7 @@ struct _is {
136143

137144
uint64_t tstate_next_unique_id;
138145

146+
struct _ceval_interpreter_state ceval;
139147
struct _warnings_runtime_state warnings;
140148

141149
PyObject *audit_hooks;

Lib/test/test_capi.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -431,7 +431,7 @@ def pendingcalls_wait(self, l, n, context = None):
431431
def test_pendingcalls_threaded(self):
432432

433433
#do every callback on a separate thread
434-
n = 32 #total callbacks
434+
n = 32 #total callbacks (see NPENDINGCALLS in pycore_ceval.h)
435435
threads = []
436436
class foo(object):pass
437437
context = foo()
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff 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.

Modules/_testcapimodule.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2677,6 +2677,7 @@ pending_threadfunc(PyObject *self, PyObject *arg)
26772677
Py_INCREF(callable);
26782678

26792679
Py_BEGIN_ALLOW_THREADS
2680+
/* XXX Use the internal _Py_AddPendingCall(). */
26802681
r = Py_AddPendingCall(&_pending_callback, callable);
26812682
Py_END_ALLOW_THREADS
26822683

Modules/signalmodule.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <process.h>
2222
#endif
2323
#endif
24+
#include "internal/pycore_pystate.h"
2425

2526
#ifdef HAVE_SIGNAL_H
2627
#include <signal.h>
@@ -259,6 +260,7 @@ trip_signal(int sig_num)
259260
/* Notify ceval.c */
260261
_PyRuntimeState *runtime = &_PyRuntime;
261262
PyThreadState *tstate = _PyRuntimeState_GetThreadState(runtime);
263+
PyInterpreterState *interp = runtime->interpreters.main;
262264
_PyEval_SignalReceived(&runtime->ceval);
263265

264266
/* And then write to the wakeup fd *after* setting all the globals and
@@ -299,7 +301,10 @@ trip_signal(int sig_num)
299301
{
300302
/* Py_AddPendingCall() isn't signal-safe, but we
301303
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,
303308
report_wakeup_send_error,
304309
(void *)(intptr_t) last_error);
305310
}
@@ -318,7 +323,10 @@ trip_signal(int sig_num)
318323
{
319324
/* Py_AddPendingCall() isn't signal-safe, but we
320325
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,
322330
report_wakeup_write_error,
323331
(void *)(intptr_t)errno);
324332
}

0 commit comments

Comments
 (0)
0