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