Skip to content

Commit c7a79bb

Browse files
authored
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.
1 parent 616fa34 commit c7a79bb

File tree

2 files changed

+16
-29
lines changed

2 files changed

+16
-29
lines changed

Python/condvar.h

+3-3
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,9 @@ void _PyThread_cond_after(long long us, struct timespec *abs);
6868
Py_LOCAL_INLINE(int)
6969
PyCOND_TIMEDWAIT(PyCOND_T *cond, PyMUTEX_T *mut, long long us)
7070
{
71-
struct timespec abs;
72-
_PyThread_cond_after(us, &abs);
73-
int ret = pthread_cond_timedwait(cond, mut, &abs);
71+
struct timespec abs_timeout;
72+
_PyThread_cond_after(us, &abs_timeout);
73+
int ret = pthread_cond_timedwait(cond, mut, &abs_timeout);
7474
if (ret == ETIMEDOUT) {
7575
return 1;
7676
}

Python/thread_pthread.h

+13-26
Original file line numberDiff line numberDiff line change
@@ -113,19 +113,6 @@
113113
#endif
114114

115115

116-
#define MICROSECONDS_TO_TIMESPEC(microseconds, ts) \
117-
do { \
118-
struct timeval tv; \
119-
gettimeofday(&tv, NULL); \
120-
tv.tv_usec += microseconds % 1000000; \
121-
tv.tv_sec += microseconds / 1000000; \
122-
tv.tv_sec += tv.tv_usec / 1000000; \
123-
tv.tv_usec %= 1000000; \
124-
ts.tv_sec = tv.tv_sec; \
125-
ts.tv_nsec = tv.tv_usec * 1000; \
126-
} while(0)
127-
128-
129116
/*
130117
* pthread_cond support
131118
*/
@@ -156,23 +143,23 @@ _PyThread_cond_init(PyCOND_T *cond)
156143
return pthread_cond_init(cond, condattr_monotonic);
157144
}
158145

146+
159147
void
160148
_PyThread_cond_after(long long us, struct timespec *abs)
161149
{
150+
_PyTime_t timeout = _PyTime_FromMicrosecondsClamp(us);
151+
_PyTime_t t;
162152
#ifdef CONDATTR_MONOTONIC
163153
if (condattr_monotonic) {
164-
clock_gettime(CLOCK_MONOTONIC, abs);
165-
abs->tv_sec += us / 1000000;
166-
abs->tv_nsec += (us % 1000000) * 1000;
167-
abs->tv_sec += abs->tv_nsec / 1000000000;
168-
abs->tv_nsec %= 1000000000;
169-
return;
154+
t = _PyTime_GetMonotonicClock();
170155
}
156+
else
171157
#endif
172-
173-
struct timespec ts;
174-
MICROSECONDS_TO_TIMESPEC(us, ts);
175-
*abs = ts;
158+
{
159+
t = _PyTime_GetSystemClock();
160+
}
161+
t = _PyTime_Add(t, timeout);
162+
_PyTime_AsTimespec_clamp(t, abs);
176163
}
177164

178165

@@ -639,17 +626,17 @@ PyThread_acquire_lock_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds,
639626
goto unlock;
640627
}
641628

642-
struct timespec abs;
629+
struct timespec abs_timeout;
643630
if (microseconds > 0) {
644-
_PyThread_cond_after(microseconds, &abs);
631+
_PyThread_cond_after(microseconds, &abs_timeout);
645632
}
646633
// Continue trying until we get the lock
647634

648635
// mut must be locked by me -- part of the condition protocol
649636
while (1) {
650637
if (microseconds > 0) {
651638
status = pthread_cond_timedwait(&thelock->lock_released,
652-
&thelock->mut, &abs);
639+
&thelock->mut, &abs_timeout);
653640
if (status == 1) {
654641
break;
655642
}

0 commit comments

Comments
 (0)