Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
On Linux, allow timed semaphore waits to use the monotonic clock when
``sem_clockwait`` is available at runtime, even if Python was built with
older libc headers.
47 changes: 31 additions & 16 deletions Python/parking_lot.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,18 @@

#include <stdbool.h>

#if defined(_Py_USE_SEMAPHORES) && defined(CLOCK_MONOTONIC) && !defined(_Py_THREAD_SANITIZER)
# ifdef HAVE_SEM_CLOCKWAIT
# define _Py_SEM_CLOCKWAIT_AVAILABLE 1
# elif defined(__linux__) && (defined(__GNUC__) || defined(__clang__))
/* Older glibc headers do not declare sem_clockwait. A weak reference allows
such builds to use monotonic waits on newer runtimes. */
extern int sem_clockwait(sem_t *, clockid_t, const struct timespec *)
__attribute__((weak));
# define _Py_SEM_CLOCKWAIT_AVAILABLE (sem_clockwait != NULL)
# endif
#endif


typedef struct {
// The mutex protects the waiter queue and the num_waiters counter.
Expand Down Expand Up @@ -151,24 +163,27 @@ _PySemaphore_Wait(_PySemaphore *sema, PyTime_t timeout)
if (timeout >= 0) {
struct timespec ts;

#if defined(CLOCK_MONOTONIC) && defined(HAVE_SEM_CLOCKWAIT) && !defined(_Py_THREAD_SANITIZER)
PyTime_t now;
// silently ignore error: cannot report error to the caller
(void)PyTime_MonotonicRaw(&now);
PyTime_t deadline = _PyTime_Add(now, timeout);
_PyTime_AsTimespec_clamp(deadline, &ts);

err = sem_clockwait(&sema->platform_sem, CLOCK_MONOTONIC, &ts);
#else
PyTime_t now;
// silently ignore error: cannot report error to the caller
(void)PyTime_TimeRaw(&now);
PyTime_t deadline = _PyTime_Add(now, timeout);

_PyTime_AsTimespec_clamp(deadline, &ts);
#ifdef _Py_SEM_CLOCKWAIT_AVAILABLE
if (_Py_SEM_CLOCKWAIT_AVAILABLE) {
PyTime_t now;
// Silently ignore error: cannot report error to the caller.
(void)PyTime_MonotonicRaw(&now);
PyTime_t deadline = _PyTime_Add(now, timeout);
_PyTime_AsTimespec_clamp(deadline, &ts);

err = sem_timedwait(&sema->platform_sem, &ts);
err = sem_clockwait(&sema->platform_sem, CLOCK_MONOTONIC, &ts);
}
else
#endif
{
PyTime_t now;
// Silently ignore error: cannot report error to the caller.
(void)PyTime_TimeRaw(&now);
PyTime_t deadline = _PyTime_Add(now, timeout);
_PyTime_AsTimespec_clamp(deadline, &ts);

err = sem_timedwait(&sema->platform_sem, &ts);
}
}
else {
err = sem_wait(&sema->platform_sem);
Expand Down
Loading