Branch data 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 : : #include "pycore_pystate.h" // _PyInterpreterState_GET() 10 : : #include "pycore_structseq.h" // _PyStructSequence_FiniType() 11 : : 12 : : #ifndef _POSIX_THREADS 13 : : /* This means pthreads are not implemented in libc headers, hence the macro 14 : : not present in unistd.h. But they still can be implemented as an external 15 : : library (e.g. gnu pth in pthread emulation) */ 16 : : # ifdef HAVE_PTHREAD_H 17 : : # include <pthread.h> /* _POSIX_THREADS */ 18 : : # endif 19 : : #endif 20 : : 21 : : #ifndef DONT_HAVE_STDIO_H 22 : : #include <stdio.h> 23 : : #endif 24 : : 25 : : #include <stdlib.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 : : static int initialized; 46 : : 47 : : static void PyThread__init_thread(void); /* Forward */ 48 : : 49 : : void 50 : 9056 : PyThread_init_thread(void) 51 : : { 52 [ + + ]: 9056 : if (initialized) 53 : 6102 : return; 54 : 2954 : initialized = 1; 55 : 2954 : PyThread__init_thread(); 56 : : } 57 : : 58 : : #if defined(_POSIX_THREADS) 59 : : # define PYTHREAD_NAME "pthread" 60 : : # include "thread_pthread.h" 61 : : #elif defined(NT_THREADS) 62 : : # define PYTHREAD_NAME "nt" 63 : : # include "thread_nt.h" 64 : : #else 65 : : # error "Require native threads. See https://bugs.python.org/issue31370" 66 : : #endif 67 : : 68 : : 69 : : /* return the current thread stack size */ 70 : : size_t 71 : 15 : PyThread_get_stacksize(void) 72 : : { 73 : 15 : return _PyInterpreterState_GET()->threads.stacksize; 74 : : } 75 : : 76 : : /* Only platforms defining a THREAD_SET_STACKSIZE() macro 77 : : in thread_<platform>.h support changing the stack size. 78 : : Return 0 if stack size is valid, 79 : : -1 if stack size value is invalid, 80 : : -2 if setting stack size is not supported. */ 81 : : int 82 : 15 : PyThread_set_stacksize(size_t size) 83 : : { 84 : : #if defined(THREAD_SET_STACKSIZE) 85 : 15 : return THREAD_SET_STACKSIZE(size); 86 : : #else 87 : : return -2; 88 : : #endif 89 : : } 90 : : 91 : : 92 : : /* Thread Specific Storage (TSS) API 93 : : 94 : : Cross-platform components of TSS API implementation. 95 : : */ 96 : : 97 : : Py_tss_t * 98 : 1 : PyThread_tss_alloc(void) 99 : : { 100 : 1 : Py_tss_t *new_key = (Py_tss_t *)PyMem_RawMalloc(sizeof(Py_tss_t)); 101 [ - + ]: 1 : if (new_key == NULL) { 102 : 0 : return NULL; 103 : : } 104 : 1 : new_key->_is_initialized = 0; 105 : 1 : return new_key; 106 : : } 107 : : 108 : : void 109 : 1 : PyThread_tss_free(Py_tss_t *key) 110 : : { 111 [ + - ]: 1 : if (key != NULL) { 112 : 1 : PyThread_tss_delete(key); 113 : 1 : PyMem_RawFree((void *)key); 114 : : } 115 : 1 : } 116 : : 117 : : int 118 : 6945649 : PyThread_tss_is_created(Py_tss_t *key) 119 : : { 120 : : assert(key != NULL); 121 : 6945649 : return key->_is_initialized; 122 : : } 123 : : 124 : : 125 : : PyDoc_STRVAR(threadinfo__doc__, 126 : : "sys.thread_info\n\ 127 : : \n\ 128 : : A named tuple holding information about the thread implementation."); 129 : : 130 : : static PyStructSequence_Field threadinfo_fields[] = { 131 : : {"name", "name of the thread implementation"}, 132 : : {"lock", "name of the lock implementation"}, 133 : : {"version", "name and version of the thread library"}, 134 : : {0} 135 : : }; 136 : : 137 : : static PyStructSequence_Desc threadinfo_desc = { 138 : : "sys.thread_info", /* name */ 139 : : threadinfo__doc__, /* doc */ 140 : : threadinfo_fields, /* fields */ 141 : : 3 142 : : }; 143 : : 144 : : static PyTypeObject ThreadInfoType; 145 : : 146 : : PyObject* 147 : 3138 : PyThread_GetInfo(void) 148 : : { 149 : : PyObject *threadinfo, *value; 150 : 3138 : int pos = 0; 151 : : #if (defined(_POSIX_THREADS) && defined(HAVE_CONFSTR) \ 152 : : && defined(_CS_GNU_LIBPTHREAD_VERSION)) 153 : : char buffer[255]; 154 : : int len; 155 : : #endif 156 : : 157 [ + + ]: 3138 : if (ThreadInfoType.tp_name == 0) { 158 [ - + ]: 2967 : if (PyStructSequence_InitType2(&ThreadInfoType, &threadinfo_desc) < 0) 159 : 0 : return NULL; 160 : : } 161 : : 162 : 3138 : threadinfo = PyStructSequence_New(&ThreadInfoType); 163 [ - + ]: 3138 : if (threadinfo == NULL) 164 : 0 : return NULL; 165 : : 166 : 3138 : value = PyUnicode_FromString(PYTHREAD_NAME); 167 [ - + ]: 3138 : if (value == NULL) { 168 : 0 : Py_DECREF(threadinfo); 169 : 0 : return NULL; 170 : : } 171 : 3138 : PyStructSequence_SET_ITEM(threadinfo, pos++, value); 172 : : 173 : : #ifdef _POSIX_THREADS 174 : : #ifdef USE_SEMAPHORES 175 : 3138 : value = PyUnicode_FromString("semaphore"); 176 : : #else 177 : : value = PyUnicode_FromString("mutex+cond"); 178 : : #endif 179 [ - + ]: 3138 : if (value == NULL) { 180 : 0 : Py_DECREF(threadinfo); 181 : 0 : return NULL; 182 : : } 183 : : #else 184 : : Py_INCREF(Py_None); 185 : : value = Py_None; 186 : : #endif 187 : 3138 : PyStructSequence_SET_ITEM(threadinfo, pos++, value); 188 : : 189 : : #if (defined(_POSIX_THREADS) && defined(HAVE_CONFSTR) \ 190 : : && defined(_CS_GNU_LIBPTHREAD_VERSION)) 191 : 3138 : value = NULL; 192 : 3138 : len = confstr(_CS_GNU_LIBPTHREAD_VERSION, buffer, sizeof(buffer)); 193 [ + - + - ]: 3138 : if (1 < len && (size_t)len < sizeof(buffer)) { 194 : 3138 : value = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1); 195 [ - + ]: 3138 : if (value == NULL) 196 : 0 : PyErr_Clear(); 197 : : } 198 [ - + ]: 3138 : if (value == NULL) 199 : : #endif 200 : : { 201 : 0 : Py_INCREF(Py_None); 202 : 0 : value = Py_None; 203 : : } 204 : 3138 : PyStructSequence_SET_ITEM(threadinfo, pos++, value); 205 : 3138 : return threadinfo; 206 : : } 207 : : 208 : : 209 : : void 210 : 3125 : _PyThread_FiniType(PyInterpreterState *interp) 211 : : { 212 [ + + ]: 3125 : if (!_Py_IsMainInterpreter(interp)) { 213 : 169 : return; 214 : : } 215 : : 216 : 2956 : _PyStructSequence_FiniType(&ThreadInfoType); 217 : : }