ยปCore Development>Code coverage>Python/thread.c

Python code coverage for Python/thread.c

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