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