(root)/
Python-3.12.0/
Python/
thread_pthread.h
       1  #include "pycore_interp.h"    // _PyInterpreterState.threads.stacksize
       2  
       3  /* Posix threads interface */
       4  
       5  #include <stdlib.h>
       6  #include <string.h>
       7  #if defined(__APPLE__) || defined(HAVE_PTHREAD_DESTRUCTOR)
       8  #define destructor xxdestructor
       9  #endif
      10  #ifndef HAVE_PTHREAD_STUBS
      11  #  include <pthread.h>
      12  #endif
      13  #if defined(__APPLE__) || defined(HAVE_PTHREAD_DESTRUCTOR)
      14  #undef destructor
      15  #endif
      16  #include <signal.h>
      17  
      18  #if defined(__linux__)
      19  #   include <sys/syscall.h>     /* syscall(SYS_gettid) */
      20  #elif defined(__FreeBSD__)
      21  #   include <pthread_np.h>      /* pthread_getthreadid_np() */
      22  #elif defined(__OpenBSD__)
      23  #   include <unistd.h>          /* getthrid() */
      24  #elif defined(_AIX)
      25  #   include <sys/thread.h>      /* thread_self() */
      26  #elif defined(__NetBSD__)
      27  #   include <lwp.h>             /* _lwp_self() */
      28  #elif defined(__DragonFly__)
      29  #   include <sys/lwp.h>         /* lwp_gettid() */
      30  #endif
      31  
      32  /* The POSIX spec requires that use of pthread_attr_setstacksize
      33     be conditional on _POSIX_THREAD_ATTR_STACKSIZE being defined. */
      34  #ifdef _POSIX_THREAD_ATTR_STACKSIZE
      35  #ifndef THREAD_STACK_SIZE
      36  #define THREAD_STACK_SIZE       0       /* use default stack size */
      37  #endif
      38  
      39  /* The default stack size for new threads on BSD is small enough that
      40   * we'll get hard crashes instead of 'maximum recursion depth exceeded'
      41   * exceptions.
      42   *
      43   * The default stack size below is the empirically determined minimal stack
      44   * sizes where a simple recursive function doesn't cause a hard crash.
      45   *
      46   * For macOS the value of THREAD_STACK_SIZE is determined in configure.ac
      47   * as it also depends on the other configure options like chosen sanitizer
      48   * runtimes.
      49   */
      50  #if defined(__FreeBSD__) && defined(THREAD_STACK_SIZE) && THREAD_STACK_SIZE == 0
      51  #undef  THREAD_STACK_SIZE
      52  #define THREAD_STACK_SIZE       0x400000
      53  #endif
      54  #if defined(_AIX) && defined(THREAD_STACK_SIZE) && THREAD_STACK_SIZE == 0
      55  #undef  THREAD_STACK_SIZE
      56  #define THREAD_STACK_SIZE       0x200000
      57  #endif
      58  /* bpo-38852: test_threading.test_recursion_limit() checks that 1000 recursive
      59     Python calls (default recursion limit) doesn't crash, but raise a regular
      60     RecursionError exception. In debug mode, Python function calls allocates
      61     more memory on the stack, so use a stack of 8 MiB. */
      62  #if defined(__ANDROID__) && defined(THREAD_STACK_SIZE) && THREAD_STACK_SIZE == 0
      63  #   ifdef Py_DEBUG
      64  #   undef  THREAD_STACK_SIZE
      65  #   define THREAD_STACK_SIZE    0x800000
      66  #   endif
      67  #endif
      68  #if defined(__VXWORKS__) && defined(THREAD_STACK_SIZE) && THREAD_STACK_SIZE == 0
      69  #undef  THREAD_STACK_SIZE
      70  #define THREAD_STACK_SIZE       0x100000
      71  #endif
      72  /* for safety, ensure a viable minimum stacksize */
      73  #define THREAD_STACK_MIN        0x8000  /* 32 KiB */
      74  #else  /* !_POSIX_THREAD_ATTR_STACKSIZE */
      75  #ifdef THREAD_STACK_SIZE
      76  #error "THREAD_STACK_SIZE defined but _POSIX_THREAD_ATTR_STACKSIZE undefined"
      77  #endif
      78  #endif
      79  
      80  /* The POSIX spec says that implementations supporting the sem_*
      81     family of functions must indicate this by defining
      82     _POSIX_SEMAPHORES. */
      83  #ifdef _POSIX_SEMAPHORES
      84  /* On FreeBSD 4.x, _POSIX_SEMAPHORES is defined empty, so
      85     we need to add 0 to make it work there as well. */
      86  #if (_POSIX_SEMAPHORES+0) == -1
      87  #define HAVE_BROKEN_POSIX_SEMAPHORES
      88  #else
      89  #include <semaphore.h>
      90  #include <errno.h>
      91  #endif
      92  #endif
      93  
      94  
      95  /* Whether or not to use semaphores directly rather than emulating them with
      96   * mutexes and condition variables:
      97   */
      98  #if (defined(_POSIX_SEMAPHORES) && !defined(HAVE_BROKEN_POSIX_SEMAPHORES) && \
      99       (defined(HAVE_SEM_TIMEDWAIT) || defined(HAVE_SEM_CLOCKWAIT)))
     100  #  define USE_SEMAPHORES
     101  #else
     102  #  undef USE_SEMAPHORES
     103  #endif
     104  
     105  
     106  /* On platforms that don't use standard POSIX threads pthread_sigmask()
     107   * isn't present.  DEC threads uses sigprocmask() instead as do most
     108   * other UNIX International compliant systems that don't have the full
     109   * pthread implementation.
     110   */
     111  #if defined(HAVE_PTHREAD_SIGMASK) && !defined(HAVE_BROKEN_PTHREAD_SIGMASK)
     112  #  define SET_THREAD_SIGMASK pthread_sigmask
     113  #else
     114  #  define SET_THREAD_SIGMASK sigprocmask
     115  #endif
     116  
     117  
     118  /*
     119   * pthread_cond support
     120   */
     121  
     122  #define condattr_monotonic _PyRuntime.threads._condattr_monotonic.ptr
     123  
     124  static void
     125  init_condattr(void)
     126  {
     127  #ifdef CONDATTR_MONOTONIC
     128  # define ca _PyRuntime.threads._condattr_monotonic.val
     129      // XXX We need to check the return code?
     130      pthread_condattr_init(&ca);
     131      // XXX We need to run pthread_condattr_destroy() during runtime fini.
     132      if (pthread_condattr_setclock(&ca, CLOCK_MONOTONIC) == 0) {
     133          condattr_monotonic = &ca;  // Use monotonic clock
     134      }
     135  # undef ca
     136  #endif  // CONDATTR_MONOTONIC
     137  }
     138  
     139  int
     140  _PyThread_cond_init(PyCOND_T *cond)
     141  {
     142      return pthread_cond_init(cond, condattr_monotonic);
     143  }
     144  
     145  
     146  void
     147  _PyThread_cond_after(long long us, struct timespec *abs)
     148  {
     149      _PyTime_t timeout = _PyTime_FromMicrosecondsClamp(us);
     150      _PyTime_t t;
     151  #ifdef CONDATTR_MONOTONIC
     152      if (condattr_monotonic) {
     153          t = _PyTime_GetMonotonicClock();
     154      }
     155      else
     156  #endif
     157      {
     158          t = _PyTime_GetSystemClock();
     159      }
     160      t = _PyTime_Add(t, timeout);
     161      _PyTime_AsTimespec_clamp(t, abs);
     162  }
     163  
     164  
     165  /* A pthread mutex isn't sufficient to model the Python lock type
     166   * because, according to Draft 5 of the docs (P1003.4a/D5), both of the
     167   * following are undefined:
     168   *  -> a thread tries to lock a mutex it already has locked
     169   *  -> a thread tries to unlock a mutex locked by a different thread
     170   * pthread mutexes are designed for serializing threads over short pieces
     171   * of code anyway, so wouldn't be an appropriate implementation of
     172   * Python's locks regardless.
     173   *
     174   * The pthread_lock struct implements a Python lock as a "locked?" bit
     175   * and a <condition, mutex> pair.  In general, if the bit can be acquired
     176   * instantly, it is, else the pair is used to block the thread until the
     177   * bit is cleared.     9 May 1994 tim@ksr.com
     178   */
     179  
     180  typedef struct {
     181      char             locked; /* 0=unlocked, 1=locked */
     182      /* a <cond, mutex> pair to handle an acquire of a locked lock */
     183      pthread_cond_t   lock_released;
     184      pthread_mutex_t  mut;
     185  } pthread_lock;
     186  
     187  #define CHECK_STATUS(name)  if (status != 0) { perror(name); error = 1; }
     188  #define CHECK_STATUS_PTHREAD(name)  if (status != 0) { fprintf(stderr, \
     189      "%s: %s\n", name, strerror(status)); error = 1; }
     190  
     191  /*
     192   * Initialization for the current runtime.
     193   */
     194  static void
     195  PyThread__init_thread(void)
     196  {
     197      // The library is only initialized once in the process,
     198      // regardless of how many times the Python runtime is initialized.
     199      static int lib_initialized = 0;
     200      if (!lib_initialized) {
     201          lib_initialized = 1;
     202  #if defined(_AIX) && defined(__GNUC__)
     203          extern void pthread_init(void);
     204          pthread_init();
     205  #endif
     206      }
     207      init_condattr();
     208  }
     209  
     210  /*
     211   * Thread support.
     212   */
     213  
     214  /* bpo-33015: pythread_callback struct and pythread_wrapper() cast
     215     "void func(void *)" to "void* func(void *)": always return NULL.
     216  
     217     PyThread_start_new_thread() uses "void func(void *)" type, whereas
     218     pthread_create() requires a void* return value. */
     219  typedef struct {
     220      void (*func) (void *);
     221      void *arg;
     222  } pythread_callback;
     223  
     224  static void *
     225  pythread_wrapper(void *arg)
     226  {
     227      /* copy func and func_arg and free the temporary structure */
     228      pythread_callback *callback = arg;
     229      void (*func)(void *) = callback->func;
     230      void *func_arg = callback->arg;
     231      PyMem_RawFree(arg);
     232  
     233      func(func_arg);
     234      return NULL;
     235  }
     236  
     237  unsigned long
     238  PyThread_start_new_thread(void (*func)(void *), void *arg)
     239  {
     240      pthread_t th;
     241      int status;
     242  #if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED)
     243      pthread_attr_t attrs;
     244  #endif
     245  #if defined(THREAD_STACK_SIZE)
     246      size_t      tss;
     247  #endif
     248  
     249      if (!initialized)
     250          PyThread_init_thread();
     251  
     252  #if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED)
     253      if (pthread_attr_init(&attrs) != 0)
     254          return PYTHREAD_INVALID_THREAD_ID;
     255  #endif
     256  #if defined(THREAD_STACK_SIZE)
     257      PyThreadState *tstate = _PyThreadState_GET();
     258      size_t stacksize = tstate ? tstate->interp->threads.stacksize : 0;
     259      tss = (stacksize != 0) ? stacksize : THREAD_STACK_SIZE;
     260      if (tss != 0) {
     261          if (pthread_attr_setstacksize(&attrs, tss) != 0) {
     262              pthread_attr_destroy(&attrs);
     263              return PYTHREAD_INVALID_THREAD_ID;
     264          }
     265      }
     266  #endif
     267  #if defined(PTHREAD_SYSTEM_SCHED_SUPPORTED)
     268      pthread_attr_setscope(&attrs, PTHREAD_SCOPE_SYSTEM);
     269  #endif
     270  
     271      pythread_callback *callback = PyMem_RawMalloc(sizeof(pythread_callback));
     272  
     273      if (callback == NULL) {
     274        return PYTHREAD_INVALID_THREAD_ID;
     275      }
     276  
     277      callback->func = func;
     278      callback->arg = arg;
     279  
     280      status = pthread_create(&th,
     281  #if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED)
     282                               &attrs,
     283  #else
     284                               (pthread_attr_t*)NULL,
     285  #endif
     286                               pythread_wrapper, callback);
     287  
     288  #if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED)
     289      pthread_attr_destroy(&attrs);
     290  #endif
     291  
     292      if (status != 0) {
     293          PyMem_RawFree(callback);
     294          return PYTHREAD_INVALID_THREAD_ID;
     295      }
     296  
     297      pthread_detach(th);
     298  
     299  #if SIZEOF_PTHREAD_T <= SIZEOF_LONG
     300      return (unsigned long) th;
     301  #else
     302      return (unsigned long) *(unsigned long *) &th;
     303  #endif
     304  }
     305  
     306  /* XXX This implementation is considered (to quote Tim Peters) "inherently
     307     hosed" because:
     308       - It does not guarantee the promise that a non-zero integer is returned.
     309       - The cast to unsigned long is inherently unsafe.
     310       - It is not clear that the 'volatile' (for AIX?) are any longer necessary.
     311  */
     312  unsigned long
     313  PyThread_get_thread_ident(void)
     314  {
     315      volatile pthread_t threadid;
     316      if (!initialized)
     317          PyThread_init_thread();
     318      threadid = pthread_self();
     319      return (unsigned long) threadid;
     320  }
     321  
     322  #ifdef PY_HAVE_THREAD_NATIVE_ID
     323  unsigned long
     324  PyThread_get_thread_native_id(void)
     325  {
     326      if (!initialized)
     327          PyThread_init_thread();
     328  #ifdef __APPLE__
     329      uint64_t native_id;
     330      (void) pthread_threadid_np(NULL, &native_id);
     331  #elif defined(__linux__)
     332      pid_t native_id;
     333      native_id = syscall(SYS_gettid);
     334  #elif defined(__FreeBSD__)
     335      int native_id;
     336      native_id = pthread_getthreadid_np();
     337  #elif defined(__OpenBSD__)
     338      pid_t native_id;
     339      native_id = getthrid();
     340  #elif defined(_AIX)
     341      tid_t native_id;
     342      native_id = thread_self();
     343  #elif defined(__NetBSD__)
     344      lwpid_t native_id;
     345      native_id = _lwp_self();
     346  #elif defined(__DragonFly__)
     347      lwpid_t native_id;
     348      native_id = lwp_gettid();
     349  #endif
     350      return (unsigned long) native_id;
     351  }
     352  #endif
     353  
     354  void _Py_NO_RETURN
     355  PyThread_exit_thread(void)
     356  {
     357      if (!initialized)
     358          exit(0);
     359  #if defined(__wasi__)
     360      /*
     361       * wasi-threads doesn't have pthread_exit right now
     362       * cf. https://github.com/WebAssembly/wasi-threads/issues/7
     363       */
     364      abort();
     365  #else
     366      pthread_exit(0);
     367  #endif
     368  }
     369  
     370  #ifdef USE_SEMAPHORES
     371  
     372  /*
     373   * Lock support.
     374   */
     375  
     376  PyThread_type_lock
     377  PyThread_allocate_lock(void)
     378  {
     379      sem_t *lock;
     380      int status, error = 0;
     381  
     382      if (!initialized)
     383          PyThread_init_thread();
     384  
     385      lock = (sem_t *)PyMem_RawMalloc(sizeof(sem_t));
     386  
     387      if (lock) {
     388          status = sem_init(lock,0,1);
     389          CHECK_STATUS("sem_init");
     390  
     391          if (error) {
     392              PyMem_RawFree((void *)lock);
     393              lock = NULL;
     394          }
     395      }
     396  
     397      return (PyThread_type_lock)lock;
     398  }
     399  
     400  void
     401  PyThread_free_lock(PyThread_type_lock lock)
     402  {
     403      sem_t *thelock = (sem_t *)lock;
     404      int status, error = 0;
     405  
     406      (void) error; /* silence unused-but-set-variable warning */
     407  
     408      if (!thelock)
     409          return;
     410  
     411      status = sem_destroy(thelock);
     412      CHECK_STATUS("sem_destroy");
     413  
     414      PyMem_RawFree((void *)thelock);
     415  }
     416  
     417  /*
     418   * As of February 2002, Cygwin thread implementations mistakenly report error
     419   * codes in the return value of the sem_ calls (like the pthread_ functions).
     420   * Correct implementations return -1 and put the code in errno. This supports
     421   * either.
     422   */
     423  static int
     424  fix_status(int status)
     425  {
     426      return (status == -1) ? errno : status;
     427  }
     428  
     429  PyLockStatus
     430  PyThread_acquire_lock_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds,
     431                              int intr_flag)
     432  {
     433      PyLockStatus success;
     434      sem_t *thelock = (sem_t *)lock;
     435      int status, error = 0;
     436  
     437      (void) error; /* silence unused-but-set-variable warning */
     438  
     439      _PyTime_t timeout;  // relative timeout
     440      if (microseconds >= 0) {
     441          // bpo-41710: PyThread_acquire_lock_timed() cannot report timeout
     442          // overflow to the caller, so clamp the timeout to
     443          // [_PyTime_MIN, _PyTime_MAX].
     444          //
     445          // _PyTime_MAX nanoseconds is around 292.3 years.
     446          //
     447          // _thread.Lock.acquire() and _thread.RLock.acquire() raise an
     448          // OverflowError if microseconds is greater than PY_TIMEOUT_MAX.
     449          timeout = _PyTime_FromMicrosecondsClamp(microseconds);
     450      }
     451      else {
     452          timeout = _PyTime_FromNanoseconds(-1);
     453      }
     454  
     455  #ifdef HAVE_SEM_CLOCKWAIT
     456      struct timespec abs_timeout;
     457      // Local scope for deadline
     458      {
     459          _PyTime_t deadline = _PyTime_Add(_PyTime_GetMonotonicClock(), timeout);
     460          _PyTime_AsTimespec_clamp(deadline, &abs_timeout);
     461      }
     462  #else
     463      _PyTime_t deadline = 0;
     464      if (timeout > 0 && !intr_flag) {
     465          deadline = _PyDeadline_Init(timeout);
     466      }
     467  #endif
     468  
     469      while (1) {
     470          if (timeout > 0) {
     471  #ifdef HAVE_SEM_CLOCKWAIT
     472              status = fix_status(sem_clockwait(thelock, CLOCK_MONOTONIC,
     473                                                &abs_timeout));
     474  #else
     475              _PyTime_t abs_time = _PyTime_Add(_PyTime_GetSystemClock(),
     476                                               timeout);
     477              struct timespec ts;
     478              _PyTime_AsTimespec_clamp(abs_time, &ts);
     479              status = fix_status(sem_timedwait(thelock, &ts));
     480  #endif
     481          }
     482          else if (timeout == 0) {
     483              status = fix_status(sem_trywait(thelock));
     484          }
     485          else {
     486              status = fix_status(sem_wait(thelock));
     487          }
     488  
     489          /* Retry if interrupted by a signal, unless the caller wants to be
     490             notified.  */
     491          if (intr_flag || status != EINTR) {
     492              break;
     493          }
     494  
     495          // sem_clockwait() uses an absolute timeout, there is no need
     496          // to recompute the relative timeout.
     497  #ifndef HAVE_SEM_CLOCKWAIT
     498          if (timeout > 0) {
     499              /* wait interrupted by a signal (EINTR): recompute the timeout */
     500              timeout = _PyDeadline_Get(deadline);
     501              if (timeout < 0) {
     502                  status = ETIMEDOUT;
     503                  break;
     504              }
     505          }
     506  #endif
     507      }
     508  
     509      /* Don't check the status if we're stopping because of an interrupt.  */
     510      if (!(intr_flag && status == EINTR)) {
     511          if (timeout > 0) {
     512              if (status != ETIMEDOUT) {
     513  #ifdef HAVE_SEM_CLOCKWAIT
     514                  CHECK_STATUS("sem_clockwait");
     515  #else
     516                  CHECK_STATUS("sem_timedwait");
     517  #endif
     518              }
     519          }
     520          else if (timeout == 0) {
     521              if (status != EAGAIN) {
     522                  CHECK_STATUS("sem_trywait");
     523              }
     524          }
     525          else {
     526              CHECK_STATUS("sem_wait");
     527          }
     528      }
     529  
     530      if (status == 0) {
     531          success = PY_LOCK_ACQUIRED;
     532      } else if (intr_flag && status == EINTR) {
     533          success = PY_LOCK_INTR;
     534      } else {
     535          success = PY_LOCK_FAILURE;
     536      }
     537  
     538      return success;
     539  }
     540  
     541  void
     542  PyThread_release_lock(PyThread_type_lock lock)
     543  {
     544      sem_t *thelock = (sem_t *)lock;
     545      int status, error = 0;
     546  
     547      (void) error; /* silence unused-but-set-variable warning */
     548  
     549      status = sem_post(thelock);
     550      CHECK_STATUS("sem_post");
     551  }
     552  
     553  #else /* USE_SEMAPHORES */
     554  
     555  /*
     556   * Lock support.
     557   */
     558  PyThread_type_lock
     559  PyThread_allocate_lock(void)
     560  {
     561      pthread_lock *lock;
     562      int status, error = 0;
     563  
     564      if (!initialized)
     565          PyThread_init_thread();
     566  
     567      lock = (pthread_lock *) PyMem_RawCalloc(1, sizeof(pthread_lock));
     568      if (lock) {
     569          lock->locked = 0;
     570  
     571          status = pthread_mutex_init(&lock->mut, NULL);
     572          CHECK_STATUS_PTHREAD("pthread_mutex_init");
     573          /* Mark the pthread mutex underlying a Python mutex as
     574             pure happens-before.  We can't simply mark the
     575             Python-level mutex as a mutex because it can be
     576             acquired and released in different threads, which
     577             will cause errors. */
     578          _Py_ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX(&lock->mut);
     579  
     580          status = _PyThread_cond_init(&lock->lock_released);
     581          CHECK_STATUS_PTHREAD("pthread_cond_init");
     582  
     583          if (error) {
     584              PyMem_RawFree((void *)lock);
     585              lock = 0;
     586          }
     587      }
     588  
     589      return (PyThread_type_lock) lock;
     590  }
     591  
     592  void
     593  PyThread_free_lock(PyThread_type_lock lock)
     594  {
     595      pthread_lock *thelock = (pthread_lock *)lock;
     596      int status, error = 0;
     597  
     598      (void) error; /* silence unused-but-set-variable warning */
     599  
     600      /* some pthread-like implementations tie the mutex to the cond
     601       * and must have the cond destroyed first.
     602       */
     603      status = pthread_cond_destroy( &thelock->lock_released );
     604      CHECK_STATUS_PTHREAD("pthread_cond_destroy");
     605  
     606      status = pthread_mutex_destroy( &thelock->mut );
     607      CHECK_STATUS_PTHREAD("pthread_mutex_destroy");
     608  
     609      PyMem_RawFree((void *)thelock);
     610  }
     611  
     612  PyLockStatus
     613  PyThread_acquire_lock_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds,
     614                              int intr_flag)
     615  {
     616      PyLockStatus success = PY_LOCK_FAILURE;
     617      pthread_lock *thelock = (pthread_lock *)lock;
     618      int status, error = 0;
     619  
     620      if (microseconds == 0) {
     621          status = pthread_mutex_trylock( &thelock->mut );
     622          if (status != EBUSY) {
     623              CHECK_STATUS_PTHREAD("pthread_mutex_trylock[1]");
     624          }
     625      }
     626      else {
     627          status = pthread_mutex_lock( &thelock->mut );
     628          CHECK_STATUS_PTHREAD("pthread_mutex_lock[1]");
     629      }
     630      if (status != 0) {
     631          goto done;
     632      }
     633  
     634      if (thelock->locked == 0) {
     635          success = PY_LOCK_ACQUIRED;
     636          goto unlock;
     637      }
     638      if (microseconds == 0) {
     639          goto unlock;
     640      }
     641  
     642      struct timespec abs_timeout;
     643      if (microseconds > 0) {
     644          _PyThread_cond_after(microseconds, &abs_timeout);
     645      }
     646      // Continue trying until we get the lock
     647  
     648      // mut must be locked by me -- part of the condition protocol
     649      while (1) {
     650          if (microseconds > 0) {
     651              status = pthread_cond_timedwait(&thelock->lock_released,
     652                                              &thelock->mut, &abs_timeout);
     653              if (status == 1) {
     654                  break;
     655              }
     656              if (status == ETIMEDOUT) {
     657                  break;
     658              }
     659              CHECK_STATUS_PTHREAD("pthread_cond_timedwait");
     660          }
     661          else {
     662              status = pthread_cond_wait(
     663                  &thelock->lock_released,
     664                  &thelock->mut);
     665              CHECK_STATUS_PTHREAD("pthread_cond_wait");
     666          }
     667  
     668          if (intr_flag && status == 0 && thelock->locked) {
     669              // We were woken up, but didn't get the lock.  We probably received
     670              // a signal.  Return PY_LOCK_INTR to allow the caller to handle
     671              // it and retry.
     672              success = PY_LOCK_INTR;
     673              break;
     674          }
     675  
     676          if (status == 0 && !thelock->locked) {
     677              success = PY_LOCK_ACQUIRED;
     678              break;
     679          }
     680  
     681          // Wait got interrupted by a signal: retry
     682      }
     683  
     684  unlock:
     685      if (success == PY_LOCK_ACQUIRED) {
     686          thelock->locked = 1;
     687      }
     688      status = pthread_mutex_unlock( &thelock->mut );
     689      CHECK_STATUS_PTHREAD("pthread_mutex_unlock[1]");
     690  
     691  done:
     692      if (error) {
     693          success = PY_LOCK_FAILURE;
     694      }
     695      return success;
     696  }
     697  
     698  void
     699  PyThread_release_lock(PyThread_type_lock lock)
     700  {
     701      pthread_lock *thelock = (pthread_lock *)lock;
     702      int status, error = 0;
     703  
     704      (void) error; /* silence unused-but-set-variable warning */
     705  
     706      status = pthread_mutex_lock( &thelock->mut );
     707      CHECK_STATUS_PTHREAD("pthread_mutex_lock[3]");
     708  
     709      thelock->locked = 0;
     710  
     711      /* wake up someone (anyone, if any) waiting on the lock */
     712      status = pthread_cond_signal( &thelock->lock_released );
     713      CHECK_STATUS_PTHREAD("pthread_cond_signal");
     714  
     715      status = pthread_mutex_unlock( &thelock->mut );
     716      CHECK_STATUS_PTHREAD("pthread_mutex_unlock[3]");
     717  }
     718  
     719  #endif /* USE_SEMAPHORES */
     720  
     721  int
     722  _PyThread_at_fork_reinit(PyThread_type_lock *lock)
     723  {
     724      PyThread_type_lock new_lock = PyThread_allocate_lock();
     725      if (new_lock == NULL) {
     726          return -1;
     727      }
     728  
     729      /* bpo-6721, bpo-40089: The old lock can be in an inconsistent state.
     730         fork() can be called in the middle of an operation on the lock done by
     731         another thread. So don't call PyThread_free_lock(*lock).
     732  
     733         Leak memory on purpose. Don't release the memory either since the
     734         address of a mutex is relevant. Putting two mutexes at the same address
     735         can lead to problems. */
     736  
     737      *lock = new_lock;
     738      return 0;
     739  }
     740  
     741  int
     742  PyThread_acquire_lock(PyThread_type_lock lock, int waitflag)
     743  {
     744      return PyThread_acquire_lock_timed(lock, waitflag ? -1 : 0, /*intr_flag=*/0);
     745  }
     746  
     747  /* set the thread stack size.
     748   * Return 0 if size is valid, -1 if size is invalid,
     749   * -2 if setting stack size is not supported.
     750   */
     751  static int
     752  _pythread_pthread_set_stacksize(size_t size)
     753  {
     754  #if defined(THREAD_STACK_SIZE)
     755      pthread_attr_t attrs;
     756      size_t tss_min;
     757      int rc = 0;
     758  #endif
     759  
     760      /* set to default */
     761      if (size == 0) {
     762          _PyInterpreterState_GET()->threads.stacksize = 0;
     763          return 0;
     764      }
     765  
     766  #if defined(THREAD_STACK_SIZE)
     767  #if defined(PTHREAD_STACK_MIN)
     768      tss_min = PTHREAD_STACK_MIN > THREAD_STACK_MIN ? PTHREAD_STACK_MIN
     769                                                     : THREAD_STACK_MIN;
     770  #else
     771      tss_min = THREAD_STACK_MIN;
     772  #endif
     773      if (size >= tss_min) {
     774          /* validate stack size by setting thread attribute */
     775          if (pthread_attr_init(&attrs) == 0) {
     776              rc = pthread_attr_setstacksize(&attrs, size);
     777              pthread_attr_destroy(&attrs);
     778              if (rc == 0) {
     779                  _PyInterpreterState_GET()->threads.stacksize = size;
     780                  return 0;
     781              }
     782          }
     783      }
     784      return -1;
     785  #else
     786      return -2;
     787  #endif
     788  }
     789  
     790  #define THREAD_SET_STACKSIZE(x) _pythread_pthread_set_stacksize(x)
     791  
     792  
     793  /* Thread Local Storage (TLS) API
     794  
     795     This API is DEPRECATED since Python 3.7.  See PEP 539 for details.
     796  */
     797  
     798  /* Issue #25658: On platforms where native TLS key is defined in a way that
     799     cannot be safely cast to int, PyThread_create_key returns immediately a
     800     failure status and other TLS functions all are no-ops.  This indicates
     801     clearly that the old API is not supported on platforms where it cannot be
     802     used reliably, and that no effort will be made to add such support.
     803  
     804     Note: PTHREAD_KEY_T_IS_COMPATIBLE_WITH_INT will be unnecessary after
     805     removing this API.
     806  */
     807  
     808  int
     809  PyThread_create_key(void)
     810  {
     811  #ifdef PTHREAD_KEY_T_IS_COMPATIBLE_WITH_INT
     812      pthread_key_t key;
     813      int fail = pthread_key_create(&key, NULL);
     814      if (fail)
     815          return -1;
     816      if (key > INT_MAX) {
     817          /* Issue #22206: handle integer overflow */
     818          pthread_key_delete(key);
     819          errno = ENOMEM;
     820          return -1;
     821      }
     822      return (int)key;
     823  #else
     824      return -1;  /* never return valid key value. */
     825  #endif
     826  }
     827  
     828  void
     829  PyThread_delete_key(int key)
     830  {
     831  #ifdef PTHREAD_KEY_T_IS_COMPATIBLE_WITH_INT
     832      pthread_key_delete(key);
     833  #endif
     834  }
     835  
     836  void
     837  PyThread_delete_key_value(int key)
     838  {
     839  #ifdef PTHREAD_KEY_T_IS_COMPATIBLE_WITH_INT
     840      pthread_setspecific(key, NULL);
     841  #endif
     842  }
     843  
     844  int
     845  PyThread_set_key_value(int key, void *value)
     846  {
     847  #ifdef PTHREAD_KEY_T_IS_COMPATIBLE_WITH_INT
     848      int fail = pthread_setspecific(key, value);
     849      return fail ? -1 : 0;
     850  #else
     851      return -1;
     852  #endif
     853  }
     854  
     855  void *
     856  PyThread_get_key_value(int key)
     857  {
     858  #ifdef PTHREAD_KEY_T_IS_COMPATIBLE_WITH_INT
     859      return pthread_getspecific(key);
     860  #else
     861      return NULL;
     862  #endif
     863  }
     864  
     865  
     866  void
     867  PyThread_ReInitTLS(void)
     868  {
     869  }
     870  
     871  
     872  /* Thread Specific Storage (TSS) API
     873  
     874     Platform-specific components of TSS API implementation.
     875  */
     876  
     877  int
     878  PyThread_tss_create(Py_tss_t *key)
     879  {
     880      assert(key != NULL);
     881      /* If the key has been created, function is silently skipped. */
     882      if (key->_is_initialized) {
     883          return 0;
     884      }
     885  
     886      int fail = pthread_key_create(&(key->_key), NULL);
     887      if (fail) {
     888          return -1;
     889      }
     890      key->_is_initialized = 1;
     891      return 0;
     892  }
     893  
     894  void
     895  PyThread_tss_delete(Py_tss_t *key)
     896  {
     897      assert(key != NULL);
     898      /* If the key has not been created, function is silently skipped. */
     899      if (!key->_is_initialized) {
     900          return;
     901      }
     902  
     903      pthread_key_delete(key->_key);
     904      /* pthread has not provided the defined invalid value for the key. */
     905      key->_is_initialized = 0;
     906  }
     907  
     908  int
     909  PyThread_tss_set(Py_tss_t *key, void *value)
     910  {
     911      assert(key != NULL);
     912      int fail = pthread_setspecific(key->_key, value);
     913      return fail ? -1 : 0;
     914  }
     915  
     916  void *
     917  PyThread_tss_get(Py_tss_t *key)
     918  {
     919      assert(key != NULL);
     920      return pthread_getspecific(key->_key);
     921  }