5656#endif
5757#endif
5858
59- #if !defined(pthread_attr_default )
60- # define pthread_attr_default ((pthread_attr_t *)NULL)
61- #endif
62- #if !defined(pthread_mutexattr_default )
63- # define pthread_mutexattr_default ((pthread_mutexattr_t *)NULL)
64- #endif
65- #if !defined(pthread_condattr_default )
66- # define pthread_condattr_default ((pthread_condattr_t *)NULL)
67- #endif
68-
6959
7060/* Whether or not to use semaphores directly rather than emulating them with
7161 * mutexes and condition variables:
@@ -110,6 +100,56 @@ do { \
110100} while(0)
111101
112102
103+ /*
104+ * pthread_cond support
105+ */
106+
107+ #if defined(HAVE_PTHREAD_CONDATTR_SETCLOCK ) && defined(HAVE_CLOCK_GETTIME ) && defined(CLOCK_MONOTONIC )
108+ // monotonic is supported statically. It doesn't mean it works on runtime.
109+ #define CONDATTR_MONOTONIC
110+ #endif
111+
112+ // NULL when pthread_condattr_setclock(CLOCK_MONOTONIC) is not supported.
113+ static pthread_condattr_t * condattr_monotonic = NULL ;
114+
115+ static void
116+ init_condattr ()
117+ {
118+ #ifdef CONDATTR_MONOTONIC
119+ static pthread_condattr_t ca ;
120+ pthread_condattr_init (& ca );
121+ if (pthread_condattr_setclock (& ca , CLOCK_MONOTONIC ) == 0 ) {
122+ condattr_monotonic = & ca ; // Use monotonic clock
123+ }
124+ #endif
125+ }
126+
127+ int
128+ _PyThread_cond_init (PyCOND_T * cond )
129+ {
130+ return pthread_cond_init (cond , condattr_monotonic );
131+ }
132+
133+ void
134+ _PyThread_cond_after (long long us , struct timespec * abs )
135+ {
136+ #ifdef CONDATTR_MONOTONIC
137+ if (condattr_monotonic ) {
138+ clock_gettime (CLOCK_MONOTONIC , abs );
139+ abs -> tv_sec += us / 1000000 ;
140+ abs -> tv_nsec += (us % 1000000 ) * 1000 ;
141+ abs -> tv_sec += abs -> tv_nsec / 1000000000 ;
142+ abs -> tv_nsec %= 1000000000 ;
143+ return ;
144+ }
145+ #endif
146+
147+ struct timespec ts ;
148+ MICROSECONDS_TO_TIMESPEC (us , ts );
149+ * abs = ts ;
150+ }
151+
152+
113153/* A pthread mutex isn't sufficient to model the Python lock type
114154 * because, according to Draft 5 of the docs (P1003.4a/D5), both of the
115155 * following are undefined:
@@ -146,6 +186,7 @@ PyThread__init_thread(void)
146186 extern void pthread_init (void );
147187 pthread_init ();
148188#endif
189+ init_condattr ();
149190}
150191
151192/*
@@ -462,8 +503,7 @@ PyThread_allocate_lock(void)
462503 memset ((void * )lock , '\0' , sizeof (pthread_lock ));
463504 lock -> locked = 0 ;
464505
465- status = pthread_mutex_init (& lock -> mut ,
466- pthread_mutexattr_default );
506+ status = pthread_mutex_init (& lock -> mut , NULL );
467507 CHECK_STATUS_PTHREAD ("pthread_mutex_init" );
468508 /* Mark the pthread mutex underlying a Python mutex as
469509 pure happens-before. We can't simply mark the
@@ -472,8 +512,7 @@ PyThread_allocate_lock(void)
472512 will cause errors. */
473513 _Py_ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX (& lock -> mut );
474514
475- status = pthread_cond_init (& lock -> lock_released ,
476- pthread_condattr_default );
515+ status = _PyThread_cond_init (& lock -> lock_released );
477516 CHECK_STATUS_PTHREAD ("pthread_cond_init" );
478517
479518 if (error ) {
@@ -532,9 +571,10 @@ PyThread_acquire_lock_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds,
532571 success = PY_LOCK_ACQUIRED ;
533572 }
534573 else if (microseconds != 0 ) {
535- struct timespec ts ;
536- if (microseconds > 0 )
537- MICROSECONDS_TO_TIMESPEC (microseconds , ts );
574+ struct timespec abs ;
575+ if (microseconds > 0 ) {
576+ _PyThread_cond_after (microseconds , & abs );
577+ }
538578 /* continue trying until we get the lock */
539579
540580 /* mut must be locked by me -- part of the condition
@@ -543,10 +583,13 @@ PyThread_acquire_lock_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds,
543583 if (microseconds > 0 ) {
544584 status = pthread_cond_timedwait (
545585 & thelock -> lock_released ,
546- & thelock -> mut , & ts );
586+ & thelock -> mut , & abs );
587+ if (status == 1 ) {
588+ break ;
589+ }
547590 if (status == ETIMEDOUT )
548591 break ;
549- CHECK_STATUS_PTHREAD ("pthread_cond_timed_wait " );
592+ CHECK_STATUS_PTHREAD ("pthread_cond_timedwait " );
550593 }
551594 else {
552595 status = pthread_cond_wait (
0 commit comments