LCOV - code coverage report
Current view: top level - Python - thread_pthread.h (source / functions) Hit Total Coverage
Test: CPython 3.12 LCOV report [commit acb105a7c1f] Lines: 145 183 79.2 %
Date: 2022-07-20 13:12:14 Functions: 21 27 77.8 %
Branches: 70 102 68.6 %

           Branch data     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                 :       2954 : init_condattr(void)
     130                 :            : {
     131                 :            : #ifdef CONDATTR_MONOTONIC
     132                 :            :     static pthread_condattr_t ca;
     133                 :       2954 :     pthread_condattr_init(&ca);
     134         [ +  - ]:       2954 :     if (pthread_condattr_setclock(&ca, CLOCK_MONOTONIC) == 0) {
     135                 :       2954 :         condattr_monotonic = &ca;  // Use monotonic clock
     136                 :            :     }
     137                 :            : #endif
     138                 :       2954 : }
     139                 :            : 
     140                 :            : int
     141                 :       5950 : _PyThread_cond_init(PyCOND_T *cond)
     142                 :            : {
     143                 :       5950 :     return pthread_cond_init(cond, condattr_monotonic);
     144                 :            : }
     145                 :            : 
     146                 :            : 
     147                 :            : void
     148                 :     198413 : _PyThread_cond_after(long long us, struct timespec *abs)
     149                 :            : {
     150                 :     198413 :     _PyTime_t timeout = _PyTime_FromMicrosecondsClamp(us);
     151                 :            :     _PyTime_t t;
     152                 :            : #ifdef CONDATTR_MONOTONIC
     153         [ +  - ]:     198413 :     if (condattr_monotonic) {
     154                 :     198413 :         t = _PyTime_GetMonotonicClock();
     155                 :            :     }
     156                 :            :     else
     157                 :            : #endif
     158                 :            :     {
     159                 :          0 :         t = _PyTime_GetSystemClock();
     160                 :            :     }
     161                 :     198413 :     t = _PyTime_Add(t, timeout);
     162                 :     198413 :     _PyTime_AsTimespec_clamp(t, abs);
     163                 :     198413 : }
     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                 :       2954 : PyThread__init_thread(void)
     197                 :            : {
     198                 :            : #if defined(_AIX) && defined(__GNUC__)
     199                 :            :     extern void pthread_init(void);
     200                 :            :     pthread_init();
     201                 :            : #endif
     202                 :       2954 :     init_condattr();
     203                 :       2954 : }
     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                 :       9381 : pythread_wrapper(void *arg)
     221                 :            : {
     222                 :            :     /* copy func and func_arg and free the temporary structure */
     223                 :       9381 :     pythread_callback *callback = arg;
     224                 :       9381 :     void (*func)(void *) = callback->func;
     225                 :       9381 :     void *func_arg = callback->arg;
     226                 :       9381 :     PyMem_RawFree(arg);
     227                 :            : 
     228                 :       9381 :     func(func_arg);
     229                 :       9251 :     return NULL;
     230                 :            : }
     231                 :            : 
     232                 :            : unsigned long
     233                 :       9381 : 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         [ -  + ]:       9381 :     if (!initialized)
     245                 :          0 :         PyThread_init_thread();
     246                 :            : 
     247                 :            : #if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED)
     248         [ -  + ]:       9381 :     if (pthread_attr_init(&attrs) != 0)
     249                 :          0 :         return PYTHREAD_INVALID_THREAD_ID;
     250                 :            : #endif
     251                 :            : #if defined(THREAD_STACK_SIZE)
     252                 :       9381 :     PyThreadState *tstate = _PyThreadState_GET();
     253         [ +  + ]:       9381 :     size_t stacksize = tstate ? tstate->interp->threads.stacksize : 0;
     254                 :       9381 :     tss = (stacksize != 0) ? stacksize : THREAD_STACK_SIZE;
     255         [ +  + ]:       9381 :     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                 :       9381 :     pthread_attr_setscope(&attrs, PTHREAD_SCOPE_SYSTEM);
     264                 :            : #endif
     265                 :            : 
     266                 :       9381 :     pythread_callback *callback = PyMem_RawMalloc(sizeof(pythread_callback));
     267                 :            : 
     268         [ -  + ]:       9381 :     if (callback == NULL) {
     269                 :          0 :       return PYTHREAD_INVALID_THREAD_ID;
     270                 :            :     }
     271                 :            : 
     272                 :       9381 :     callback->func = func;
     273                 :       9381 :     callback->arg = arg;
     274                 :            : 
     275                 :       9381 :     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                 :       9381 :     pthread_attr_destroy(&attrs);
     285                 :            : #endif
     286                 :            : 
     287         [ -  + ]:       9381 :     if (status != 0) {
     288                 :          0 :         PyMem_RawFree(callback);
     289                 :          0 :         return PYTHREAD_INVALID_THREAD_ID;
     290                 :            :     }
     291                 :            : 
     292                 :       9381 :     pthread_detach(th);
     293                 :            : 
     294                 :            : #if SIZEOF_PTHREAD_T <= SIZEOF_LONG
     295                 :       9381 :     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                 :   56311353 : PyThread_get_thread_ident(void)
     309                 :            : {
     310                 :            :     volatile pthread_t threadid;
     311         [ -  + ]:   56311353 :     if (!initialized)
     312                 :          0 :         PyThread_init_thread();
     313                 :   56311353 :     threadid = pthread_self();
     314                 :   56311353 :     return (unsigned long) threadid;
     315                 :            : }
     316                 :            : 
     317                 :            : #ifdef PY_HAVE_THREAD_NATIVE_ID
     318                 :            : unsigned long
     319                 :      30324 : PyThread_get_thread_native_id(void)
     320                 :            : {
     321         [ -  + ]:      30324 :     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                 :      30324 :     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                 :      30325 :     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                 :    1060551 : PyThread_allocate_lock(void)
     365                 :            : {
     366                 :            :     sem_t *lock;
     367                 :    1060551 :     int status, error = 0;
     368                 :            : 
     369         [ +  + ]:    1060551 :     if (!initialized)
     370                 :       2954 :         PyThread_init_thread();
     371                 :            : 
     372                 :    1060551 :     lock = (sem_t *)PyMem_RawMalloc(sizeof(sem_t));
     373                 :            : 
     374         [ +  - ]:    1060551 :     if (lock) {
     375                 :    1060551 :         status = sem_init(lock,0,1);
     376         [ -  + ]:    1060551 :         CHECK_STATUS("sem_init");
     377                 :            : 
     378         [ -  + ]:    1060551 :         if (error) {
     379                 :          0 :             PyMem_RawFree((void *)lock);
     380                 :          0 :             lock = NULL;
     381                 :            :         }
     382                 :            :     }
     383                 :            : 
     384                 :    1060551 :     return (PyThread_type_lock)lock;
     385                 :            : }
     386                 :            : 
     387                 :            : void
     388                 :    1059832 : PyThread_free_lock(PyThread_type_lock lock)
     389                 :            : {
     390                 :    1059832 :     sem_t *thelock = (sem_t *)lock;
     391                 :    1059832 :     int status, error = 0;
     392                 :            : 
     393                 :            :     (void) error; /* silence unused-but-set-variable warning */
     394                 :            : 
     395         [ -  + ]:    1059832 :     if (!thelock)
     396                 :          0 :         return;
     397                 :            : 
     398                 :    1059832 :     status = sem_destroy(thelock);
     399         [ -  + ]:    1059832 :     CHECK_STATUS("sem_destroy");
     400                 :            : 
     401                 :    1059832 :     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                 :    9072021 : fix_status(int status)
     412                 :            : {
     413         [ +  + ]:    9072021 :     return (status == -1) ? errno : status;
     414                 :            : }
     415                 :            : 
     416                 :            : PyLockStatus
     417                 :    9072040 : PyThread_acquire_lock_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds,
     418                 :            :                             int intr_flag)
     419                 :            : {
     420                 :            :     PyLockStatus success;
     421                 :    9072040 :     sem_t *thelock = (sem_t *)lock;
     422                 :    9072040 :     int status, error = 0;
     423                 :            : 
     424                 :            :     (void) error; /* silence unused-but-set-variable warning */
     425                 :            : 
     426                 :            :     _PyTime_t timeout;  // relative timeout
     427         [ +  + ]:    9072040 :     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                 :    5221635 :         timeout = _PyTime_FromMicrosecondsClamp(microseconds);
     437                 :            :     }
     438                 :            :     else {
     439                 :    3850405 :         timeout = _PyTime_FromNanoseconds(-1);
     440                 :            :     }
     441                 :            : 
     442                 :            : #ifdef HAVE_SEM_CLOCKWAIT
     443                 :            :     struct timespec abs_timeout;
     444                 :            :     // Local scope for deadline
     445                 :            :     {
     446                 :    9072041 :         _PyTime_t deadline = _PyTime_Add(_PyTime_GetMonotonicClock(), timeout);
     447                 :    9072041 :         _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         [ +  + ]:    9072041 :         if (timeout > 0) {
     458                 :            : #ifdef HAVE_SEM_CLOCKWAIT
     459                 :      15055 :             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         [ +  + ]:    9056986 :         else if (timeout == 0) {
     470                 :    5206580 :             status = fix_status(sem_trywait(thelock));
     471                 :            :         }
     472                 :            :         else {
     473                 :    3850406 :             status = fix_status(sem_wait(thelock));
     474                 :            :         }
     475                 :            : 
     476                 :            :         /* Retry if interrupted by a signal, unless the caller wants to be
     477                 :            :            notified.  */
     478   [ +  +  -  + ]:    9071974 :         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   [ +  +  +  + ]:    9071974 :     if (!(intr_flag && status == EINTR)) {
     498         [ +  + ]:    9071953 :         if (timeout > 0) {
     499         [ +  + ]:      15013 :             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         [ +  + ]:    9056940 :         else if (timeout == 0) {
     508         [ +  + ]:    5206580 :             if (status != EAGAIN) {
     509         [ -  + ]:    5021484 :                 CHECK_STATUS("sem_trywait");
     510                 :            :             }
     511                 :            :         }
     512                 :            :         else {
     513         [ -  + ]:    3850360 :             CHECK_STATUS("sem_wait");
     514                 :            :         }
     515                 :            :     }
     516                 :            : 
     517         [ +  + ]:    9071974 :     if (status == 0) {
     518                 :    8886187 :         success = PY_LOCK_ACQUIRED;
     519   [ +  +  +  + ]:     185787 :     } else if (intr_flag && status == EINTR) {
     520                 :         43 :         success = PY_LOCK_INTR;
     521                 :            :     } else {
     522                 :     185744 :         success = PY_LOCK_FAILURE;
     523                 :            :     }
     524                 :            : 
     525                 :    9071974 :     return success;
     526                 :            : }
     527                 :            : 
     528                 :            : void
     529                 :    8886222 : PyThread_release_lock(PyThread_type_lock lock)
     530                 :            : {
     531                 :    8886222 :     sem_t *thelock = (sem_t *)lock;
     532                 :    8886222 :     int status, error = 0;
     533                 :            : 
     534                 :            :     (void) error; /* silence unused-but-set-variable warning */
     535                 :            : 
     536                 :    8886222 :     status = sem_post(thelock);
     537         [ -  + ]:    8886222 :     CHECK_STATUS("sem_post");
     538                 :    8886222 : }
     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                 :    7190951 : PyThread_acquire_lock(PyThread_type_lock lock, int waitflag)
     730                 :            : {
     731         [ +  + ]:    7190951 :     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         [ -  + ]:          5 :                                                    : 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                 :       3001 : PyThread_tss_create(Py_tss_t *key)
     866                 :            : {
     867                 :            :     assert(key != NULL);
     868                 :            :     /* If the key has been created, function is silently skipped. */
     869         [ +  + ]:       3001 :     if (key->_is_initialized) {
     870                 :          1 :         return 0;
     871                 :            :     }
     872                 :            : 
     873                 :       3000 :     int fail = pthread_key_create(&(key->_key), NULL);
     874         [ -  + ]:       3000 :     if (fail) {
     875                 :          0 :         return -1;
     876                 :            :     }
     877                 :       3000 :     key->_is_initialized = 1;
     878                 :       3000 :     return 0;
     879                 :            : }
     880                 :            : 
     881                 :            : void
     882                 :       2990 : PyThread_tss_delete(Py_tss_t *key)
     883                 :            : {
     884                 :            :     assert(key != NULL);
     885                 :            :     /* If the key has not been created, function is silently skipped. */
     886         [ +  + ]:       2990 :     if (!key->_is_initialized) {
     887                 :          1 :         return;
     888                 :            :     }
     889                 :            : 
     890                 :       2989 :     pthread_key_delete(key->_key);
     891                 :            :     /* pthread has not provided the defined invalid value for the key. */
     892                 :       2989 :     key->_is_initialized = 0;
     893                 :            : }
     894                 :            : 
     895                 :            : int
     896                 :    2813684 : PyThread_tss_set(Py_tss_t *key, void *value)
     897                 :            : {
     898                 :            :     assert(key != NULL);
     899                 :    2813684 :     int fail = pthread_setspecific(key->_key, value);
     900         [ -  + ]:    2813684 :     return fail ? -1 : 0;
     901                 :            : }
     902                 :            : 
     903                 :            : void *
     904                 :   10746687 : PyThread_tss_get(Py_tss_t *key)
     905                 :            : {
     906                 :            :     assert(key != NULL);
     907                 :   10746687 :     return pthread_getspecific(key->_key);
     908                 :            : }

Generated by: LCOV version 1.14