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)
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;
}

View file

@ -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;
}