• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /* Thread package.
3    This is intended to be usable independently from Python.
4    The implementation for system foobar is in a file thread_foobar.h
5    which is included by this file dependent on config settings.
6    Stuff shared by all thread_*.h files is collected here. */
7 
8 #include "Python.h"
9 
10 #ifndef _POSIX_THREADS
11 /* This means pthreads are not implemented in libc headers, hence the macro
12    not present in unistd.h. But they still can be implemented as an external
13    library (e.g. gnu pth in pthread emulation) */
14 # ifdef HAVE_PTHREAD_H
15 #  include <pthread.h> /* _POSIX_THREADS */
16 # endif
17 #endif
18 
19 #ifndef DONT_HAVE_STDIO_H
20 #include <stdio.h>
21 #endif
22 
23 #include <stdlib.h>
24 
25 #include "pythread.h"
26 
27 #ifndef _POSIX_THREADS
28 
29 /* Check if we're running on HP-UX and _SC_THREADS is defined. If so, then
30    enough of the Posix threads package is implemented to support python
31    threads.
32 
33    This is valid for HP-UX 11.23 running on an ia64 system. If needed, add
34    a check of __ia64 to verify that we're running on an ia64 system instead
35    of a pa-risc system.
36 */
37 #ifdef __hpux
38 #ifdef _SC_THREADS
39 #define _POSIX_THREADS
40 #endif
41 #endif
42 
43 #endif /* _POSIX_THREADS */
44 
45 
46 #ifdef Py_DEBUG
47 static int thread_debug = 0;
48 #define dprintf(args)   (void)((thread_debug & 1) && printf args)
49 #define d2printf(args)  ((thread_debug & 8) && printf args)
50 #else
51 #define dprintf(args)
52 #define d2printf(args)
53 #endif
54 
55 static int initialized;
56 
57 static void PyThread__init_thread(void); /* Forward */
58 
59 void
PyThread_init_thread(void)60 PyThread_init_thread(void)
61 {
62 #ifdef Py_DEBUG
63     char *p = Py_GETENV("PYTHONTHREADDEBUG");
64 
65     if (p) {
66         if (*p)
67             thread_debug = atoi(p);
68         else
69             thread_debug = 1;
70     }
71 #endif /* Py_DEBUG */
72     if (initialized)
73         return;
74     initialized = 1;
75     dprintf(("PyThread_init_thread called\n"));
76     PyThread__init_thread();
77 }
78 
79 /* Support for runtime thread stack size tuning.
80    A value of 0 means using the platform's default stack size
81    or the size specified by the THREAD_STACK_SIZE macro. */
82 static size_t _pythread_stacksize = 0;
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"
92 #endif
93 
94 
95 /*
96 #ifdef FOOBAR_THREADS
97 #include "thread_foobar.h"
98 #endif
99 */
100 
101 /* return the current thread stack size */
102 size_t
PyThread_get_stacksize(void)103 PyThread_get_stacksize(void)
104 {
105     return _pythread_stacksize;
106 }
107 
108 /* Only platforms defining a THREAD_SET_STACKSIZE() macro
109    in thread_<platform>.h support changing the stack size.
110    Return 0 if stack size is valid,
111       -1 if stack size value is invalid,
112       -2 if setting stack size is not supported. */
113 int
PyThread_set_stacksize(size_t size)114 PyThread_set_stacksize(size_t size)
115 {
116 #if defined(THREAD_SET_STACKSIZE)
117     return THREAD_SET_STACKSIZE(size);
118 #else
119     return -2;
120 #endif
121 }
122 
123 #ifndef Py_HAVE_NATIVE_TLS
124 /* If the platform has not supplied a platform specific
125    TLS implementation, provide our own.
126 
127    This code stolen from "thread_sgi.h", where it was the only
128    implementation of an existing Python TLS API.
129 */
130 /* ------------------------------------------------------------------------
131 Per-thread data ("key") support.
132 
133 Use PyThread_create_key() to create a new key.  This is typically shared
134 across threads.
135 
136 Use PyThread_set_key_value(thekey, value) to associate void* value with
137 thekey in the current thread.  Each thread has a distinct mapping of thekey
138 to a void* value.  Caution:  if the current thread already has a mapping
139 for thekey, value is ignored.
140 
141 Use PyThread_get_key_value(thekey) to retrieve the void* value associated
142 with thekey in the current thread.  This returns NULL if no value is
143 associated with thekey in the current thread.
144 
145 Use PyThread_delete_key_value(thekey) to forget the current thread's associated
146 value for thekey.  PyThread_delete_key(thekey) forgets the values associated
147 with thekey across *all* threads.
148 
149 While some of these functions have error-return values, none set any
150 Python exception.
151 
152 None of the functions does memory management on behalf of the void* values.
153 You need to allocate and deallocate them yourself.  If the void* values
154 happen to be PyObject*, these functions don't do refcount operations on
155 them either.
156 
157 The GIL does not need to be held when calling these functions; they supply
158 their own locking.  This isn't true of PyThread_create_key(), though (see
159 next paragraph).
160 
161 There's a hidden assumption that PyThread_create_key() will be called before
162 any of the other functions are called.  There's also a hidden assumption
163 that calls to PyThread_create_key() are serialized externally.
164 ------------------------------------------------------------------------ */
165 
166 /* A singly-linked list of struct key objects remembers all the key->value
167  * associations.  File static keyhead heads the list.  keymutex is used
168  * to enforce exclusion internally.
169  */
170 struct key {
171     /* Next record in the list, or NULL if this is the last record. */
172     struct key *next;
173 
174     /* The thread id, according to PyThread_get_thread_ident(). */
175     long id;
176 
177     /* The key and its associated value. */
178     int key;
179     void *value;
180 };
181 
182 static struct key *keyhead = NULL;
183 static PyThread_type_lock keymutex = NULL;
184 static int nkeys = 0;  /* PyThread_create_key() hands out nkeys+1 next */
185 
186 /* Internal helper.
187  * If the current thread has a mapping for key, the appropriate struct key*
188  * is returned.  NB:  value is ignored in this case!
189  * If there is no mapping for key in the current thread, then:
190  *     If value is NULL, NULL is returned.
191  *     Else a mapping of key to value is created for the current thread,
192  *     and a pointer to a new struct key* is returned; except that if
193  *     malloc() can't find room for a new struct key*, NULL is returned.
194  * So when value==NULL, this acts like a pure lookup routine, and when
195  * value!=NULL, this acts like dict.setdefault(), returning an existing
196  * mapping if one exists, else creating a new mapping.
197  *
198  * Caution:  this used to be too clever, trying to hold keymutex only
199  * around the "p->next = keyhead; keyhead = p" pair.  That allowed
200  * another thread to mutate the list, via key deletion, concurrent with
201  * find_key() crawling over the list.  Hilarity ensued.  For example, when
202  * the for-loop here does "p = p->next", p could end up pointing at a
203  * record that PyThread_delete_key_value() was concurrently free()'ing.
204  * That could lead to anything, from failing to find a key that exists, to
205  * segfaults.  Now we lock the whole routine.
206  */
207 static struct key *
find_key(int set_value,int key,void * value)208 find_key(int set_value, int key, void *value)
209 {
210     struct key *p, *prev_p;
211     long id = PyThread_get_thread_ident();
212 
213     if (!keymutex)
214         return NULL;
215     PyThread_acquire_lock(keymutex, 1);
216     prev_p = NULL;
217     for (p = keyhead; p != NULL; p = p->next) {
218         if (p->id == id && p->key == key) {
219             if (set_value)
220                 p->value = value;
221             goto Done;
222         }
223         /* Sanity check.  These states should never happen but if
224          * they do we must abort.  Otherwise we'll end up spinning
225          * in a tight loop with the lock held.  A similar check is done
226          * in pystate.c tstate_delete_common().  */
227         if (p == prev_p)
228             Py_FatalError("tls find_key: small circular list(!)");
229         prev_p = p;
230         if (p->next == keyhead)
231             Py_FatalError("tls find_key: circular list(!)");
232     }
233     if (!set_value && value == NULL) {
234         assert(p == NULL);
235         goto Done;
236     }
237     p = (struct key *)PyMem_RawMalloc(sizeof(struct key));
238     if (p != NULL) {
239         p->id = id;
240         p->key = key;
241         p->value = value;
242         p->next = keyhead;
243         keyhead = p;
244     }
245  Done:
246     PyThread_release_lock(keymutex);
247     return p;
248 }
249 
250 /* Return a new key.  This must be called before any other functions in
251  * this family, and callers must arrange to serialize calls to this
252  * function.  No violations are detected.
253  */
254 int
PyThread_create_key(void)255 PyThread_create_key(void)
256 {
257     /* All parts of this function are wrong if it's called by multiple
258      * threads simultaneously.
259      */
260     if (keymutex == NULL)
261         keymutex = PyThread_allocate_lock();
262     return ++nkeys;
263 }
264 
265 /* Forget the associations for key across *all* threads. */
266 void
PyThread_delete_key(int key)267 PyThread_delete_key(int key)
268 {
269     struct key *p, **q;
270 
271     PyThread_acquire_lock(keymutex, 1);
272     q = &keyhead;
273     while ((p = *q) != NULL) {
274         if (p->key == key) {
275             *q = p->next;
276             PyMem_RawFree((void *)p);
277             /* NB This does *not* free p->value! */
278         }
279         else
280             q = &p->next;
281     }
282     PyThread_release_lock(keymutex);
283 }
284 
285 int
PyThread_set_key_value(int key,void * value)286 PyThread_set_key_value(int key, void *value)
287 {
288     struct key *p;
289 
290     p = find_key(1, key, value);
291     if (p == NULL)
292         return -1;
293     else
294         return 0;
295 }
296 
297 /* Retrieve the value associated with key in the current thread, or NULL
298  * if the current thread doesn't have an association for key.
299  */
300 void *
PyThread_get_key_value(int key)301 PyThread_get_key_value(int key)
302 {
303     struct key *p = find_key(0, key, NULL);
304 
305     if (p == NULL)
306         return NULL;
307     else
308         return p->value;
309 }
310 
311 /* Forget the current thread's association for key, if any. */
312 void
PyThread_delete_key_value(int key)313 PyThread_delete_key_value(int key)
314 {
315     long id = PyThread_get_thread_ident();
316     struct key *p, **q;
317 
318     PyThread_acquire_lock(keymutex, 1);
319     q = &keyhead;
320     while ((p = *q) != NULL) {
321         if (p->key == key && p->id == id) {
322             *q = p->next;
323             PyMem_RawFree((void *)p);
324             /* NB This does *not* free p->value! */
325             break;
326         }
327         else
328             q = &p->next;
329     }
330     PyThread_release_lock(keymutex);
331 }
332 
333 /* Forget everything not associated with the current thread id.
334  * This function is called from PyOS_AfterFork().  It is necessary
335  * because other thread ids which were in use at the time of the fork
336  * may be reused for new threads created in the forked process.
337  */
338 void
PyThread_ReInitTLS(void)339 PyThread_ReInitTLS(void)
340 {
341     long id = PyThread_get_thread_ident();
342     struct key *p, **q;
343 
344     if (!keymutex)
345         return;
346 
347     /* As with interpreter_lock in PyEval_ReInitThreads()
348        we just create a new lock without freeing the old one */
349     keymutex = PyThread_allocate_lock();
350 
351     /* Delete all keys which do not match the current thread id */
352     q = &keyhead;
353     while ((p = *q) != NULL) {
354         if (p->id != id) {
355             *q = p->next;
356             PyMem_RawFree((void *)p);
357             /* NB This does *not* free p->value! */
358         }
359         else
360             q = &p->next;
361     }
362 }
363 
364 #endif /* Py_HAVE_NATIVE_TLS */
365 
366 PyDoc_STRVAR(threadinfo__doc__,
367 "sys.thread_info\n\
368 \n\
369 A struct sequence holding information about the thread implementation.");
370 
371 static PyStructSequence_Field threadinfo_fields[] = {
372     {"name",    "name of the thread implementation"},
373     {"lock",    "name of the lock implementation"},
374     {"version", "name and version of the thread library"},
375     {0}
376 };
377 
378 static PyStructSequence_Desc threadinfo_desc = {
379     "sys.thread_info",           /* name */
380     threadinfo__doc__,           /* doc */
381     threadinfo_fields,           /* fields */
382     3
383 };
384 
385 static PyTypeObject ThreadInfoType;
386 
387 PyObject*
PyThread_GetInfo(void)388 PyThread_GetInfo(void)
389 {
390     PyObject *threadinfo, *value;
391     int pos = 0;
392 #if (defined(_POSIX_THREADS) && defined(HAVE_CONFSTR) \
393      && defined(_CS_GNU_LIBPTHREAD_VERSION))
394     char buffer[255];
395     int len;
396 #endif
397 
398     if (ThreadInfoType.tp_name == 0) {
399         if (PyStructSequence_InitType2(&ThreadInfoType, &threadinfo_desc) < 0)
400             return NULL;
401     }
402 
403     threadinfo = PyStructSequence_New(&ThreadInfoType);
404     if (threadinfo == NULL)
405         return NULL;
406 
407     value = PyUnicode_FromString(PYTHREAD_NAME);
408     if (value == NULL) {
409         Py_DECREF(threadinfo);
410         return NULL;
411     }
412     PyStructSequence_SET_ITEM(threadinfo, pos++, value);
413 
414 #ifdef _POSIX_THREADS
415 #ifdef USE_SEMAPHORES
416     value = PyUnicode_FromString("semaphore");
417 #else
418     value = PyUnicode_FromString("mutex+cond");
419 #endif
420     if (value == NULL) {
421         Py_DECREF(threadinfo);
422         return NULL;
423     }
424 #else
425     Py_INCREF(Py_None);
426     value = Py_None;
427 #endif
428     PyStructSequence_SET_ITEM(threadinfo, pos++, value);
429 
430 #if (defined(_POSIX_THREADS) && defined(HAVE_CONFSTR) \
431      && defined(_CS_GNU_LIBPTHREAD_VERSION))
432     value = NULL;
433     len = confstr(_CS_GNU_LIBPTHREAD_VERSION, buffer, sizeof(buffer));
434     if (1 < len && (size_t)len < sizeof(buffer)) {
435         value = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1);
436         if (value == NULL)
437             PyErr_Clear();
438     }
439     if (value == NULL)
440 #endif
441     {
442         Py_INCREF(Py_None);
443         value = Py_None;
444     }
445     PyStructSequence_SET_ITEM(threadinfo, pos++, value);
446     return threadinfo;
447 }
448