/src/Python-3.8.3/Python/thread.c
Line  | Count  | Source  | 
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  |  | #include "pycore_pystate.h"  | 
10  |  |  | 
11  |  | #ifndef _POSIX_THREADS  | 
12  |  | /* This means pthreads are not implemented in libc headers, hence the macro  | 
13  |  |    not present in unistd.h. But they still can be implemented as an external  | 
14  |  |    library (e.g. gnu pth in pthread emulation) */  | 
15  |  | # ifdef HAVE_PTHREAD_H  | 
16  |  | #  include <pthread.h> /* _POSIX_THREADS */  | 
17  |  | # endif  | 
18  |  | #endif  | 
19  |  |  | 
20  |  | #ifndef DONT_HAVE_STDIO_H  | 
21  |  | #include <stdio.h>  | 
22  |  | #endif  | 
23  |  |  | 
24  |  | #include <stdlib.h>  | 
25  |  |  | 
26  |  | #include "pythread.h"  | 
27  |  |  | 
28  |  | #ifndef _POSIX_THREADS  | 
29  |  |  | 
30  |  | /* Check if we're running on HP-UX and _SC_THREADS is defined. If so, then  | 
31  |  |    enough of the Posix threads package is implemented to support python  | 
32  |  |    threads.  | 
33  |  |  | 
34  |  |    This is valid for HP-UX 11.23 running on an ia64 system. If needed, add  | 
35  |  |    a check of __ia64 to verify that we're running on an ia64 system instead  | 
36  |  |    of a pa-risc system.  | 
37  |  | */  | 
38  |  | #ifdef __hpux  | 
39  |  | #ifdef _SC_THREADS  | 
40  |  | #define _POSIX_THREADS  | 
41  |  | #endif  | 
42  |  | #endif  | 
43  |  |  | 
44  |  | #endif /* _POSIX_THREADS */  | 
45  |  |  | 
46  |  |  | 
47  |  | #ifdef Py_DEBUG  | 
48  |  | static int thread_debug = 0;  | 
49  |  | #define dprintf(args)   (void)((thread_debug & 1) && printf args)  | 
50  |  | #define d2printf(args)  ((thread_debug & 8) && printf args)  | 
51  |  | #else  | 
52  |  | #define dprintf(args)  | 
53  |  | #define d2printf(args)  | 
54  |  | #endif  | 
55  |  |  | 
56  |  | static int initialized;  | 
57  |  |  | 
58  |  | static void PyThread__init_thread(void); /* Forward */  | 
59  |  |  | 
60  |  | void  | 
61  |  | PyThread_init_thread(void)  | 
62  | 42  | { | 
63  |  | #ifdef Py_DEBUG  | 
64  |  |     const char *p = Py_GETENV("PYTHONTHREADDEBUG"); | 
65  |  |  | 
66  |  |     if (p) { | 
67  |  |         if (*p)  | 
68  |  |             thread_debug = atoi(p);  | 
69  |  |         else  | 
70  |  |             thread_debug = 1;  | 
71  |  |     }  | 
72  |  | #endif /* Py_DEBUG */  | 
73  | 42  |     if (initialized)  | 
74  | 28  |         return;  | 
75  | 14  |     initialized = 1;  | 
76  | 14  |     dprintf(("PyThread_init_thread called\n")); | 
77  | 14  |     PyThread__init_thread();  | 
78  | 14  | }  | 
79  |  |  | 
80  |  | #if defined(_POSIX_THREADS)  | 
81  | 14  | #   define PYTHREAD_NAME "pthread"  | 
82  |  | #   include "thread_pthread.h"  | 
83  |  | #elif defined(NT_THREADS)  | 
84  |  | #   define PYTHREAD_NAME "nt"  | 
85  |  | #   include "thread_nt.h"  | 
86  |  | #else  | 
87  |  | #   error "Require native threads. See https://bugs.python.org/issue31370"  | 
88  |  | #endif  | 
89  |  |  | 
90  |  |  | 
91  |  | /* return the current thread stack size */  | 
92  |  | size_t  | 
93  |  | PyThread_get_stacksize(void)  | 
94  | 0  | { | 
95  | 0  |     return _PyInterpreterState_Get()->pythread_stacksize;  | 
96  | 0  | }  | 
97  |  |  | 
98  |  | /* Only platforms defining a THREAD_SET_STACKSIZE() macro  | 
99  |  |    in thread_<platform>.h support changing the stack size.  | 
100  |  |    Return 0 if stack size is valid,  | 
101  |  |       -1 if stack size value is invalid,  | 
102  |  |       -2 if setting stack size is not supported. */  | 
103  |  | int  | 
104  |  | PyThread_set_stacksize(size_t size)  | 
105  | 0  | { | 
106  | 0  | #if defined(THREAD_SET_STACKSIZE)  | 
107  | 0  |     return THREAD_SET_STACKSIZE(size);  | 
108  |  | #else  | 
109  |  |     return -2;  | 
110  |  | #endif  | 
111  | 0  | }  | 
112  |  |  | 
113  |  |  | 
114  |  | /* Thread Specific Storage (TSS) API  | 
115  |  |  | 
116  |  |    Cross-platform components of TSS API implementation.  | 
117  |  | */  | 
118  |  |  | 
119  |  | Py_tss_t *  | 
120  |  | PyThread_tss_alloc(void)  | 
121  | 0  | { | 
122  | 0  |     Py_tss_t *new_key = (Py_tss_t *)PyMem_RawMalloc(sizeof(Py_tss_t));  | 
123  | 0  |     if (new_key == NULL) { | 
124  | 0  |         return NULL;  | 
125  | 0  |     }  | 
126  | 0  |     new_key->_is_initialized = 0;  | 
127  | 0  |     return new_key;  | 
128  | 0  | }  | 
129  |  |  | 
130  |  | void  | 
131  |  | PyThread_tss_free(Py_tss_t *key)  | 
132  | 0  | { | 
133  | 0  |     if (key != NULL) { | 
134  | 0  |         PyThread_tss_delete(key);  | 
135  | 0  |         PyMem_RawFree((void *)key);  | 
136  | 0  |     }  | 
137  | 0  | }  | 
138  |  |  | 
139  |  | int  | 
140  |  | PyThread_tss_is_created(Py_tss_t *key)  | 
141  | 0  | { | 
142  | 0  |     assert(key != NULL);  | 
143  | 0  |     return key->_is_initialized;  | 
144  | 0  | }  | 
145  |  |  | 
146  |  |  | 
147  |  | PyDoc_STRVAR(threadinfo__doc__,  | 
148  |  | "sys.thread_info\n\  | 
149  |  | \n\  | 
150  |  | A named tuple holding information about the thread implementation.");  | 
151  |  |  | 
152  |  | static PyStructSequence_Field threadinfo_fields[] = { | 
153  |  |     {"name",    "name of the thread implementation"}, | 
154  |  |     {"lock",    "name of the lock implementation"}, | 
155  |  |     {"version", "name and version of the thread library"}, | 
156  |  |     {0} | 
157  |  | };  | 
158  |  |  | 
159  |  | static PyStructSequence_Desc threadinfo_desc = { | 
160  |  |     "sys.thread_info",           /* name */  | 
161  |  |     threadinfo__doc__,           /* doc */  | 
162  |  |     threadinfo_fields,           /* fields */  | 
163  |  |     3  | 
164  |  | };  | 
165  |  |  | 
166  |  | static PyTypeObject ThreadInfoType;  | 
167  |  |  | 
168  |  | PyObject*  | 
169  |  | PyThread_GetInfo(void)  | 
170  | 14  | { | 
171  | 14  |     PyObject *threadinfo, *value;  | 
172  | 14  |     int pos = 0;  | 
173  | 14  | #if (defined(_POSIX_THREADS) && defined(HAVE_CONFSTR) \  | 
174  | 14  |      && defined(_CS_GNU_LIBPTHREAD_VERSION))  | 
175  | 14  |     char buffer[255];  | 
176  | 14  |     int len;  | 
177  | 14  | #endif  | 
178  |  |  | 
179  | 14  |     if (ThreadInfoType.tp_name == 0) { | 
180  | 14  |         if (PyStructSequence_InitType2(&ThreadInfoType, &threadinfo_desc) < 0)  | 
181  | 0  |             return NULL;  | 
182  | 14  |     }  | 
183  |  |  | 
184  | 14  |     threadinfo = PyStructSequence_New(&ThreadInfoType);  | 
185  | 14  |     if (threadinfo == NULL)  | 
186  | 0  |         return NULL;  | 
187  |  |  | 
188  | 14  |     value = PyUnicode_FromString(PYTHREAD_NAME);  | 
189  | 14  |     if (value == NULL) { | 
190  | 0  |         Py_DECREF(threadinfo);  | 
191  | 0  |         return NULL;  | 
192  | 0  |     }  | 
193  | 14  |     PyStructSequence_SET_ITEM(threadinfo, pos++, value);  | 
194  |  |  | 
195  | 14  | #ifdef _POSIX_THREADS  | 
196  | 14  | #ifdef USE_SEMAPHORES  | 
197  | 14  |     value = PyUnicode_FromString("semaphore"); | 
198  |  | #else  | 
199  |  |     value = PyUnicode_FromString("mutex+cond"); | 
200  |  | #endif  | 
201  | 14  |     if (value == NULL) { | 
202  | 0  |         Py_DECREF(threadinfo);  | 
203  | 0  |         return NULL;  | 
204  | 0  |     }  | 
205  |  | #else  | 
206  |  |     Py_INCREF(Py_None);  | 
207  |  |     value = Py_None;  | 
208  |  | #endif  | 
209  | 14  |     PyStructSequence_SET_ITEM(threadinfo, pos++, value);  | 
210  |  |  | 
211  | 14  | #if (defined(_POSIX_THREADS) && defined(HAVE_CONFSTR) \  | 
212  | 14  |      && defined(_CS_GNU_LIBPTHREAD_VERSION))  | 
213  | 14  |     value = NULL;  | 
214  | 14  |     len = confstr(_CS_GNU_LIBPTHREAD_VERSION, buffer, sizeof(buffer));  | 
215  | 14  |     if (1 < len && (size_t)len < sizeof(buffer)) { | 
216  | 14  |         value = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1);  | 
217  | 14  |         if (value == NULL)  | 
218  | 0  |             PyErr_Clear();  | 
219  | 14  |     }  | 
220  | 14  |     if (value == NULL)  | 
221  | 0  | #endif  | 
222  | 0  |     { | 
223  | 0  |         Py_INCREF(Py_None);  | 
224  | 0  |         value = Py_None;  | 
225  | 0  |     }  | 
226  |  |     PyStructSequence_SET_ITEM(threadinfo, pos++, value);  | 
227  | 14  |     return threadinfo;  | 
228  | 14  | }  |