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.
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;
{
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;