Web lists-archives.com

Re: pthread_cond_timedwait with setclock(CLOCK_MONOTONIC) times out early




On Nov 25 09:01, James E. King III wrote:
> I have isolated a problem in pthread_cond_timedwait when the condattr
> is used to set the clock type to CLOCK_MONOTONIC.  In this case even
> though a target time point in the future is specified, the call
> returns ETIMEDOUT but a subsequent call to
> clock_gettime(CLOCK_MONOTONIC) shows the desired time point was not
> reached.
> 
> $ gcc timed_wait_short.c -o timed_wait_short
> $ ./timed_wait_short.exe
> [...]
>  begin:     521056s  671907500n
> target:     521056s  721907500n
>    end:     521056s  721578000n
>     ok: false
> 
> I have attached the source code.

Thanks for the testcase.  The problem is this:

The underlying implementation uses a Windows waitable time set to
implement the timeout.  In case of a CLOCK_REALTIME timer, we can use
the given absolut timestamp in 100ns resolution for the timer.

On the other hand, the CLOCK_MONOTONIC timer is not running in absolut
time but uses the hi-res timestamps generated by QueryPerformanceCounter.
The perf counter uses an arbitrary "ticks per second" unit which is
converted to nsecs on the fly on the POSIX API level.  However, perf
counters are not waitable objects, only waitable timers are, so we have
to use the perf timer values to prime a waitable timer evetually.

The side effect is that we have to use relative offset under the hood as
soon as the base timer is CLOCK_MONOTONIC, since there's no direct
relation to the absolute system time as used by the waitable timer in
absolute mode.

Combine this with the inaccuracy of the Windows waitable timer and wait
functions in general(*) and you know what uphill battle accuracy is in
this scenario.

Having said that, I don't have a *good*, reliable solution to this
problem.

At the moment I only have an *ugly* idea:  We can always add the
coarsest resolution of the wait functions (typically 15.625 ms) to the
relative timeout value computed from the absolute timeout given to
pthread_cond_timedwait.  In my testing this is sufficient since the
difference between target and actual end time is always < 15ms, in
thousands of runs.

Thoughts?


Thanks,
Corinna

(*) https://docs.microsoft.com/en-us/windows/desktop/Sync/wait-functions#wait-functions-and-time-out-intervals

-- 
Corinna Vinschen
Cygwin Maintainer

Attachment: signature.asc
Description: PGP signature