Skip to content

Commit 09532fe

Browse files
authored
bpo-36710: Add 'ceval' local variable to ceval.c (GH-12934)
Add "struct _ceval_runtime_state *ceval = &_PyRuntime.ceval;" local variables to function to better highlight the dependency on the global variable _PyRuntime and to point directly to _PyRuntime.ceval field rather than on the larger _PyRuntime. Changes: * Add _PyRuntimeState_GetThreadState(runtime) macro. * Add _PyEval_AddPendingCall(ceval, ...) and _PyThreadState_Swap(gilstate, ...) functions. * _PyThreadState_GET() macro now calls _PyRuntimeState_GetThreadState() using &_PyRuntime. * Add 'ceval' parameter to COMPUTE_EVAL_BREAKER(), SIGNAL_PENDING_SIGNALS(), _PyEval_SignalAsyncExc(), _PyEval_SignalReceived() and _PyEval_FiniThreads() macros and functions. * Add 'tstate' parameter to call_function(), do_call_core() and do_raise(). * Add 'runtime' parameter to _Py_CURRENTLY_FINALIZING(), _Py_FinishPendingCalls() and _PyThreadState_DeleteExcept() macros and functions. * Declare 'runtime', 'tstate', 'ceval' and 'eval_breaker' variables as constant.
1 parent f22cc69 commit 09532fe

File tree

8 files changed

+371
-321
lines changed

8 files changed

+371
-321
lines changed

Include/ceval.h

-5
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,6 @@ PyAPI_FUNC(int) PyEval_MergeCompilerFlags(PyCompilerFlags *cf);
5858
#endif
5959

6060
PyAPI_FUNC(int) Py_AddPendingCall(int (*func)(void *), void *arg);
61-
PyAPI_FUNC(void) _PyEval_SignalReceived(void);
6261
PyAPI_FUNC(int) Py_MakePendingCalls(void);
6362

6463
/* Protection against deeply nested recursive calls
@@ -192,9 +191,6 @@ PyAPI_FUNC(void) PyEval_RestoreThread(PyThreadState *);
192191

193192
PyAPI_FUNC(int) PyEval_ThreadsInitialized(void);
194193
PyAPI_FUNC(void) PyEval_InitThreads(void);
195-
#ifndef Py_LIMITED_API
196-
PyAPI_FUNC(void) _PyEval_FiniThreads(void);
197-
#endif /* !Py_LIMITED_API */
198194
PyAPI_FUNC(void) PyEval_AcquireLock(void) Py_DEPRECATED(3.2);
199195
PyAPI_FUNC(void) PyEval_ReleaseLock(void) /* Py_DEPRECATED(3.2) */;
200196
PyAPI_FUNC(void) PyEval_AcquireThread(PyThreadState *tstate);
@@ -221,7 +217,6 @@ PyAPI_FUNC(Py_ssize_t) _PyEval_RequestCodeExtraIndex(freefunc);
221217
#ifndef Py_LIMITED_API
222218
PyAPI_FUNC(int) _PyEval_SliceIndex(PyObject *, Py_ssize_t *);
223219
PyAPI_FUNC(int) _PyEval_SliceIndexNotNone(PyObject *, Py_ssize_t *);
224-
PyAPI_FUNC(void) _PyEval_SignalAsyncExc(void);
225220
#endif
226221

227222
/* Masks and values used by FORMAT_VALUE opcode. */

Include/internal/pycore_ceval.h

+12-41
Original file line numberDiff line numberDiff line change
@@ -9,50 +9,21 @@ extern "C" {
99
#endif
1010

1111
#include "pycore_atomic.h"
12+
#include "pycore_pystate.h"
1213
#include "pythread.h"
1314

14-
PyAPI_FUNC(void) _Py_FinishPendingCalls(void);
15-
16-
struct _pending_calls {
17-
int finishing;
18-
PyThread_type_lock lock;
19-
/* Request for running pending calls. */
20-
_Py_atomic_int calls_to_do;
21-
/* Request for looking at the `async_exc` field of the current
22-
thread state.
23-
Guarded by the GIL. */
24-
int async_exc;
25-
#define NPENDINGCALLS 32
26-
struct {
27-
int (*func)(void *);
28-
void *arg;
29-
} calls[NPENDINGCALLS];
30-
int first;
31-
int last;
32-
};
33-
34-
#include "pycore_gil.h"
35-
36-
struct _ceval_runtime_state {
37-
int recursion_limit;
38-
/* Records whether tracing is on for any thread. Counts the number
39-
of threads for which tstate->c_tracefunc is non-NULL, so if the
40-
value is 0, we know we don't have to check this thread's
41-
c_tracefunc. This speeds up the if statement in
42-
PyEval_EvalFrameEx() after fast_next_opcode. */
43-
int tracing_possible;
44-
/* This single variable consolidates all requests to break out of
45-
the fast path in the eval loop. */
46-
_Py_atomic_int eval_breaker;
47-
/* Request for dropping the GIL */
48-
_Py_atomic_int gil_drop_request;
49-
struct _pending_calls pending;
50-
/* Request for checking signals. */
51-
_Py_atomic_int signals_pending;
52-
struct _gil_runtime_state gil;
53-
};
54-
15+
PyAPI_FUNC(void) _Py_FinishPendingCalls(_PyRuntimeState *runtime);
5516
PyAPI_FUNC(void) _PyEval_Initialize(struct _ceval_runtime_state *);
17+
PyAPI_FUNC(void) _PyEval_FiniThreads(
18+
struct _ceval_runtime_state *ceval);
19+
PyAPI_FUNC(void) _PyEval_SignalReceived(
20+
struct _ceval_runtime_state *ceval);
21+
PyAPI_FUNC(int) _PyEval_AddPendingCall(
22+
struct _ceval_runtime_state *ceval,
23+
int (*func)(void *),
24+
void *arg);
25+
PyAPI_FUNC(void) _PyEval_SignalAsyncExc(
26+
struct _ceval_runtime_state *ceval);
5627

5728
#ifdef __cplusplus
5829
}

Include/internal/pycore_pystate.h

+53-6
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,51 @@ extern "C" {
1212
#include "pystate.h"
1313
#include "pythread.h"
1414

15-
#include "pycore_ceval.h"
15+
#include "pycore_gil.h" /* _gil_runtime_state */
1616
#include "pycore_pathconfig.h"
1717
#include "pycore_pymem.h"
1818
#include "pycore_warnings.h"
1919

2020

21+
/* ceval state */
22+
23+
struct _pending_calls {
24+
int finishing;
25+
PyThread_type_lock lock;
26+
/* Request for running pending calls. */
27+
_Py_atomic_int calls_to_do;
28+
/* Request for looking at the `async_exc` field of the current
29+
thread state.
30+
Guarded by the GIL. */
31+
int async_exc;
32+
#define NPENDINGCALLS 32
33+
struct {
34+
int (*func)(void *);
35+
void *arg;
36+
} calls[NPENDINGCALLS];
37+
int first;
38+
int last;
39+
};
40+
41+
struct _ceval_runtime_state {
42+
int recursion_limit;
43+
/* Records whether tracing is on for any thread. Counts the number
44+
of threads for which tstate->c_tracefunc is non-NULL, so if the
45+
value is 0, we know we don't have to check this thread's
46+
c_tracefunc. This speeds up the if statement in
47+
PyEval_EvalFrameEx() after fast_next_opcode. */
48+
int tracing_possible;
49+
/* This single variable consolidates all requests to break out of
50+
the fast path in the eval loop. */
51+
_Py_atomic_int eval_breaker;
52+
/* Request for dropping the GIL */
53+
_Py_atomic_int gil_drop_request;
54+
struct _pending_calls pending;
55+
/* Request for checking signals. */
56+
_Py_atomic_int signals_pending;
57+
struct _gil_runtime_state gil;
58+
};
59+
2160
/* interpreter state */
2261

2362
typedef PyObject* (*_PyFrameEvalFunction)(struct _frame *, int);
@@ -203,13 +242,16 @@ PyAPI_FUNC(_PyInitError) _PyRuntime_Initialize(void);
203242

204243
PyAPI_FUNC(void) _PyRuntime_Finalize(void);
205244

206-
#define _Py_CURRENTLY_FINALIZING(tstate) \
207-
(_PyRuntime.finalizing == tstate)
245+
#define _Py_CURRENTLY_FINALIZING(runtime, tstate) \
246+
(runtime->finalizing == tstate)
208247

209248

210249
/* Variable and macro for in-line access to current thread
211250
and interpreter state */
212251

252+
#define _PyRuntimeState_GetThreadState(runtime) \
253+
((PyThreadState*)_Py_atomic_load_relaxed(&(runtime)->gilstate.tstate_current))
254+
213255
/* Get the current Python thread state.
214256
215257
Efficient macro reading directly the 'gilstate.tstate_current' atomic
@@ -219,8 +261,7 @@ PyAPI_FUNC(void) _PyRuntime_Finalize(void);
219261
The caller must hold the GIL.
220262
221263
See also PyThreadState_Get() and PyThreadState_GET(). */
222-
#define _PyThreadState_GET() \
223-
((PyThreadState*)_Py_atomic_load_relaxed(&_PyRuntime.gilstate.tstate_current))
264+
#define _PyThreadState_GET() _PyRuntimeState_GetThreadState(&_PyRuntime)
224265

225266
/* Redefine PyThreadState_GET() as an alias to _PyThreadState_GET() */
226267
#undef PyThreadState_GET
@@ -242,7 +283,13 @@ PyAPI_FUNC(void) _PyRuntime_Finalize(void);
242283
PyAPI_FUNC(void) _PyThreadState_Init(
243284
_PyRuntimeState *runtime,
244285
PyThreadState *tstate);
245-
PyAPI_FUNC(void) _PyThreadState_DeleteExcept(PyThreadState *tstate);
286+
PyAPI_FUNC(void) _PyThreadState_DeleteExcept(
287+
_PyRuntimeState *runtime,
288+
PyThreadState *tstate);
289+
290+
PyAPI_FUNC(PyThreadState *) _PyThreadState_Swap(
291+
struct _gilstate_runtime_state *gilstate,
292+
PyThreadState *newts);
246293

247294
PyAPI_FUNC(_PyInitError) _PyInterpreterState_Enable(_PyRuntimeState *runtime);
248295
PyAPI_FUNC(void) _PyInterpreterState_DeleteExceptMain(_PyRuntimeState *runtime);

Modules/signalmodule.c

+14-9
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55

66
#include "Python.h"
77
#include "pycore_atomic.h"
8+
#include "pycore_ceval.h"
9+
#include "pycore_pystate.h"
810

911
#ifndef MS_WINDOWS
1012
#include "posixmodule.h"
@@ -256,7 +258,8 @@ trip_signal(int sig_num)
256258
_Py_atomic_store(&is_tripped, 1);
257259

258260
/* Notify ceval.c */
259-
_PyEval_SignalReceived();
261+
_PyRuntimeState *runtime = &_PyRuntime;
262+
_PyEval_SignalReceived(&runtime->ceval);
260263

261264
/* And then write to the wakeup fd *after* setting all the globals and
262265
doing the _PyEval_SignalReceived. We used to write to the wakeup fd
@@ -296,8 +299,9 @@ trip_signal(int sig_num)
296299
{
297300
/* Py_AddPendingCall() isn't signal-safe, but we
298301
still use it for this exceptional case. */
299-
Py_AddPendingCall(report_wakeup_send_error,
300-
(void *)(intptr_t) last_error);
302+
_PyEval_AddPendingCall(&runtime->ceval,
303+
report_wakeup_send_error,
304+
(void *)(intptr_t) last_error);
301305
}
302306
}
303307
}
@@ -314,8 +318,9 @@ trip_signal(int sig_num)
314318
{
315319
/* Py_AddPendingCall() isn't signal-safe, but we
316320
still use it for this exceptional case. */
317-
Py_AddPendingCall(report_wakeup_write_error,
318-
(void *)(intptr_t)errno);
321+
_PyEval_AddPendingCall(&runtime->ceval,
322+
report_wakeup_write_error,
323+
(void *)(intptr_t)errno);
319324
}
320325
}
321326
}
@@ -420,7 +425,7 @@ signal_raise_signal_impl(PyObject *module, int signalnum)
420425
err = raise(signalnum);
421426
_Py_END_SUPPRESS_IPH
422427
Py_END_ALLOW_THREADS
423-
428+
424429
if (err) {
425430
return PyErr_SetFromErrno(PyExc_OSError);
426431
}
@@ -1076,18 +1081,18 @@ fill_siginfo(siginfo_t *si)
10761081

10771082
PyStructSequence_SET_ITEM(result, 0, PyLong_FromLong((long)(si->si_signo)));
10781083
PyStructSequence_SET_ITEM(result, 1, PyLong_FromLong((long)(si->si_code)));
1079-
#ifdef __VXWORKS__
1084+
#ifdef __VXWORKS__
10801085
PyStructSequence_SET_ITEM(result, 2, PyLong_FromLong(0L));
10811086
PyStructSequence_SET_ITEM(result, 3, PyLong_FromLong(0L));
10821087
PyStructSequence_SET_ITEM(result, 4, PyLong_FromLong(0L));
10831088
PyStructSequence_SET_ITEM(result, 5, PyLong_FromLong(0L));
1084-
#else
1089+
#else
10851090
PyStructSequence_SET_ITEM(result, 2, PyLong_FromLong((long)(si->si_errno)));
10861091
PyStructSequence_SET_ITEM(result, 3, PyLong_FromPid(si->si_pid));
10871092
PyStructSequence_SET_ITEM(result, 4, _PyLong_FromUid(si->si_uid));
10881093
PyStructSequence_SET_ITEM(result, 5,
10891094
PyLong_FromLong((long)(si->si_status)));
1090-
#endif
1095+
#endif
10911096
#ifdef HAVE_SIGINFO_T_SI_BAND
10921097
PyStructSequence_SET_ITEM(result, 6, PyLong_FromLong(si->si_band));
10931098
#else

0 commit comments

Comments
 (0)