From c7a79bb036b42f96b7379b95efa643ee27df2168 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 21 Jun 2022 15:45:49 +0200 Subject: [PATCH] gh-74953: _PyThread_cond_after() uses _PyTime_t (#94056) pthread _PyThread_cond_after() implementation now uses the _PyTime_t type to handle properly overflow: clamp to the maximum value. Remove MICROSECONDS_TO_TIMESPEC() function. --- Python/condvar.h | 6 +++--- Python/thread_pthread.h | 39 +++++++++++++-------------------------- 2 files changed, 16 insertions(+), 29 deletions(-) diff --git a/Python/condvar.h b/Python/condvar.h index e5df7ff1328..4ddc5311cf8 100644 --- a/Python/condvar.h +++ b/Python/condvar.h @@ -68,9 +68,9 @@ void _PyThread_cond_after(long long us, struct timespec *abs); Py_LOCAL_INLINE(int) PyCOND_TIMEDWAIT(PyCOND_T *cond, PyMUTEX_T *mut, long long us) { - struct timespec abs; - _PyThread_cond_after(us, &abs); - int ret = pthread_cond_timedwait(cond, mut, &abs); + struct timespec abs_timeout; + _PyThread_cond_after(us, &abs_timeout); + int ret = pthread_cond_timedwait(cond, mut, &abs_timeout); if (ret == ETIMEDOUT) { return 1; } diff --git a/Python/thread_pthread.h b/Python/thread_pthread.h index a5719c39bc0..c310d72abd2 100644 --- a/Python/thread_pthread.h +++ b/Python/thread_pthread.h @@ -113,19 +113,6 @@ #endif -#define MICROSECONDS_TO_TIMESPEC(microseconds, ts) \ -do { \ - struct timeval tv; \ - gettimeofday(&tv, NULL); \ - tv.tv_usec += microseconds % 1000000; \ - tv.tv_sec += microseconds / 1000000; \ - tv.tv_sec += tv.tv_usec / 1000000; \ - tv.tv_usec %= 1000000; \ - ts.tv_sec = tv.tv_sec; \ - ts.tv_nsec = tv.tv_usec * 1000; \ -} while(0) - - /* * pthread_cond support */ @@ -156,23 +143,23 @@ _PyThread_cond_init(PyCOND_T *cond) return pthread_cond_init(cond, condattr_monotonic); } + void _PyThread_cond_after(long long us, struct timespec *abs) { + _PyTime_t timeout = _PyTime_FromMicrosecondsClamp(us); + _PyTime_t t; #ifdef CONDATTR_MONOTONIC if (condattr_monotonic) { - clock_gettime(CLOCK_MONOTONIC, abs); - abs->tv_sec += us / 1000000; - abs->tv_nsec += (us % 1000000) * 1000; - abs->tv_sec += abs->tv_nsec / 1000000000; - abs->tv_nsec %= 1000000000; - return; + t = _PyTime_GetMonotonicClock(); } + else #endif - - struct timespec ts; - MICROSECONDS_TO_TIMESPEC(us, ts); - *abs = ts; + { + t = _PyTime_GetSystemClock(); + } + t = _PyTime_Add(t, timeout); + _PyTime_AsTimespec_clamp(t, abs); } @@ -639,9 +626,9 @@ PyThread_acquire_lock_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds, goto unlock; } - struct timespec abs; + struct timespec abs_timeout; if (microseconds > 0) { - _PyThread_cond_after(microseconds, &abs); + _PyThread_cond_after(microseconds, &abs_timeout); } // Continue trying until we get the lock @@ -649,7 +636,7 @@ PyThread_acquire_lock_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds, while (1) { if (microseconds > 0) { status = pthread_cond_timedwait(&thelock->lock_released, - &thelock->mut, &abs); + &thelock->mut, &abs_timeout); if (status == 1) { break; }