thread.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. /* Thread package.
  2. This is intended to be usable independently from Python.
  3. The implementation for system foobar is in a file thread_foobar.h
  4. which is included by this file dependent on config settings.
  5. Stuff shared by all thread_*.h files is collected here. */
  6. #include "Python.h"
  7. #include "pycore_pystate.h" // _PyInterpreterState_GET()
  8. #include "pycore_structseq.h" // _PyStructSequence_FiniBuiltin()
  9. #include "pycore_pythread.h"
  10. #ifndef DONT_HAVE_STDIO_H
  11. #include <stdio.h>
  12. #endif
  13. #include <stdlib.h>
  14. static void PyThread__init_thread(void); /* Forward */
  15. #define initialized _PyRuntime.threads.initialized
  16. void
  17. PyThread_init_thread(void)
  18. {
  19. if (initialized) {
  20. return;
  21. }
  22. initialized = 1;
  23. PyThread__init_thread();
  24. }
  25. #if defined(HAVE_PTHREAD_STUBS)
  26. # define PYTHREAD_NAME "pthread-stubs"
  27. # include "thread_pthread_stubs.h"
  28. #elif defined(_USE_PTHREADS) /* AKA _PTHREADS */
  29. # if defined(__EMSCRIPTEN__) && !defined(__EMSCRIPTEN_PTHREADS__)
  30. # define PYTHREAD_NAME "pthread-stubs"
  31. # else
  32. # define PYTHREAD_NAME "pthread"
  33. # endif
  34. # include "thread_pthread.h"
  35. #elif defined(NT_THREADS)
  36. # define PYTHREAD_NAME "nt"
  37. # include "thread_nt.h"
  38. #else
  39. # error "Require native threads. See https://bugs.python.org/issue31370"
  40. #endif
  41. /* return the current thread stack size */
  42. size_t
  43. PyThread_get_stacksize(void)
  44. {
  45. return _PyInterpreterState_GET()->threads.stacksize;
  46. }
  47. /* Only platforms defining a THREAD_SET_STACKSIZE() macro
  48. in thread_<platform>.h support changing the stack size.
  49. Return 0 if stack size is valid,
  50. -1 if stack size value is invalid,
  51. -2 if setting stack size is not supported. */
  52. int
  53. PyThread_set_stacksize(size_t size)
  54. {
  55. #if defined(THREAD_SET_STACKSIZE)
  56. return THREAD_SET_STACKSIZE(size);
  57. #else
  58. return -2;
  59. #endif
  60. }
  61. /* Thread Specific Storage (TSS) API
  62. Cross-platform components of TSS API implementation.
  63. */
  64. Py_tss_t *
  65. PyThread_tss_alloc(void)
  66. {
  67. Py_tss_t *new_key = (Py_tss_t *)PyMem_RawMalloc(sizeof(Py_tss_t));
  68. if (new_key == NULL) {
  69. return NULL;
  70. }
  71. new_key->_is_initialized = 0;
  72. return new_key;
  73. }
  74. void
  75. PyThread_tss_free(Py_tss_t *key)
  76. {
  77. if (key != NULL) {
  78. PyThread_tss_delete(key);
  79. PyMem_RawFree((void *)key);
  80. }
  81. }
  82. int
  83. PyThread_tss_is_created(Py_tss_t *key)
  84. {
  85. assert(key != NULL);
  86. return key->_is_initialized;
  87. }
  88. PyDoc_STRVAR(threadinfo__doc__,
  89. "sys.thread_info\n\
  90. \n\
  91. A named tuple holding information about the thread implementation.");
  92. static PyStructSequence_Field threadinfo_fields[] = {
  93. {"name", "name of the thread implementation"},
  94. {"lock", "name of the lock implementation"},
  95. {"version", "name and version of the thread library"},
  96. {0}
  97. };
  98. static PyStructSequence_Desc threadinfo_desc = {
  99. "sys.thread_info", /* name */
  100. threadinfo__doc__, /* doc */
  101. threadinfo_fields, /* fields */
  102. 3
  103. };
  104. static PyTypeObject ThreadInfoType;
  105. PyObject*
  106. PyThread_GetInfo(void)
  107. {
  108. PyObject *threadinfo, *value;
  109. int pos = 0;
  110. #if (defined(_POSIX_THREADS) && defined(HAVE_CONFSTR) \
  111. && defined(_CS_GNU_LIBPTHREAD_VERSION))
  112. char buffer[255];
  113. int len;
  114. #endif
  115. PyInterpreterState *interp = _PyInterpreterState_GET();
  116. if (_PyStructSequence_InitBuiltin(interp, &ThreadInfoType, &threadinfo_desc) < 0) {
  117. return NULL;
  118. }
  119. threadinfo = PyStructSequence_New(&ThreadInfoType);
  120. if (threadinfo == NULL)
  121. return NULL;
  122. value = PyUnicode_FromString(PYTHREAD_NAME);
  123. if (value == NULL) {
  124. Py_DECREF(threadinfo);
  125. return NULL;
  126. }
  127. PyStructSequence_SET_ITEM(threadinfo, pos++, value);
  128. #ifdef HAVE_PTHREAD_STUBS
  129. value = Py_NewRef(Py_None);
  130. #elif defined(_POSIX_THREADS)
  131. #ifdef USE_SEMAPHORES
  132. value = PyUnicode_FromString("semaphore");
  133. #else
  134. value = PyUnicode_FromString("mutex+cond");
  135. #endif
  136. if (value == NULL) {
  137. Py_DECREF(threadinfo);
  138. return NULL;
  139. }
  140. #else
  141. value = Py_NewRef(Py_None);
  142. #endif
  143. PyStructSequence_SET_ITEM(threadinfo, pos++, value);
  144. #if (defined(_POSIX_THREADS) && defined(HAVE_CONFSTR) \
  145. && defined(_CS_GNU_LIBPTHREAD_VERSION))
  146. value = NULL;
  147. len = confstr(_CS_GNU_LIBPTHREAD_VERSION, buffer, sizeof(buffer));
  148. if (1 < len && (size_t)len < sizeof(buffer)) {
  149. value = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1);
  150. if (value == NULL)
  151. PyErr_Clear();
  152. }
  153. if (value == NULL)
  154. #endif
  155. {
  156. value = Py_NewRef(Py_None);
  157. }
  158. PyStructSequence_SET_ITEM(threadinfo, pos++, value);
  159. return threadinfo;
  160. }
  161. void
  162. _PyThread_FiniType(PyInterpreterState *interp)
  163. {
  164. _PyStructSequence_FiniBuiltin(interp, &ThreadInfoType);
  165. }