89
89
* mutexes and condition variables:
90
90
*/
91
91
#if (defined(_POSIX_SEMAPHORES ) && !defined(HAVE_BROKEN_POSIX_SEMAPHORES ) && \
92
- defined(HAVE_SEM_TIMEDWAIT ))
92
+ ( defined(HAVE_SEM_TIMEDWAIT ) || defined( HAVE_SEM_CLOCKWAIT ) ))
93
93
# define USE_SEMAPHORES
94
94
#else
95
95
# undef USE_SEMAPHORES
96
96
#endif
97
97
98
+ #if defined(HAVE_PTHREAD_CONDATTR_SETCLOCK ) && defined(HAVE_CLOCK_GETTIME ) && defined(CLOCK_MONOTONIC )
99
+ // monotonic is supported statically. It doesn't mean it works on runtime.
100
+ #define CONDATTR_MONOTONIC
101
+ #endif
102
+
98
103
99
104
/* On platforms that don't use standard POSIX threads pthread_sigmask()
100
105
* isn't present. DEC threads uses sigprocmask() instead as do most
@@ -120,16 +125,23 @@ do { \
120
125
ts.tv_nsec = tv.tv_usec * 1000; \
121
126
} while(0)
122
127
128
+ #if defined(CONDATTR_MONOTONIC ) || defined(HAVE_SEM_CLOCKWAIT )
129
+ static void
130
+ monotonic_abs_timeout (long long us , struct timespec * abs )
131
+ {
132
+ clock_gettime (CLOCK_MONOTONIC , abs );
133
+ abs -> tv_sec += us / 1000000 ;
134
+ abs -> tv_nsec += (us % 1000000 ) * 1000 ;
135
+ abs -> tv_sec += abs -> tv_nsec / 1000000000 ;
136
+ abs -> tv_nsec %= 1000000000 ;
137
+ }
138
+ #endif
139
+
123
140
124
141
/*
125
142
* pthread_cond support
126
143
*/
127
144
128
- #if defined(HAVE_PTHREAD_CONDATTR_SETCLOCK ) && defined(HAVE_CLOCK_GETTIME ) && defined(CLOCK_MONOTONIC )
129
- // monotonic is supported statically. It doesn't mean it works on runtime.
130
- #define CONDATTR_MONOTONIC
131
- #endif
132
-
133
145
// NULL when pthread_condattr_setclock(CLOCK_MONOTONIC) is not supported.
134
146
static pthread_condattr_t * condattr_monotonic = NULL ;
135
147
@@ -151,16 +163,13 @@ _PyThread_cond_init(PyCOND_T *cond)
151
163
return pthread_cond_init (cond , condattr_monotonic );
152
164
}
153
165
166
+
154
167
void
155
168
_PyThread_cond_after (long long us , struct timespec * abs )
156
169
{
157
170
#ifdef CONDATTR_MONOTONIC
158
171
if (condattr_monotonic ) {
159
- clock_gettime (CLOCK_MONOTONIC , abs );
160
- abs -> tv_sec += us / 1000000 ;
161
- abs -> tv_nsec += (us % 1000000 ) * 1000 ;
162
- abs -> tv_sec += abs -> tv_nsec / 1000000000 ;
163
- abs -> tv_nsec %= 1000000000 ;
172
+ monotonic_abs_timeout (us , abs );
164
173
return ;
165
174
}
166
175
#endif
@@ -431,7 +440,9 @@ PyThread_acquire_lock_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds,
431
440
sem_t * thelock = (sem_t * )lock ;
432
441
int status , error = 0 ;
433
442
struct timespec ts ;
443
+ #ifndef HAVE_SEM_CLOCKWAIT
434
444
_PyTime_t deadline = 0 ;
445
+ #endif
435
446
436
447
(void ) error ; /* silence unused-but-set-variable warning */
437
448
dprintf (("PyThread_acquire_lock_timed(%p, %lld, %d) called\n" ,
@@ -442,6 +453,9 @@ PyThread_acquire_lock_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds,
442
453
}
443
454
444
455
if (microseconds > 0 ) {
456
+ #ifdef HAVE_SEM_CLOCKWAIT
457
+ monotonic_abs_timeout (microseconds , & ts );
458
+ #else
445
459
MICROSECONDS_TO_TIMESPEC (microseconds , ts );
446
460
447
461
if (!intr_flag ) {
@@ -450,11 +464,17 @@ PyThread_acquire_lock_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds,
450
464
_PyTime_t timeout = _PyTime_FromNanoseconds (microseconds * 1000 );
451
465
deadline = _PyTime_GetMonotonicClock () + timeout ;
452
466
}
467
+ #endif
453
468
}
454
469
455
470
while (1 ) {
456
471
if (microseconds > 0 ) {
472
+ #ifdef HAVE_SEM_CLOCKWAIT
473
+ status = fix_status (sem_clockwait (thelock , CLOCK_MONOTONIC ,
474
+ & ts ));
475
+ #else
457
476
status = fix_status (sem_timedwait (thelock , & ts ));
477
+ #endif
458
478
}
459
479
else if (microseconds == 0 ) {
460
480
status = fix_status (sem_trywait (thelock ));
@@ -469,6 +489,9 @@ PyThread_acquire_lock_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds,
469
489
break ;
470
490
}
471
491
492
+ // sem_clockwait() uses an absolute timeout, there is no need
493
+ // to recompute the relative timeout.
494
+ #ifndef HAVE_SEM_CLOCKWAIT
472
495
if (microseconds > 0 ) {
473
496
/* wait interrupted by a signal (EINTR): recompute the timeout */
474
497
_PyTime_t dt = deadline - _PyTime_GetMonotonicClock ();
@@ -490,13 +513,19 @@ PyThread_acquire_lock_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds,
490
513
microseconds = 0 ;
491
514
}
492
515
}
516
+ #endif
493
517
}
494
518
495
519
/* Don't check the status if we're stopping because of an interrupt. */
496
520
if (!(intr_flag && status == EINTR )) {
497
521
if (microseconds > 0 ) {
498
- if (status != ETIMEDOUT )
522
+ if (status != ETIMEDOUT ) {
523
+ #ifdef HAVE_SEM_CLOCKWAIT
524
+ CHECK_STATUS ("sem_clockwait" );
525
+ #else
499
526
CHECK_STATUS ("sem_timedwait" );
527
+ #endif
528
+ }
500
529
}
501
530
else if (microseconds == 0 ) {
502
531
if (status != EAGAIN )
0 commit comments