(root)/
Python-3.12.0/
Python/
thread.c
       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_FiniBuiltin()
      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  PyThread_init_thread(void)
      26  {
      27      if (initialized) {
      28          return;
      29      }
      30      initialized = 1;
      31      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  PyThread_get_stacksize(void)
      55  {
      56      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  PyThread_set_stacksize(size_t size)
      66  {
      67  #if defined(THREAD_SET_STACKSIZE)
      68      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  PyThread_tss_alloc(void)
      82  {
      83      Py_tss_t *new_key = (Py_tss_t *)PyMem_RawMalloc(sizeof(Py_tss_t));
      84      if (new_key == NULL) {
      85          return NULL;
      86      }
      87      new_key->_is_initialized = 0;
      88      return new_key;
      89  }
      90  
      91  void
      92  PyThread_tss_free(Py_tss_t *key)
      93  {
      94      if (key != NULL) {
      95          PyThread_tss_delete(key);
      96          PyMem_RawFree((void *)key);
      97      }
      98  }
      99  
     100  int
     101  PyThread_tss_is_created(Py_tss_t *key)
     102  {
     103      assert(key != NULL);
     104      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  PyThread_GetInfo(void)
     131  {
     132      PyObject *threadinfo, *value;
     133      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      PyInterpreterState *interp = _PyInterpreterState_GET();
     141      if (_PyStructSequence_InitBuiltin(interp, &ThreadInfoType, &threadinfo_desc) < 0) {
     142          return NULL;
     143      }
     144  
     145      threadinfo = PyStructSequence_New(&ThreadInfoType);
     146      if (threadinfo == NULL)
     147          return NULL;
     148  
     149      value = PyUnicode_FromString(PYTHREAD_NAME);
     150      if (value == NULL) {
     151          Py_DECREF(threadinfo);
     152          return NULL;
     153      }
     154      PyStructSequence_SET_ITEM(threadinfo, pos++, value);
     155  
     156  #ifdef HAVE_PTHREAD_STUBS
     157      value = Py_NewRef(Py_None);
     158  #elif defined(_POSIX_THREADS)
     159  #ifdef USE_SEMAPHORES
     160      value = PyUnicode_FromString("semaphore");
     161  #else
     162      value = PyUnicode_FromString("mutex+cond");
     163  #endif
     164      if (value == NULL) {
     165          Py_DECREF(threadinfo);
     166          return NULL;
     167      }
     168  #else
     169      value = Py_NewRef(Py_None);
     170  #endif
     171      PyStructSequence_SET_ITEM(threadinfo, pos++, value);
     172  
     173  #if (defined(_POSIX_THREADS) && defined(HAVE_CONFSTR) \
     174       && defined(_CS_GNU_LIBPTHREAD_VERSION))
     175      value = NULL;
     176      len = confstr(_CS_GNU_LIBPTHREAD_VERSION, buffer, sizeof(buffer));
     177      if (1 < len && (size_t)len < sizeof(buffer)) {
     178          value = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1);
     179          if (value == NULL)
     180              PyErr_Clear();
     181      }
     182      if (value == NULL)
     183  #endif
     184      {
     185          value = Py_NewRef(Py_None);
     186      }
     187      PyStructSequence_SET_ITEM(threadinfo, pos++, value);
     188      return threadinfo;
     189  }
     190  
     191  
     192  void
     193  _PyThread_FiniType(PyInterpreterState *interp)
     194  {
     195      _PyStructSequence_FiniBuiltin(interp, &ThreadInfoType);
     196  }