@@ -81,14 +81,14 @@ PyThread_init_thread(void)
81
81
or the size specified by the THREAD_STACK_SIZE macro. */
82
82
static size_t _pythread_stacksize = 0 ;
83
83
84
- #ifdef _POSIX_THREADS
85
- #define PYTHREAD_NAME "pthread"
86
- #include "thread_pthread.h"
87
- #endif
88
-
89
- #ifdef NT_THREADS
90
- #define PYTHREAD_NAME "nt"
91
- #include "thread_nt.h "
84
+ #if defined( _POSIX_THREADS )
85
+ # define PYTHREAD_NAME "pthread"
86
+ # include "thread_pthread.h"
87
+ #elif defined( NT_THREADS )
88
+ # define PYTHREAD_NAME "nt"
89
+ # include "thread_nt.h"
90
+ #else
91
+ # error "Require native thread feature. See https://bugs.python.org/issue30832 "
92
92
#endif
93
93
94
94
@@ -114,13 +114,7 @@ PyThread_set_stacksize(size_t size)
114
114
#endif
115
115
}
116
116
117
- #ifndef Py_HAVE_NATIVE_TLS
118
- /* If the platform has not supplied a platform specific
119
- TLS implementation, provide our own.
120
117
121
- This code stolen from "thread_sgi.h", where it was the only
122
- implementation of an existing Python TLS API.
123
- */
124
118
/* ------------------------------------------------------------------------
125
119
Per-thread data ("key") support.
126
120
@@ -157,205 +151,6 @@ any of the other functions are called. There's also a hidden assumption
157
151
that calls to PyThread_create_key() are serialized externally.
158
152
------------------------------------------------------------------------ */
159
153
160
- /* A singly-linked list of struct key objects remembers all the key->value
161
- * associations. File static keyhead heads the list. keymutex is used
162
- * to enforce exclusion internally.
163
- */
164
- struct key {
165
- /* Next record in the list, or NULL if this is the last record. */
166
- struct key * next ;
167
-
168
- /* The thread id, according to PyThread_get_thread_ident(). */
169
- unsigned long id ;
170
-
171
- /* The key and its associated value. */
172
- int key ;
173
- void * value ;
174
- };
175
-
176
- static struct key * keyhead = NULL ;
177
- static PyThread_type_lock keymutex = NULL ;
178
- static int nkeys = 0 ; /* PyThread_create_key() hands out nkeys+1 next */
179
-
180
- /* Internal helper.
181
- * If the current thread has a mapping for key, the appropriate struct key*
182
- * is returned. NB: value is ignored in this case!
183
- * If there is no mapping for key in the current thread, then:
184
- * If value is NULL, NULL is returned.
185
- * Else a mapping of key to value is created for the current thread,
186
- * and a pointer to a new struct key* is returned; except that if
187
- * malloc() can't find room for a new struct key*, NULL is returned.
188
- * So when value==NULL, this acts like a pure lookup routine, and when
189
- * value!=NULL, this acts like dict.setdefault(), returning an existing
190
- * mapping if one exists, else creating a new mapping.
191
- *
192
- * Caution: this used to be too clever, trying to hold keymutex only
193
- * around the "p->next = keyhead; keyhead = p" pair. That allowed
194
- * another thread to mutate the list, via key deletion, concurrent with
195
- * find_key() crawling over the list. Hilarity ensued. For example, when
196
- * the for-loop here does "p = p->next", p could end up pointing at a
197
- * record that PyThread_delete_key_value() was concurrently free()'ing.
198
- * That could lead to anything, from failing to find a key that exists, to
199
- * segfaults. Now we lock the whole routine.
200
- */
201
- static struct key *
202
- find_key (int set_value , int key , void * value )
203
- {
204
- struct key * p , * prev_p ;
205
- unsigned long id = PyThread_get_thread_ident ();
206
-
207
- if (!keymutex )
208
- return NULL ;
209
- PyThread_acquire_lock (keymutex , 1 );
210
- prev_p = NULL ;
211
- for (p = keyhead ; p != NULL ; p = p -> next ) {
212
- if (p -> id == id && p -> key == key ) {
213
- if (set_value )
214
- p -> value = value ;
215
- goto Done ;
216
- }
217
- /* Sanity check. These states should never happen but if
218
- * they do we must abort. Otherwise we'll end up spinning
219
- * in a tight loop with the lock held. A similar check is done
220
- * in pystate.c tstate_delete_common(). */
221
- if (p == prev_p )
222
- Py_FatalError ("tls find_key: small circular list(!)" );
223
- prev_p = p ;
224
- if (p -> next == keyhead )
225
- Py_FatalError ("tls find_key: circular list(!)" );
226
- }
227
- if (!set_value && value == NULL ) {
228
- assert (p == NULL );
229
- goto Done ;
230
- }
231
- p = (struct key * )PyMem_RawMalloc (sizeof (struct key ));
232
- if (p != NULL ) {
233
- p -> id = id ;
234
- p -> key = key ;
235
- p -> value = value ;
236
- p -> next = keyhead ;
237
- keyhead = p ;
238
- }
239
- Done :
240
- PyThread_release_lock (keymutex );
241
- return p ;
242
- }
243
-
244
- /* Return a new key. This must be called before any other functions in
245
- * this family, and callers must arrange to serialize calls to this
246
- * function. No violations are detected.
247
- */
248
- int
249
- PyThread_create_key (void )
250
- {
251
- /* All parts of this function are wrong if it's called by multiple
252
- * threads simultaneously.
253
- */
254
- if (keymutex == NULL )
255
- keymutex = PyThread_allocate_lock ();
256
- return ++ nkeys ;
257
- }
258
-
259
- /* Forget the associations for key across *all* threads. */
260
- void
261
- PyThread_delete_key (int key )
262
- {
263
- struct key * p , * * q ;
264
-
265
- PyThread_acquire_lock (keymutex , 1 );
266
- q = & keyhead ;
267
- while ((p = * q ) != NULL ) {
268
- if (p -> key == key ) {
269
- * q = p -> next ;
270
- PyMem_RawFree ((void * )p );
271
- /* NB This does *not* free p->value! */
272
- }
273
- else
274
- q = & p -> next ;
275
- }
276
- PyThread_release_lock (keymutex );
277
- }
278
-
279
- int
280
- PyThread_set_key_value (int key , void * value )
281
- {
282
- struct key * p ;
283
-
284
- p = find_key (1 , key , value );
285
- if (p == NULL )
286
- return -1 ;
287
- else
288
- return 0 ;
289
- }
290
-
291
- /* Retrieve the value associated with key in the current thread, or NULL
292
- * if the current thread doesn't have an association for key.
293
- */
294
- void *
295
- PyThread_get_key_value (int key )
296
- {
297
- struct key * p = find_key (0 , key , NULL );
298
-
299
- if (p == NULL )
300
- return NULL ;
301
- else
302
- return p -> value ;
303
- }
304
-
305
- /* Forget the current thread's association for key, if any. */
306
- void
307
- PyThread_delete_key_value (int key )
308
- {
309
- unsigned long id = PyThread_get_thread_ident ();
310
- struct key * p , * * q ;
311
-
312
- PyThread_acquire_lock (keymutex , 1 );
313
- q = & keyhead ;
314
- while ((p = * q ) != NULL ) {
315
- if (p -> key == key && p -> id == id ) {
316
- * q = p -> next ;
317
- PyMem_RawFree ((void * )p );
318
- /* NB This does *not* free p->value! */
319
- break ;
320
- }
321
- else
322
- q = & p -> next ;
323
- }
324
- PyThread_release_lock (keymutex );
325
- }
326
-
327
- /* Forget everything not associated with the current thread id.
328
- * This function is called from PyOS_AfterFork_Child(). It is necessary
329
- * because other thread ids which were in use at the time of the fork
330
- * may be reused for new threads created in the forked process.
331
- */
332
- void
333
- PyThread_ReInitTLS (void )
334
- {
335
- unsigned long id = PyThread_get_thread_ident ();
336
- struct key * p , * * q ;
337
-
338
- if (!keymutex )
339
- return ;
340
-
341
- /* As with interpreter_lock in PyEval_ReInitThreads()
342
- we just create a new lock without freeing the old one */
343
- keymutex = PyThread_allocate_lock ();
344
-
345
- /* Delete all keys which do not match the current thread id */
346
- q = & keyhead ;
347
- while ((p = * q ) != NULL ) {
348
- if (p -> id != id ) {
349
- * q = p -> next ;
350
- PyMem_RawFree ((void * )p );
351
- /* NB This does *not* free p->value! */
352
- }
353
- else
354
- q = & p -> next ;
355
- }
356
- }
357
-
358
- #endif /* Py_HAVE_NATIVE_TLS */
359
154
360
155
PyDoc_STRVAR (threadinfo__doc__ ,
361
156
"sys.thread_info\n\
0 commit comments