Skip to content

Commit 4652f0d

Browse files
committed
Convert the gilstate into a thread-local.
1 parent be763e5 commit 4652f0d

File tree

3 files changed

+31
-160
lines changed

3 files changed

+31
-160
lines changed

Include/internal/pycore_runtime_init.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,6 @@ extern PyTypeObject _PyExc_MemoryError;
6161
}, \
6262
}, \
6363
}, \
64-
/* A TSS key must be initialized with Py_tss_NEEDS_INIT \
65-
in accordance with the specification. */ \
66-
.autoTSSkey = Py_tss_NEEDS_INIT, \
6764
.parser = _parser_runtime_state_INIT, \
6865
.ceval = { \
6966
.pending_mainthread = { \

Include/internal/pycore_runtime_structs.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -223,12 +223,6 @@ struct pyruntimestate {
223223
struct _pythread_runtime_state threads;
224224
struct _signals_runtime_state signals;
225225

226-
/* Used for the thread state bound to the current thread. */
227-
Py_tss_t autoTSSkey;
228-
229-
/* Used instead of PyThreadState.trash when there is not current tstate. */
230-
Py_tss_t trashTSSkey;
231-
232226
PyWideStringList orig_argv;
233227

234228
struct _parser_runtime_state parser;

Python/pystate.c

Lines changed: 31 additions & 151 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,10 @@ to avoid the expense of doing their own locking).
6969

7070

7171
#ifdef HAVE_THREAD_LOCAL
72+
/* The attached thread state for the current thread. */
7273
_Py_thread_local PyThreadState *_Py_tss_tstate = NULL;
74+
/* The bound gilstate for the current thread. */
75+
_Py_thread_local PyThreadState *_Py_tss_gilstate = NULL;
7376
#endif
7477

7578
static inline PyThreadState *
@@ -118,78 +121,9 @@ _PyThreadState_GetCurrent(void)
118121
}
119122

120123

121-
//------------------------------------------------
122-
// the thread state bound to the current OS thread
123-
//------------------------------------------------
124-
125-
static inline int
126-
tstate_tss_initialized(Py_tss_t *key)
127-
{
128-
return PyThread_tss_is_created(key);
129-
}
130-
131-
static inline int
132-
tstate_tss_init(Py_tss_t *key)
133-
{
134-
assert(!tstate_tss_initialized(key));
135-
return PyThread_tss_create(key);
136-
}
137-
138-
static inline void
139-
tstate_tss_fini(Py_tss_t *key)
140-
{
141-
assert(tstate_tss_initialized(key));
142-
PyThread_tss_delete(key);
143-
}
144-
145-
static inline PyThreadState *
146-
tstate_tss_get(Py_tss_t *key)
147-
{
148-
assert(tstate_tss_initialized(key));
149-
return (PyThreadState *)PyThread_tss_get(key);
150-
}
151-
152-
static inline int
153-
tstate_tss_set(Py_tss_t *key, PyThreadState *tstate)
154-
{
155-
assert(tstate != NULL);
156-
assert(tstate_tss_initialized(key));
157-
return PyThread_tss_set(key, (void *)tstate);
158-
}
159-
160-
static inline int
161-
tstate_tss_clear(Py_tss_t *key)
162-
{
163-
assert(tstate_tss_initialized(key));
164-
return PyThread_tss_set(key, (void *)NULL);
165-
}
166-
167-
#ifdef HAVE_FORK
168-
/* Reset the TSS key - called by PyOS_AfterFork_Child().
169-
* This should not be necessary, but some - buggy - pthread implementations
170-
* don't reset TSS upon fork(), see issue #10517.
171-
*/
172-
static PyStatus
173-
tstate_tss_reinit(Py_tss_t *key)
174-
{
175-
if (!tstate_tss_initialized(key)) {
176-
return _PyStatus_OK();
177-
}
178-
PyThreadState *tstate = tstate_tss_get(key);
179-
180-
tstate_tss_fini(key);
181-
if (tstate_tss_init(key) != 0) {
182-
return _PyStatus_NO_MEMORY();
183-
}
184-
185-
/* If the thread had an associated auto thread state, reassociate it with
186-
* the new key. */
187-
if (tstate && tstate_tss_set(key, tstate) != 0) {
188-
return _PyStatus_ERR("failed to re-set autoTSSkey");
189-
}
190-
return _PyStatus_OK();
191-
}
192-
#endif
124+
//---------------------------------------------
125+
// the GIL state bound to the current OS thread
126+
//---------------------------------------------
193127

194128

195129
/*
@@ -198,36 +132,23 @@ tstate_tss_reinit(Py_tss_t *key)
198132
The GIL does no need to be held for these.
199133
*/
200134

201-
#define gilstate_tss_initialized(runtime) \
202-
tstate_tss_initialized(&(runtime)->autoTSSkey)
203-
#define gilstate_tss_init(runtime) \
204-
tstate_tss_init(&(runtime)->autoTSSkey)
205-
#define gilstate_tss_fini(runtime) \
206-
tstate_tss_fini(&(runtime)->autoTSSkey)
207-
#define gilstate_tss_get(runtime) \
208-
tstate_tss_get(&(runtime)->autoTSSkey)
209-
#define _gilstate_tss_set(runtime, tstate) \
210-
tstate_tss_set(&(runtime)->autoTSSkey, tstate)
211-
#define _gilstate_tss_clear(runtime) \
212-
tstate_tss_clear(&(runtime)->autoTSSkey)
213-
#define gilstate_tss_reinit(runtime) \
214-
tstate_tss_reinit(&(runtime)->autoTSSkey)
135+
static inline PyThreadState *
136+
gilstate_get(void)
137+
{
138+
return _Py_tss_gilstate;
139+
}
215140

216141
static inline void
217-
gilstate_tss_set(_PyRuntimeState *runtime, PyThreadState *tstate)
142+
gilstate_set(PyThreadState *tstate)
218143
{
219-
assert(tstate != NULL && tstate->interp->runtime == runtime);
220-
if (_gilstate_tss_set(runtime, tstate) != 0) {
221-
Py_FatalError("failed to set current tstate (TSS)");
222-
}
144+
assert(tstate != NULL);
145+
_Py_tss_gilstate = tstate;
223146
}
224147

225148
static inline void
226-
gilstate_tss_clear(_PyRuntimeState *runtime)
149+
gilstate_clear(void)
227150
{
228-
if (_gilstate_tss_clear(runtime) != 0) {
229-
Py_FatalError("failed to clear current tstate (TSS)");
230-
}
151+
_Py_tss_gilstate = NULL;
231152
}
232153

233154

@@ -253,7 +174,7 @@ bind_tstate(PyThreadState *tstate)
253174
assert(tstate_is_alive(tstate) && !tstate->_status.bound);
254175
assert(!tstate->_status.unbound); // just in case
255176
assert(!tstate->_status.bound_gilstate);
256-
assert(tstate != gilstate_tss_get(tstate->interp->runtime));
177+
assert(tstate != gilstate_get());
257178
assert(!tstate->_status.active);
258179
assert(tstate->thread_id == 0);
259180
assert(tstate->native_thread_id == 0);
@@ -328,14 +249,13 @@ bind_gilstate_tstate(PyThreadState *tstate)
328249
// XXX assert(!tstate->_status.active);
329250
assert(!tstate->_status.bound_gilstate);
330251

331-
_PyRuntimeState *runtime = tstate->interp->runtime;
332-
PyThreadState *tcur = gilstate_tss_get(runtime);
252+
PyThreadState *tcur = gilstate_get();
333253
assert(tstate != tcur);
334254

335255
if (tcur != NULL) {
336256
tcur->_status.bound_gilstate = 0;
337257
}
338-
gilstate_tss_set(runtime, tstate);
258+
gilstate_set(tstate);
339259
tstate->_status.bound_gilstate = 1;
340260
}
341261

@@ -347,9 +267,9 @@ unbind_gilstate_tstate(PyThreadState *tstate)
347267
assert(tstate_is_bound(tstate));
348268
// XXX assert(!tstate->_status.active);
349269
assert(tstate->_status.bound_gilstate);
350-
assert(tstate == gilstate_tss_get(tstate->interp->runtime));
270+
assert(tstate == gilstate_get());
351271

352-
gilstate_tss_clear(tstate->interp->runtime);
272+
gilstate_clear();
353273
tstate->_status.bound_gilstate = 0;
354274
}
355275

@@ -373,7 +293,7 @@ holds_gil(PyThreadState *tstate)
373293
// (and tstate->interp->runtime->ceval.gil.locked).
374294
assert(tstate != NULL);
375295
/* Must be the tstate for this thread */
376-
assert(tstate == gilstate_tss_get(tstate->interp->runtime));
296+
assert(tstate == gilstate_get());
377297
return tstate == current_fast_get();
378298
}
379299

@@ -469,16 +389,6 @@ _PyRuntimeState_Init(_PyRuntimeState *runtime)
469389
return status;
470390
}
471391

472-
if (gilstate_tss_init(runtime) != 0) {
473-
_PyRuntimeState_Fini(runtime);
474-
return _PyStatus_NO_MEMORY();
475-
}
476-
477-
if (PyThread_tss_create(&runtime->trashTSSkey) != 0) {
478-
_PyRuntimeState_Fini(runtime);
479-
return _PyStatus_NO_MEMORY();
480-
}
481-
482392
init_runtime(runtime, open_code_hook, open_code_userdata, audit_hook_head,
483393
unicode_next_index);
484394

@@ -492,14 +402,6 @@ _PyRuntimeState_Fini(_PyRuntimeState *runtime)
492402
/* The count is cleared by _Py_FinalizeRefTotal(). */
493403
assert(runtime->object_state.interpreter_leaks == 0);
494404
#endif
495-
496-
if (gilstate_tss_initialized(runtime)) {
497-
gilstate_tss_fini(runtime);
498-
}
499-
500-
if (PyThread_tss_is_created(&runtime->trashTSSkey)) {
501-
PyThread_tss_delete(&runtime->trashTSSkey);
502-
}
503405
}
504406

505407
#ifdef HAVE_FORK
@@ -532,18 +434,6 @@ _PyRuntimeState_ReInitThreads(_PyRuntimeState *runtime)
532434

533435
_PyTypes_AfterFork();
534436

535-
PyStatus status = gilstate_tss_reinit(runtime);
536-
if (_PyStatus_EXCEPTION(status)) {
537-
return status;
538-
}
539-
540-
if (PyThread_tss_is_created(&runtime->trashTSSkey)) {
541-
PyThread_tss_delete(&runtime->trashTSSkey);
542-
}
543-
if (PyThread_tss_create(&runtime->trashTSSkey) != 0) {
544-
return _PyStatus_NO_MEMORY();
545-
}
546-
547437
_PyThread_AfterFork(&runtime->threads);
548438

549439
return _PyStatus_OK();
@@ -1629,7 +1519,7 @@ _PyThreadState_NewBound(PyInterpreterState *interp, int whence)
16291519
bind_tstate(tstate);
16301520
// This makes sure there's a gilstate tstate bound
16311521
// as soon as possible.
1632-
if (gilstate_tss_get(tstate->interp->runtime) == NULL) {
1522+
if (gilstate_get() == NULL) {
16331523
bind_gilstate_tstate(tstate);
16341524
}
16351525
}
@@ -2050,7 +1940,7 @@ tstate_activate(PyThreadState *tstate)
20501940
assert(!tstate->_status.active);
20511941

20521942
assert(!tstate->_status.bound_gilstate ||
2053-
tstate == gilstate_tss_get((tstate->interp->runtime)));
1943+
tstate == gilstate_get());
20541944
if (!tstate->_status.bound_gilstate) {
20551945
bind_gilstate_tstate(tstate);
20561946
}
@@ -2515,7 +2405,7 @@ _PyThreadState_Bind(PyThreadState *tstate)
25152405
bind_tstate(tstate);
25162406
// This makes sure there's a gilstate tstate bound
25172407
// as soon as possible.
2518-
if (gilstate_tss_get(tstate->interp->runtime) == NULL) {
2408+
if (gilstate_get() == NULL) {
25192409
bind_gilstate_tstate(tstate);
25202410
}
25212411
}
@@ -2717,7 +2607,7 @@ _PyGILState_Init(PyInterpreterState *interp)
27172607
return _PyStatus_OK();
27182608
}
27192609
_PyRuntimeState *runtime = interp->runtime;
2720-
assert(gilstate_tss_get(runtime) == NULL);
2610+
assert(gilstate_get() == NULL);
27212611
assert(runtime->gilstate.autoInterpreterState == NULL);
27222612
runtime->gilstate.autoInterpreterState = interp;
27232613
return _PyStatus_OK();
@@ -2753,7 +2643,7 @@ _PyGILState_SetTstate(PyThreadState *tstate)
27532643
_PyRuntimeState *runtime = tstate->interp->runtime;
27542644

27552645
assert(runtime->gilstate.autoInterpreterState == tstate->interp);
2756-
assert(gilstate_tss_get(runtime) == tstate);
2646+
assert(gilstate_get() == tstate);
27572647
assert(tstate->gilstate_counter == 1);
27582648
#endif
27592649
}
@@ -2769,11 +2659,7 @@ _PyGILState_GetInterpreterStateUnsafe(void)
27692659
PyThreadState *
27702660
PyGILState_GetThisThreadState(void)
27712661
{
2772-
_PyRuntimeState *runtime = &_PyRuntime;
2773-
if (!gilstate_tss_initialized(runtime)) {
2774-
return NULL;
2775-
}
2776-
return gilstate_tss_get(runtime);
2662+
return gilstate_get();
27772663
}
27782664

27792665
int
@@ -2784,16 +2670,12 @@ PyGILState_Check(void)
27842670
return 1;
27852671
}
27862672

2787-
if (!gilstate_tss_initialized(runtime)) {
2788-
return 1;
2789-
}
2790-
27912673
PyThreadState *tstate = current_fast_get();
27922674
if (tstate == NULL) {
27932675
return 0;
27942676
}
27952677

2796-
PyThreadState *tcur = gilstate_tss_get(runtime);
2678+
PyThreadState *tcur = gilstate_get();
27972679
return (tstate == tcur);
27982680
}
27992681

@@ -2810,10 +2692,9 @@ PyGILState_Ensure(void)
28102692
/* Ensure that _PyEval_InitThreads() and _PyGILState_Init() have been
28112693
called by Py_Initialize() */
28122694
assert(_PyEval_ThreadsInitialized());
2813-
assert(gilstate_tss_initialized(runtime));
28142695
assert(runtime->gilstate.autoInterpreterState != NULL);
28152696

2816-
PyThreadState *tcur = gilstate_tss_get(runtime);
2697+
PyThreadState *tcur = gilstate_get();
28172698
int has_gil;
28182699
if (tcur == NULL) {
28192700
/* Create a new Python thread state for this thread */
@@ -2853,8 +2734,7 @@ PyGILState_Ensure(void)
28532734
void
28542735
PyGILState_Release(PyGILState_STATE oldstate)
28552736
{
2856-
_PyRuntimeState *runtime = &_PyRuntime;
2857-
PyThreadState *tstate = gilstate_tss_get(runtime);
2737+
PyThreadState *tstate = gilstate_get();
28582738
if (tstate == NULL) {
28592739
Py_FatalError("auto-releasing thread-state, "
28602740
"but no thread-state for this thread");

0 commit comments

Comments
 (0)