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