mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	bpo-41710: PyThread_acquire_lock_timed() uses sem_clockwait() (GH-28662)
On Unix, if the sem_clockwait() function is available in the C library (glibc 2.30 and newer), the threading.Lock.acquire() method now uses the monotonic clock (time.CLOCK_MONOTONIC) for the timeout, rather than using the system clock (time.CLOCK_REALTIME), to not be affected by system clock changes. configure now checks if the sem_clockwait() function is available.
This commit is contained in:
		
							parent
							
								
									3e1c5d989a
								
							
						
					
					
						commit
						1ee0f94d16
					
				
					 6 changed files with 216 additions and 128 deletions
				
			
		|  | @ -92,7 +92,7 @@ | |||
|  * mutexes and condition variables: | ||||
|  */ | ||||
| #if (defined(_POSIX_SEMAPHORES) && !defined(HAVE_BROKEN_POSIX_SEMAPHORES) && \ | ||||
|      defined(HAVE_SEM_TIMEDWAIT)) | ||||
|      (defined(HAVE_SEM_TIMEDWAIT) || defined(HAVE_SEM_CLOCKWAIT))) | ||||
| #  define USE_SEMAPHORES | ||||
| #else | ||||
| #  undef USE_SEMAPHORES | ||||
|  | @ -461,17 +461,34 @@ PyThread_acquire_lock_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds, | |||
|         timeout = _PyTime_FromNanoseconds(-1); | ||||
|     } | ||||
| 
 | ||||
| #ifdef HAVE_SEM_CLOCKWAIT | ||||
|     struct timespec abs_timeout; | ||||
|     // Local scope for deadline
 | ||||
|     { | ||||
|         _PyTime_t deadline = _PyTime_GetMonotonicClock() + timeout; | ||||
|         _PyTime_AsTimespec_clamp(deadline, &abs_timeout); | ||||
|     } | ||||
| #else | ||||
|     _PyTime_t deadline = 0; | ||||
|     if (timeout > 0 && !intr_flag) { | ||||
|     if (timeout > 0 | ||||
|         && !intr_flag | ||||
|         ) | ||||
|     { | ||||
|         deadline = _PyTime_GetMonotonicClock() + timeout; | ||||
|     } | ||||
| #endif | ||||
| 
 | ||||
|     while (1) { | ||||
|         if (timeout > 0) { | ||||
|             _PyTime_t t = _PyTime_GetSystemClock() + timeout; | ||||
| #ifdef HAVE_SEM_CLOCKWAIT | ||||
|             status = fix_status(sem_clockwait(thelock, CLOCK_MONOTONIC, | ||||
|                                               &abs_timeout)); | ||||
| #else | ||||
|             _PyTime_t abs_timeout = _PyTime_GetSystemClock() + timeout; | ||||
|             struct timespec ts; | ||||
|             _PyTime_AsTimespec_clamp(t, &ts); | ||||
|             _PyTime_AsTimespec_clamp(abs_timeout, &ts); | ||||
|             status = fix_status(sem_timedwait(thelock, &ts)); | ||||
| #endif | ||||
|         } | ||||
|         else if (timeout == 0) { | ||||
|             status = fix_status(sem_trywait(thelock)); | ||||
|  | @ -486,6 +503,9 @@ PyThread_acquire_lock_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds, | |||
|             break; | ||||
|         } | ||||
| 
 | ||||
|         // sem_clockwait() uses an absolute timeout, there is no need
 | ||||
|         // to recompute the relative timeout.
 | ||||
| #ifndef HAVE_SEM_CLOCKWAIT | ||||
|         if (timeout > 0) { | ||||
|             /* wait interrupted by a signal (EINTR): recompute the timeout */ | ||||
|             _PyTime_t timeout = deadline - _PyTime_GetMonotonicClock(); | ||||
|  | @ -494,17 +514,24 @@ PyThread_acquire_lock_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds, | |||
|                 break; | ||||
|             } | ||||
|         } | ||||
| #endif | ||||
|     } | ||||
| 
 | ||||
|     /* Don't check the status if we're stopping because of an interrupt.  */ | ||||
|     if (!(intr_flag && status == EINTR)) { | ||||
|         if (timeout > 0) { | ||||
|             if (status != ETIMEDOUT) | ||||
|             if (status != ETIMEDOUT) { | ||||
| #ifdef HAVE_SEM_CLOCKWAIT | ||||
|                 CHECK_STATUS("sem_clockwait"); | ||||
| #else | ||||
|                 CHECK_STATUS("sem_timedwait"); | ||||
| #endif | ||||
|             } | ||||
|         } | ||||
|         else if (timeout == 0) { | ||||
|             if (status != EAGAIN) | ||||
|             if (status != EAGAIN) { | ||||
|                 CHECK_STATUS("sem_trywait"); | ||||
|             } | ||||
|         } | ||||
|         else { | ||||
|             CHECK_STATUS("sem_wait"); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Victor Stinner
						Victor Stinner