@@ -38,7 +38,6 @@ extern "C" {
38
38
#endif
39
39
40
40
/* Forward declarations */
41
- static void _PyGILState_NoteThreadState (PyThreadState * tstate );
42
41
static void _PyThreadState_Delete (PyThreadState * tstate , int check_current );
43
42
44
43
@@ -149,6 +148,64 @@ current_tss_reinit(_PyRuntimeState *runtime)
149
148
}
150
149
#endif
151
150
151
+ static void
152
+ bind_tstate (PyThreadState * tstate )
153
+ {
154
+ assert (tstate != NULL );
155
+ assert (tstate -> thread_id == 0 );
156
+ assert (tstate -> native_thread_id == 0 );
157
+ _PyRuntimeState * runtime = tstate -> interp -> runtime ;
158
+
159
+ /* Stick the thread state for this thread in thread specific storage.
160
+
161
+ The only situation where you can legitimately have more than one
162
+ thread state for an OS level thread is when there are multiple
163
+ interpreters.
164
+
165
+ You shouldn't really be using the PyGILState_ APIs anyway (see issues
166
+ #10915 and #15751).
167
+
168
+ The first thread state created for that given OS level thread will
169
+ "win", which seems reasonable behaviour.
170
+ */
171
+ /* When a thread state is created for a thread by some mechanism
172
+ other than PyGILState_Ensure(), it's important that the GILState
173
+ machinery knows about it so it doesn't try to create another
174
+ thread state for the thread.
175
+ (This is a better fix for SF bug #1010677 than the first one attempted.)
176
+ */
177
+ // XXX Skipping like this does not play nice with multiple interpreters.
178
+ if (current_tss_get (runtime ) == NULL ) {
179
+ current_tss_set (runtime , tstate );
180
+ }
181
+
182
+ tstate -> thread_id = PyThread_get_thread_ident ();
183
+ #ifdef PY_HAVE_THREAD_NATIVE_ID
184
+ tstate -> native_thread_id = PyThread_get_thread_native_id ();
185
+ #endif
186
+ }
187
+
188
+ static void
189
+ unbind_tstate (PyThreadState * tstate )
190
+ {
191
+ assert (tstate != NULL );
192
+ assert (tstate -> thread_id > 0 );
193
+ #ifdef PY_HAVE_THREAD_NATIVE_ID
194
+ assert (tstate -> native_thread_id > 0 );
195
+ #endif
196
+ _PyRuntimeState * runtime = tstate -> interp -> runtime ;
197
+
198
+ if (current_tss_initialized (runtime ) &&
199
+ tstate == current_tss_get (runtime ))
200
+ {
201
+ current_tss_clear (runtime );
202
+ }
203
+
204
+ // -1 makes sure the thread state won't be re-bound.
205
+ tstate -> thread_id = -1 ;
206
+ tstate -> native_thread_id = -1 ;
207
+ }
208
+
152
209
153
210
/* the global runtime */
154
211
@@ -926,17 +983,18 @@ init_threadstate(PyThreadState *tstate,
926
983
tstate -> next = next ;
927
984
assert (tstate -> prev == NULL );
928
985
929
- tstate -> thread_id = PyThread_get_thread_ident ();
930
- #ifdef PY_HAVE_THREAD_NATIVE_ID
931
- tstate -> native_thread_id = PyThread_get_thread_native_id ();
932
- #endif
986
+ // thread_id and native_thread_id are set in bind_tstate().
933
987
934
988
tstate -> py_recursion_limit = interp -> ceval .recursion_limit ,
935
989
tstate -> py_recursion_remaining = interp -> ceval .recursion_limit ,
936
990
tstate -> c_recursion_remaining = C_RECURSION_LIMIT ;
937
991
938
992
tstate -> exc_info = & tstate -> exc_state ;
939
993
994
+ // PyGILState_Release must not try to delete this thread state.
995
+ // This is cleared when PyGILState_Ensure() creates the thread sate.
996
+ tstate -> gilstate_counter = 1 ;
997
+
940
998
tstate -> cframe = & tstate -> root_cframe ;
941
999
tstate -> datastack_chunk = NULL ;
942
1000
tstate -> datastack_top = NULL ;
@@ -1001,11 +1059,12 @@ PyThreadState_New(PyInterpreterState *interp)
1001
1059
{
1002
1060
PyThreadState * tstate = new_threadstate (interp );
1003
1061
if (tstate ) {
1004
- _PyThreadState_SetCurrent (tstate );
1062
+ bind_tstate (tstate );
1005
1063
}
1006
1064
return tstate ;
1007
1065
}
1008
1066
1067
+ // This must be followed by a call to _PyThreadState_Bind();
1009
1068
PyThreadState *
1010
1069
_PyThreadState_Prealloc (PyInterpreterState * interp )
1011
1070
{
@@ -1021,10 +1080,9 @@ _PyThreadState_Init(PyThreadState *tstate)
1021
1080
}
1022
1081
1023
1082
void
1024
- _PyThreadState_SetCurrent (PyThreadState * tstate )
1083
+ _PyThreadState_Bind (PyThreadState * tstate )
1025
1084
{
1026
- assert (tstate != NULL );
1027
- _PyGILState_NoteThreadState (tstate );
1085
+ bind_tstate (tstate );
1028
1086
}
1029
1087
1030
1088
PyObject *
@@ -1229,11 +1287,7 @@ tstate_delete_common(PyThreadState *tstate)
1229
1287
HEAD_UNLOCK (runtime );
1230
1288
1231
1289
// XXX Do this in PyThreadState_Swap() (and assert not-equal here)?
1232
- if (current_tss_initialized (runtime ) &&
1233
- tstate == current_tss_get (runtime ))
1234
- {
1235
- current_tss_clear (runtime );
1236
- }
1290
+ unbind_tstate (tstate );
1237
1291
1238
1292
// XXX Move to PyThreadState_Clear()?
1239
1293
_PyStackChunk * chunk = tstate -> datastack_chunk ;
@@ -1714,38 +1768,6 @@ _PyGILState_GetInterpreterStateUnsafe(void)
1714
1768
return _PyRuntime .gilstate .autoInterpreterState ;
1715
1769
}
1716
1770
1717
- /* When a thread state is created for a thread by some mechanism other than
1718
- PyGILState_Ensure, it's important that the GILState machinery knows about
1719
- it so it doesn't try to create another thread state for the thread (this is
1720
- a better fix for SF bug #1010677 than the first one attempted).
1721
- */
1722
- static void
1723
- _PyGILState_NoteThreadState (PyThreadState * tstate )
1724
- {
1725
- assert (tstate != NULL );
1726
- _PyRuntimeState * runtime = tstate -> interp -> runtime ;
1727
- assert (current_tss_initialized (runtime ));
1728
-
1729
- /* Stick the thread state for this thread in thread specific storage.
1730
-
1731
- The only situation where you can legitimately have more than one
1732
- thread state for an OS level thread is when there are multiple
1733
- interpreters.
1734
-
1735
- You shouldn't really be using the PyGILState_ APIs anyway (see issues
1736
- #10915 and #15751).
1737
-
1738
- The first thread state created for that given OS level thread will
1739
- "win", which seems reasonable behaviour.
1740
- */
1741
- if (current_tss_get (runtime ) == NULL ) {
1742
- current_tss_set (runtime , tstate );
1743
- }
1744
-
1745
- /* PyGILState_Release must not try to delete this thread state. */
1746
- tstate -> gilstate_counter = 1 ;
1747
- }
1748
-
1749
1771
/* The public functions */
1750
1772
1751
1773
PyThreadState *
@@ -1805,6 +1827,7 @@ PyGILState_Ensure(void)
1805
1827
1806
1828
/* This is our thread state! We'll need to delete it in the
1807
1829
matching call to PyGILState_Release(). */
1830
+ assert (tcur -> gilstate_counter == 1 );
1808
1831
tcur -> gilstate_counter = 0 ;
1809
1832
current = 0 ; /* new thread state is never current */
1810
1833
}
0 commit comments