LCOV - code coverage report
Current view: top level - Python - thread_pthread.h (source / functions) Hit Total Coverage
Test: CPython lcov report Lines: 148 186 79.6 %
Date: 2022-07-07 18:19:46 Functions: 21 27 77.8 %

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

Generated by: LCOV version 1.14