Have PaUtil_GetTime() use monotonic time on Unix (#559)
The currently used clock, CLOCK_REALTIME, will have discontinuous jumps, forward and backward, when the system clock is adjusted. This is bad for synchronizing audio. CLOCK_MONOTONIC does not have jumps, and never moves backward, but does have the continuous adjustments done by NTP to increase clock accuracy. Since kernel 2.6.25 ALSA has use CLOCK_MONOTONIC by default for timestamps (commit b751eef1 from Dec 13 2007). This change means the timestamps provided in the PA callbacks can be compared to PaUtil_GetTime(), which currently does not work. The function used on MacOS, mach_absolute_time(), behaves like CLOCK_MONOTONIC. If the system does not have CLOCK_MONOTONIC, fallback to CLOCK_REALTIME, which is what alsa-lib does for such systems. Which at this point would need to be very old. * Use clock monotonic for condition variable This is necessary to match PaUtil_GetTime() also using the monotonic clock. Otherwise the wait time, derived from that function, will be completely incorrect. This will also fix an obscure flaw if the system clock is adjust while waiting for the stream to open, it might not wait at all and fail or wait (effectively) forever instead of timing out, depend on the adjustment direction.
This commit is contained in:
parent
52a78c72f3
commit
d859f7d5df
1 changed files with 10 additions and 1 deletions
|
|
@ -160,7 +160,11 @@ PaTime PaUtil_GetTime( void )
|
|||
return mach_absolute_time() * machSecondsConversionScaler_;
|
||||
#elif defined(HAVE_CLOCK_GETTIME)
|
||||
struct timespec tp;
|
||||
#if defined(CLOCK_MONOTONIC)
|
||||
clock_gettime(CLOCK_MONOTONIC, &tp);
|
||||
#else
|
||||
clock_gettime(CLOCK_REALTIME, &tp);
|
||||
#endif
|
||||
return (PaTime)(tp.tv_sec + tp.tv_nsec * 1e-9);
|
||||
#else
|
||||
struct timeval tv;
|
||||
|
|
@ -270,11 +274,16 @@ PaError PaUnixThread_New( PaUnixThread* self, void* (*threadFunc)( void* ), void
|
|||
{
|
||||
PaError result = paNoError;
|
||||
pthread_attr_t attr;
|
||||
pthread_condattr_t cattr;
|
||||
int started = 0;
|
||||
|
||||
memset( self, 0, sizeof (PaUnixThread) );
|
||||
PaUnixMutex_Initialize( &self->mtx );
|
||||
PA_ASSERT_CALL( pthread_cond_init( &self->cond, NULL ), 0 );
|
||||
PA_ASSERT_CALL( pthread_condattr_init( &cattr ), 0 );
|
||||
#if defined(CLOCK_MONOTONIC) && !defined(__APPLE__)
|
||||
PA_ASSERT_CALL( pthread_condattr_setclock( &cattr, CLOCK_MONOTONIC ), 0 );
|
||||
#endif
|
||||
PA_ASSERT_CALL( pthread_cond_init( &self->cond, &cattr), 0 );
|
||||
|
||||
self->parentWaiting = 0 != waitForChild;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue