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