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.
This commit is contained in:
Victor Stinner 2022-06-21 15:45:49 +02:00 committed by GitHub
parent 616fa3465d
commit c7a79bb036
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 16 additions and 29 deletions

View file

@ -68,9 +68,9 @@ void _PyThread_cond_after(long long us, struct timespec *abs);
Py_LOCAL_INLINE(int) Py_LOCAL_INLINE(int)
PyCOND_TIMEDWAIT(PyCOND_T *cond, PyMUTEX_T *mut, long long us) PyCOND_TIMEDWAIT(PyCOND_T *cond, PyMUTEX_T *mut, long long us)
{ {
struct timespec abs; struct timespec abs_timeout;
_PyThread_cond_after(us, &abs); _PyThread_cond_after(us, &abs_timeout);
int ret = pthread_cond_timedwait(cond, mut, &abs); int ret = pthread_cond_timedwait(cond, mut, &abs_timeout);
if (ret == ETIMEDOUT) { if (ret == ETIMEDOUT) {
return 1; return 1;
} }

View file

@ -113,19 +113,6 @@
#endif #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 * pthread_cond support
*/ */
@ -156,23 +143,23 @@ _PyThread_cond_init(PyCOND_T *cond)
return pthread_cond_init(cond, condattr_monotonic); return pthread_cond_init(cond, condattr_monotonic);
} }
void void
_PyThread_cond_after(long long us, struct timespec *abs) _PyThread_cond_after(long long us, struct timespec *abs)
{ {
_PyTime_t timeout = _PyTime_FromMicrosecondsClamp(us);
_PyTime_t t;
#ifdef CONDATTR_MONOTONIC #ifdef CONDATTR_MONOTONIC
if (condattr_monotonic) { if (condattr_monotonic) {
clock_gettime(CLOCK_MONOTONIC, abs); t = _PyTime_GetMonotonicClock();
abs->tv_sec += us / 1000000;
abs->tv_nsec += (us % 1000000) * 1000;
abs->tv_sec += abs->tv_nsec / 1000000000;
abs->tv_nsec %= 1000000000;
return;
} }
else
#endif #endif
{
struct timespec ts; t = _PyTime_GetSystemClock();
MICROSECONDS_TO_TIMESPEC(us, ts); }
*abs = ts; 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; goto unlock;
} }
struct timespec abs; struct timespec abs_timeout;
if (microseconds > 0) { if (microseconds > 0) {
_PyThread_cond_after(microseconds, &abs); _PyThread_cond_after(microseconds, &abs_timeout);
} }
// Continue trying until we get the lock // 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) { while (1) {
if (microseconds > 0) { if (microseconds > 0) {
status = pthread_cond_timedwait(&thelock->lock_released, status = pthread_cond_timedwait(&thelock->lock_released,
&thelock->mut, &abs); &thelock->mut, &abs_timeout);
if (status == 1) { if (status == 1) {
break; break;
} }