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