Skip to content

Commit 0b1e330

Browse files
authored
bpo-40513: Per-interpreter gil_drop_request (GH-19927)
Move gil_drop_request member from _PyRuntimeState.ceval to PyInterpreterState.ceval.
1 parent 4e01946 commit 0b1e330

File tree

4 files changed

+45
-47
lines changed

4 files changed

+45
-47
lines changed

Include/internal/pycore_interp.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ struct _ceval_state {
4242
/* This single variable consolidates all requests to break out of
4343
the fast path in the eval loop. */
4444
_Py_atomic_int eval_breaker;
45+
/* Request for dropping the GIL */
46+
_Py_atomic_int gil_drop_request;
4547
struct _pending_calls pending;
4648
/* Request for checking signals. */
4749
_Py_atomic_int signals_pending;

Include/internal/pycore_runtime.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@ extern "C" {
1515

1616
struct _ceval_runtime_state {
1717
int recursion_limit;
18-
/* Request for dropping the GIL */
19-
_Py_atomic_int gil_drop_request;
2018
struct _gil_runtime_state gil;
2119
};
2220

Python/ceval.c

Lines changed: 36 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -143,77 +143,70 @@ is_tstate_valid(PyThreadState *tstate)
143143
the GIL eventually anyway. */
144144
static inline void
145145
COMPUTE_EVAL_BREAKER(PyInterpreterState *interp,
146-
struct _ceval_runtime_state *ceval,
147-
struct _ceval_state *ceval2)
146+
struct _ceval_state *ceval)
148147
{
149-
_Py_atomic_store_relaxed(&ceval2->eval_breaker,
148+
_Py_atomic_store_relaxed(&ceval->eval_breaker,
150149
_Py_atomic_load_relaxed(&ceval->gil_drop_request)
151-
| (_Py_atomic_load_relaxed(&ceval2->signals_pending)
150+
| (_Py_atomic_load_relaxed(&ceval->signals_pending)
152151
&& _Py_ThreadCanHandleSignals(interp))
153-
| (_Py_atomic_load_relaxed(&ceval2->pending.calls_to_do)
152+
| (_Py_atomic_load_relaxed(&ceval->pending.calls_to_do)
154153
&& _Py_ThreadCanHandlePendingCalls())
155-
| ceval2->pending.async_exc);
154+
| ceval->pending.async_exc);
156155
}
157156

158157

159158
static inline void
160159
SET_GIL_DROP_REQUEST(PyInterpreterState *interp)
161160
{
162-
struct _ceval_runtime_state *ceval = &interp->runtime->ceval;
163-
struct _ceval_state *ceval2 = &interp->ceval;
161+
struct _ceval_state *ceval = &interp->ceval;
164162
_Py_atomic_store_relaxed(&ceval->gil_drop_request, 1);
165-
_Py_atomic_store_relaxed(&ceval2->eval_breaker, 1);
163+
_Py_atomic_store_relaxed(&ceval->eval_breaker, 1);
166164
}
167165

168166

169167
static inline void
170168
RESET_GIL_DROP_REQUEST(PyInterpreterState *interp)
171169
{
172-
struct _ceval_runtime_state *ceval = &interp->runtime->ceval;
173-
struct _ceval_state *ceval2 = &interp->ceval;
170+
struct _ceval_state *ceval = &interp->ceval;
174171
_Py_atomic_store_relaxed(&ceval->gil_drop_request, 0);
175-
COMPUTE_EVAL_BREAKER(interp, ceval, ceval2);
172+
COMPUTE_EVAL_BREAKER(interp, ceval);
176173
}
177174

178175

179176
static inline void
180177
SIGNAL_PENDING_CALLS(PyInterpreterState *interp)
181178
{
182-
struct _ceval_runtime_state *ceval = &interp->runtime->ceval;
183-
struct _ceval_state *ceval2 = &interp->ceval;
184-
_Py_atomic_store_relaxed(&ceval2->pending.calls_to_do, 1);
185-
COMPUTE_EVAL_BREAKER(interp, ceval, ceval2);
179+
struct _ceval_state *ceval = &interp->ceval;
180+
_Py_atomic_store_relaxed(&ceval->pending.calls_to_do, 1);
181+
COMPUTE_EVAL_BREAKER(interp, ceval);
186182
}
187183

188184

189185
static inline void
190186
UNSIGNAL_PENDING_CALLS(PyInterpreterState *interp)
191187
{
192-
struct _ceval_runtime_state *ceval = &interp->runtime->ceval;
193-
struct _ceval_state *ceval2 = &interp->ceval;
194-
_Py_atomic_store_relaxed(&ceval2->pending.calls_to_do, 0);
195-
COMPUTE_EVAL_BREAKER(interp, ceval, ceval2);
188+
struct _ceval_state *ceval = &interp->ceval;
189+
_Py_atomic_store_relaxed(&ceval->pending.calls_to_do, 0);
190+
COMPUTE_EVAL_BREAKER(interp, ceval);
196191
}
197192

198193

199194
static inline void
200195
SIGNAL_PENDING_SIGNALS(PyInterpreterState *interp)
201196
{
202-
struct _ceval_runtime_state *ceval = &interp->runtime->ceval;
203-
struct _ceval_state *ceval2 = &interp->ceval;
204-
_Py_atomic_store_relaxed(&ceval2->signals_pending, 1);
197+
struct _ceval_state *ceval = &interp->ceval;
198+
_Py_atomic_store_relaxed(&ceval->signals_pending, 1);
205199
/* eval_breaker is not set to 1 if thread_can_handle_signals() is false */
206-
COMPUTE_EVAL_BREAKER(interp, ceval, ceval2);
200+
COMPUTE_EVAL_BREAKER(interp, ceval);
207201
}
208202

209203

210204
static inline void
211205
UNSIGNAL_PENDING_SIGNALS(PyInterpreterState *interp)
212206
{
213-
struct _ceval_runtime_state *ceval = &interp->runtime->ceval;
214-
struct _ceval_state *ceval2 = &interp->ceval;
215-
_Py_atomic_store_relaxed(&ceval2->signals_pending, 0);
216-
COMPUTE_EVAL_BREAKER(interp, ceval, ceval2);
207+
struct _ceval_state *ceval = &interp->ceval;
208+
_Py_atomic_store_relaxed(&ceval->signals_pending, 0);
209+
COMPUTE_EVAL_BREAKER(interp, ceval);
217210
}
218211

219212

@@ -229,10 +222,9 @@ SIGNAL_ASYNC_EXC(PyInterpreterState *interp)
229222
static inline void
230223
UNSIGNAL_ASYNC_EXC(PyInterpreterState *interp)
231224
{
232-
struct _ceval_runtime_state *ceval = &interp->runtime->ceval;
233-
struct _ceval_state *ceval2 = &interp->ceval;
234-
ceval2->pending.async_exc = 0;
235-
COMPUTE_EVAL_BREAKER(interp, ceval, ceval2);
225+
struct _ceval_state *ceval = &interp->ceval;
226+
ceval->pending.async_exc = 0;
227+
COMPUTE_EVAL_BREAKER(interp, ceval);
236228
}
237229

238230

@@ -357,17 +349,19 @@ PyEval_ReleaseLock(void)
357349
{
358350
_PyRuntimeState *runtime = &_PyRuntime;
359351
PyThreadState *tstate = _PyRuntimeState_GetThreadState(runtime);
352+
struct _ceval_state *ceval2 = &tstate->interp->ceval;
360353
/* This function must succeed when the current thread state is NULL.
361354
We therefore avoid PyThreadState_Get() which dumps a fatal error
362355
in debug mode. */
363-
drop_gil(&runtime->ceval, tstate);
356+
drop_gil(&runtime->ceval, ceval2, tstate);
364357
}
365358

366359
void
367360
_PyEval_ReleaseLock(PyThreadState *tstate)
368361
{
369362
struct _ceval_runtime_state *ceval = &tstate->interp->runtime->ceval;
370-
drop_gil(ceval, tstate);
363+
struct _ceval_state *ceval2 = &tstate->interp->ceval;
364+
drop_gil(ceval, ceval2, tstate);
371365
}
372366

373367
void
@@ -393,7 +387,9 @@ PyEval_ReleaseThread(PyThreadState *tstate)
393387
if (new_tstate != tstate) {
394388
Py_FatalError("wrong thread state");
395389
}
396-
drop_gil(&runtime->ceval, tstate);
390+
struct _ceval_runtime_state *ceval = &runtime->ceval;
391+
struct _ceval_state *ceval2 = &tstate->interp->ceval;
392+
drop_gil(ceval, ceval2, tstate);
397393
}
398394

399395
#ifdef HAVE_FORK
@@ -439,13 +435,14 @@ PyThreadState *
439435
PyEval_SaveThread(void)
440436
{
441437
_PyRuntimeState *runtime = &_PyRuntime;
442-
struct _ceval_runtime_state *ceval = &runtime->ceval;
443438

444439
PyThreadState *tstate = _PyThreadState_Swap(&runtime->gilstate, NULL);
445440
ensure_tstate_not_null(__func__, tstate);
446441

442+
struct _ceval_runtime_state *ceval = &runtime->ceval;
443+
struct _ceval_state *ceval2 = &tstate->interp->ceval;
447444
assert(gil_created(&ceval->gil));
448-
drop_gil(ceval, tstate);
445+
drop_gil(ceval, ceval2, tstate);
449446
return tstate;
450447
}
451448

@@ -847,12 +844,12 @@ eval_frame_handle_pending(PyThreadState *tstate)
847844
}
848845

849846
/* GIL drop request */
850-
if (_Py_atomic_load_relaxed(&ceval->gil_drop_request)) {
847+
if (_Py_atomic_load_relaxed(&ceval2->gil_drop_request)) {
851848
/* Give another thread a chance */
852849
if (_PyThreadState_Swap(&runtime->gilstate, NULL) != tstate) {
853850
Py_FatalError("tstate mix-up");
854851
}
855-
drop_gil(ceval, tstate);
852+
drop_gil(ceval, ceval2, tstate);
856853

857854
/* Other threads may run now */
858855

Python/ceval_gil.h

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,8 @@ static void recreate_gil(struct _gil_runtime_state *gil)
141141
}
142142

143143
static void
144-
drop_gil(struct _ceval_runtime_state *ceval, PyThreadState *tstate)
144+
drop_gil(struct _ceval_runtime_state *ceval, struct _ceval_state *ceval2,
145+
PyThreadState *tstate)
145146
{
146147
struct _gil_runtime_state *gil = &ceval->gil;
147148
if (!_Py_atomic_load_relaxed(&gil->locked)) {
@@ -163,7 +164,7 @@ drop_gil(struct _ceval_runtime_state *ceval, PyThreadState *tstate)
163164
MUTEX_UNLOCK(gil->mutex);
164165

165166
#ifdef FORCE_SWITCHING
166-
if (_Py_atomic_load_relaxed(&ceval->gil_drop_request) && tstate != NULL) {
167+
if (_Py_atomic_load_relaxed(&ceval2->gil_drop_request) && tstate != NULL) {
167168
MUTEX_LOCK(gil->switch_mutex);
168169
/* Not switched yet => wait */
169170
if (((PyThreadState*)_Py_atomic_load_relaxed(&gil->last_holder)) == tstate)
@@ -226,6 +227,7 @@ take_gil(PyThreadState *tstate)
226227
assert(is_tstate_valid(tstate));
227228
PyInterpreterState *interp = tstate->interp;
228229
struct _ceval_runtime_state *ceval = &interp->runtime->ceval;
230+
struct _ceval_state *ceval2 = &interp->ceval;
229231
struct _gil_runtime_state *gil = &ceval->gil;
230232

231233
/* Check that _PyEval_InitThreads() was called to create the lock */
@@ -289,12 +291,12 @@ take_gil(PyThreadState *tstate)
289291
in take_gil() while the main thread called
290292
wait_for_thread_shutdown() from Py_Finalize(). */
291293
MUTEX_UNLOCK(gil->mutex);
292-
drop_gil(ceval, tstate);
294+
drop_gil(ceval, ceval2, tstate);
293295
PyThread_exit_thread();
294296
}
295297
assert(is_tstate_valid(tstate));
296298

297-
if (_Py_atomic_load_relaxed(&ceval->gil_drop_request)) {
299+
if (_Py_atomic_load_relaxed(&ceval2->gil_drop_request)) {
298300
RESET_GIL_DROP_REQUEST(interp);
299301
}
300302
else {
@@ -303,8 +305,7 @@ take_gil(PyThreadState *tstate)
303305
handle signals.
304306
305307
Note: RESET_GIL_DROP_REQUEST() calls COMPUTE_EVAL_BREAKER(). */
306-
struct _ceval_state *ceval2 = &interp->ceval;
307-
COMPUTE_EVAL_BREAKER(interp, ceval, ceval2);
308+
COMPUTE_EVAL_BREAKER(interp, ceval2);
308309
}
309310

310311
/* Don't access tstate if the thread must exit */

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy