]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-74953: _PyThread_cond_after() uses _PyTime_t (#94056)
authorVictor Stinner <vstinner@python.org>
Tue, 21 Jun 2022 13:45:49 +0000 (15:45 +0200)
committerGitHub <noreply@github.com>
Tue, 21 Jun 2022 13:45:49 +0000 (15:45 +0200)
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
Python/thread_pthread.h

index e5df7ff132802f8e9cacfdb222188920454449d8..4ddc5311cf8fad1c455129115e9015bf496e4b02 100644 (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;
     }
index a5719c39bc0125e9824e5fb562a58270afd2fdaa..c310d72abd2d58916607b880da514499d0b8ff89 100644 (file)
 #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;
             }