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