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 : : #include "pycore_pythread.h" 12 : : 13 : : #ifndef DONT_HAVE_STDIO_H 14 : : #include <stdio.h> 15 : : #endif 16 : : 17 : : #include <stdlib.h> 18 : : 19 : : 20 : : static void PyThread__init_thread(void); /* Forward */ 21 : : 22 : : #define initialized _PyRuntime.threads.initialized 23 : : 24 : : void 25 : 84 : PyThread_init_thread(void) 26 : : { 27 [ + + ]: 84 : if (initialized) { 28 : 55 : return; 29 : : } 30 : 29 : initialized = 1; 31 : 29 : PyThread__init_thread(); 32 : : } 33 : : 34 : : #if defined(HAVE_PTHREAD_STUBS) 35 : : # define PYTHREAD_NAME "pthread-stubs" 36 : : # include "thread_pthread_stubs.h" 37 : : #elif defined(_USE_PTHREADS) /* AKA _PTHREADS */ 38 : : # if defined(__EMSCRIPTEN__) && !defined(__EMSCRIPTEN_PTHREADS__) 39 : : # define PYTHREAD_NAME "pthread-stubs" 40 : : # else 41 : : # define PYTHREAD_NAME "pthread" 42 : : # endif 43 : : # include "thread_pthread.h" 44 : : #elif defined(NT_THREADS) 45 : : # define PYTHREAD_NAME "nt" 46 : : # include "thread_nt.h" 47 : : #else 48 : : # error "Require native threads. See https://bugs.python.org/issue31370" 49 : : #endif 50 : : 51 : : 52 : : /* return the current thread stack size */ 53 : : size_t 54 : 0 : PyThread_get_stacksize(void) 55 : : { 56 : 0 : return _PyInterpreterState_GET()->threads.stacksize; 57 : : } 58 : : 59 : : /* Only platforms defining a THREAD_SET_STACKSIZE() macro 60 : : in thread_<platform>.h support changing the stack size. 61 : : Return 0 if stack size is valid, 62 : : -1 if stack size value is invalid, 63 : : -2 if setting stack size is not supported. */ 64 : : int 65 : 0 : PyThread_set_stacksize(size_t size) 66 : : { 67 : : #if defined(THREAD_SET_STACKSIZE) 68 : 0 : return THREAD_SET_STACKSIZE(size); 69 : : #else 70 : : return -2; 71 : : #endif 72 : : } 73 : : 74 : : 75 : : /* Thread Specific Storage (TSS) API 76 : : 77 : : Cross-platform components of TSS API implementation. 78 : : */ 79 : : 80 : : Py_tss_t * 81 : 0 : PyThread_tss_alloc(void) 82 : : { 83 : 0 : Py_tss_t *new_key = (Py_tss_t *)PyMem_RawMalloc(sizeof(Py_tss_t)); 84 [ # # ]: 0 : if (new_key == NULL) { 85 : 0 : return NULL; 86 : : } 87 : 0 : new_key->_is_initialized = 0; 88 : 0 : return new_key; 89 : : } 90 : : 91 : : void 92 : 0 : PyThread_tss_free(Py_tss_t *key) 93 : : { 94 [ # # ]: 0 : if (key != NULL) { 95 : 0 : PyThread_tss_delete(key); 96 : 0 : PyMem_RawFree((void *)key); 97 : : } 98 : 0 : } 99 : : 100 : : int 101 : 100 : PyThread_tss_is_created(Py_tss_t *key) 102 : : { 103 : : assert(key != NULL); 104 : 100 : return key->_is_initialized; 105 : : } 106 : : 107 : : 108 : : PyDoc_STRVAR(threadinfo__doc__, 109 : : "sys.thread_info\n\ 110 : : \n\ 111 : : A named tuple holding information about the thread implementation."); 112 : : 113 : : static PyStructSequence_Field threadinfo_fields[] = { 114 : : {"name", "name of the thread implementation"}, 115 : : {"lock", "name of the lock implementation"}, 116 : : {"version", "name and version of the thread library"}, 117 : : {0} 118 : : }; 119 : : 120 : : static PyStructSequence_Desc threadinfo_desc = { 121 : : "sys.thread_info", /* name */ 122 : : threadinfo__doc__, /* doc */ 123 : : threadinfo_fields, /* fields */ 124 : : 3 125 : : }; 126 : : 127 : : static PyTypeObject ThreadInfoType; 128 : : 129 : : PyObject* 130 : 29 : PyThread_GetInfo(void) 131 : : { 132 : : PyObject *threadinfo, *value; 133 : 29 : int pos = 0; 134 : : #if (defined(_POSIX_THREADS) && defined(HAVE_CONFSTR) \ 135 : : && defined(_CS_GNU_LIBPTHREAD_VERSION)) 136 : : char buffer[255]; 137 : : int len; 138 : : #endif 139 : : 140 [ + - ]: 29 : if (ThreadInfoType.tp_name == 0) { 141 [ - + ]: 29 : if (_PyStructSequence_InitBuiltin(&ThreadInfoType, 142 : : &threadinfo_desc) < 0) 143 : 0 : return NULL; 144 : : } 145 : : 146 : 29 : threadinfo = PyStructSequence_New(&ThreadInfoType); 147 [ - + ]: 29 : if (threadinfo == NULL) 148 : 0 : return NULL; 149 : : 150 : 29 : value = PyUnicode_FromString(PYTHREAD_NAME); 151 [ - + ]: 29 : if (value == NULL) { 152 : 0 : Py_DECREF(threadinfo); 153 : 0 : return NULL; 154 : : } 155 : 29 : PyStructSequence_SET_ITEM(threadinfo, pos++, value); 156 : : 157 : : #ifdef HAVE_PTHREAD_STUBS 158 : : value = Py_NewRef(Py_None); 159 : : #elif defined(_POSIX_THREADS) 160 : : #ifdef USE_SEMAPHORES 161 : 29 : value = PyUnicode_FromString("semaphore"); 162 : : #else 163 : : value = PyUnicode_FromString("mutex+cond"); 164 : : #endif 165 [ - + ]: 29 : if (value == NULL) { 166 : 0 : Py_DECREF(threadinfo); 167 : 0 : return NULL; 168 : : } 169 : : #else 170 : : value = Py_NewRef(Py_None); 171 : : #endif 172 : 29 : PyStructSequence_SET_ITEM(threadinfo, pos++, value); 173 : : 174 : : #if (defined(_POSIX_THREADS) && defined(HAVE_CONFSTR) \ 175 : : && defined(_CS_GNU_LIBPTHREAD_VERSION)) 176 : 29 : value = NULL; 177 : 29 : len = confstr(_CS_GNU_LIBPTHREAD_VERSION, buffer, sizeof(buffer)); 178 [ + - + - ]: 29 : if (1 < len && (size_t)len < sizeof(buffer)) { 179 : 29 : value = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1); 180 [ - + ]: 29 : if (value == NULL) 181 : 0 : PyErr_Clear(); 182 : : } 183 [ - + ]: 29 : if (value == NULL) 184 : : #endif 185 : : { 186 : 0 : value = Py_NewRef(Py_None); 187 : : } 188 : 29 : PyStructSequence_SET_ITEM(threadinfo, pos++, value); 189 : 29 : return threadinfo; 190 : : } 191 : : 192 : : 193 : : void 194 : 25 : _PyThread_FiniType(PyInterpreterState *interp) 195 : : { 196 [ - + ]: 25 : if (!_Py_IsMainInterpreter(interp)) { 197 : 0 : return; 198 : : } 199 : : 200 : 25 : _PyStructSequence_FiniType(&ThreadInfoType); 201 : : }