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