@@ -81,14 +81,14 @@ PyThread_init_thread(void)
8181 or the size specified by the THREAD_STACK_SIZE macro. */
8282static size_t _pythread_stacksize = 0 ;
8383
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 "
9292#endif
9393
9494
@@ -114,13 +114,7 @@ PyThread_set_stacksize(size_t size)
114114#endif
115115}
116116
117- #ifndef Py_HAVE_NATIVE_TLS
118- /* If the platform has not supplied a platform specific
119- TLS implementation, provide our own.
120117
121- This code stolen from "thread_sgi.h", where it was the only
122- implementation of an existing Python TLS API.
123- */
124118/* ------------------------------------------------------------------------
125119Per-thread data ("key") support.
126120
@@ -157,205 +151,6 @@ any of the other functions are called. There's also a hidden assumption
157151that calls to PyThread_create_key() are serialized externally.
158152------------------------------------------------------------------------ */
159153
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 */
359154
360155PyDoc_STRVAR (threadinfo__doc__ ,
361156"sys.thread_info\n\
0 commit comments