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 9043 : PyThread_init_thread(void) 51 : { 52 9043 : if (initialized) 53 6093 : return; 54 2950 : initialized = 1; 55 2950 : 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 3026140000 : PyThread_tss_is_created(Py_tss_t *key) 119 : { 120 3026140000 : assert(key != NULL); 121 3026140000 : 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 3134 : PyThread_GetInfo(void) 148 : { 149 : PyObject *threadinfo, *value; 150 3134 : 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 3134 : if (ThreadInfoType.tp_name == 0) { 158 2963 : if (PyStructSequence_InitType2(&ThreadInfoType, &threadinfo_desc) < 0) 159 0 : return NULL; 160 : } 161 : 162 3134 : threadinfo = PyStructSequence_New(&ThreadInfoType); 163 3134 : if (threadinfo == NULL) 164 0 : return NULL; 165 : 166 3134 : value = PyUnicode_FromString(PYTHREAD_NAME); 167 3134 : if (value == NULL) { 168 0 : Py_DECREF(threadinfo); 169 0 : return NULL; 170 : } 171 3134 : PyStructSequence_SET_ITEM(threadinfo, pos++, value); 172 : 173 : #ifdef _POSIX_THREADS 174 : #ifdef USE_SEMAPHORES 175 3134 : value = PyUnicode_FromString("semaphore"); 176 : #else 177 : value = PyUnicode_FromString("mutex+cond"); 178 : #endif 179 3134 : 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 3134 : PyStructSequence_SET_ITEM(threadinfo, pos++, value); 188 : 189 : #if (defined(_POSIX_THREADS) && defined(HAVE_CONFSTR) \ 190 : && defined(_CS_GNU_LIBPTHREAD_VERSION)) 191 3134 : value = NULL; 192 3134 : len = confstr(_CS_GNU_LIBPTHREAD_VERSION, buffer, sizeof(buffer)); 193 3134 : if (1 < len && (size_t)len < sizeof(buffer)) { 194 3134 : value = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1); 195 3134 : if (value == NULL) 196 0 : PyErr_Clear(); 197 : } 198 3134 : if (value == NULL) 199 : #endif 200 : { 201 0 : Py_INCREF(Py_None); 202 0 : value = Py_None; 203 : } 204 3134 : PyStructSequence_SET_ITEM(threadinfo, pos++, value); 205 3134 : return threadinfo; 206 : } 207 : 208 : 209 : void 210 3120 : _PyThread_FiniType(PyInterpreterState *interp) 211 : { 212 3120 : if (!_Py_IsMainInterpreter(interp)) { 213 169 : return; 214 : } 215 : 216 2951 : _PyStructSequence_FiniType(&ThreadInfoType); 217 : }