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 "internal/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 { 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 if (initialized) 74 return; 75 initialized = 1; 76 dprintf(("PyThread_init_thread called\n")); 77 PyThread__init_thread(); 78 } 79 80 #if defined(_POSIX_THREADS) 81 # 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 { 95 return PyThreadState_GET()->interp->pythread_stacksize; 96 } 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 { 106 #if defined(THREAD_SET_STACKSIZE) 107 return THREAD_SET_STACKSIZE(size); 108 #else 109 return -2; 110 #endif 111 } 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 { 122 Py_tss_t *new_key = (Py_tss_t *)PyMem_RawMalloc(sizeof(Py_tss_t)); 123 if (new_key == NULL) { 124 return NULL; 125 } 126 new_key->_is_initialized = 0; 127 return new_key; 128 } 129 130 void 131 PyThread_tss_free(Py_tss_t *key) 132 { 133 if (key != NULL) { 134 PyThread_tss_delete(key); 135 PyMem_RawFree((void *)key); 136 } 137 } 138 139 int 140 PyThread_tss_is_created(Py_tss_t *key) 141 { 142 assert(key != NULL); 143 return key->_is_initialized; 144 } 145 146 147 PyDoc_STRVAR(threadinfo__doc__, 148 "sys.thread_info\n\ 149 \n\ 150 A struct sequence 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 { 171 PyObject *threadinfo, *value; 172 int pos = 0; 173 #if (defined(_POSIX_THREADS) && defined(HAVE_CONFSTR) \ 174 && defined(_CS_GNU_LIBPTHREAD_VERSION)) 175 char buffer[255]; 176 int len; 177 #endif 178 179 if (ThreadInfoType.tp_name == 0) { 180 if (PyStructSequence_InitType2(&ThreadInfoType, &threadinfo_desc) < 0) 181 return NULL; 182 } 183 184 threadinfo = PyStructSequence_New(&ThreadInfoType); 185 if (threadinfo == NULL) 186 return NULL; 187 188 value = PyUnicode_FromString(PYTHREAD_NAME); 189 if (value == NULL) { 190 Py_DECREF(threadinfo); 191 return NULL; 192 } 193 PyStructSequence_SET_ITEM(threadinfo, pos++, value); 194 195 #ifdef _POSIX_THREADS 196 #ifdef USE_SEMAPHORES 197 value = PyUnicode_FromString("semaphore"); 198 #else 199 value = PyUnicode_FromString("mutex+cond"); 200 #endif 201 if (value == NULL) { 202 Py_DECREF(threadinfo); 203 return NULL; 204 } 205 #else 206 Py_INCREF(Py_None); 207 value = Py_None; 208 #endif 209 PyStructSequence_SET_ITEM(threadinfo, pos++, value); 210 211 #if (defined(_POSIX_THREADS) && defined(HAVE_CONFSTR) \ 212 && defined(_CS_GNU_LIBPTHREAD_VERSION)) 213 value = NULL; 214 len = confstr(_CS_GNU_LIBPTHREAD_VERSION, buffer, sizeof(buffer)); 215 if (1 < len && (size_t)len < sizeof(buffer)) { 216 value = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1); 217 if (value == NULL) 218 PyErr_Clear(); 219 } 220 if (value == NULL) 221 #endif 222 { 223 Py_INCREF(Py_None); 224 value = Py_None; 225 } 226 PyStructSequence_SET_ITEM(threadinfo, pos++, value); 227 return threadinfo; 228 } 229