Aftar a few years of working with Pthreads I've matured to ask this
question. ;-)
What on Earth is the clock attribute of a condvar useful for?
We can do a pthread_cond_timedwait(), but we do not any explicit clock id
to do that. Moreover other synchronization primitives, like a mutex or an
rwlock do not have such an attribute. Why is it so?
Some googling I did showed that switching from CLOCK_REALTIME to
CLOCK_MONOTONIC might be useful in some real-time applications. I believe
it can, though it seems to me there applications must be rather obscure.
But why isn't an analogous feature for other synchronization tools?
Thanks for any remarks and best regards
Bartlomiej
> Aftar a few years of working with Pthreads I've matured to ask this
> question. ;-)
> What on Earth is the clock attribute of a condvar useful for?
It's useful to switch a condvar from wall time to elapsed time. This
makes the condvar usable even against jumps in system time without ill
effects.
> We can do a pthread_cond_timedwait(), but we do not any explicit clock id
> to do that.
If pthread_cond_timedwait took an explicit clock ID, then a condvar
would have to support waits against system time and waits against
elapsed time. This could mean that a change in the system time would
change the thread wakeup order. That would be a bizarre requirement.
So it makes more sense for the clock ID to be a condvar attribute.
> Moreover other synchronization primitives, like a mutex or an
> rwlock do not have such an attribute. Why is it so?
Because they don't have spurious (or apparently spurious) wakeups. You
have to wait for a condition variable in a loop. If the wait took a
delta time (wait up to 5 seconds), you would have to recalculate the
wait time each pass, which would be irritating. So condvars take a
fixed wakeup time, so you can keep calling them in a loop until either
the thing you want happens or a timeout occurs.
POSIX explicitly allows completely spurious wakeups. But you can also
get an "apparently spurious" wakeup because another thread consumed
the event that woke you up before you got to it.
Consider:
1) Thread A is willing to wait up to 5 seconds for something, but then
it must do something else.
2) It calculates the time five seconds from now.
3) There is nothing for it to do now, so it blocks on the condvar.
4) Thread B queues some work and signals the condvar, waking thread A.
5) Thread C finishes the work it was doing, acquires the mutex and
sees that there is work waiting. It takes the work and starts doing
it.
6) Thread A wakes up, checks for the work, and finds that it is not
there. It appears to thread A that this wakeup is spurious, though it
actually was triggered by thread B.
7) Thread A now needs to block on the condvar again, but for how long
should it block? It needs to know how much time is *left* of those
five seconds.
This is pretty much unique to condvars, as they are typically used.
> Some googling I did showed that switching from CLOCK_REALTIME to
> CLOCK_MONOTONIC might be useful in some real-time applications. I believe
> it can, though it seems to me there applications must be rather obscure.
> But why isn't an analogous feature for other synchronization tools?
Other synchronization tools don't take an absolute wakeup time. It's
the combination of spurious wakeups and an absolute wakeup time that
make it useful to switch to a monotonic (elapsed) time source.
DS
Thanks a lot for your answer.
On Sat, 24 Oct 2009, David Schwartz wrote:
> ---
> It's useful to switch a condvar from wall time to elapsed time. This
> makes the condvar usable even against jumps in system time without ill
> effects.
OK, so what are possible values of this attribute? Is it something more
than CLOCK_REALTIME and CLOCK_MONOTONIC?
>> We can do a pthread_cond_timedwait(), but we do not any explicit clock id
>> to do that.
>
> If pthread_cond_timedwait took an explicit clock ID, then a condvar
> would have to support waits against system time and waits against
> elapsed time. This could mean that a change in the system time would
> change the thread wakeup order. That would be a bizarre requirement.
> So it makes more sense for the clock ID to be a condvar attribute.
But what is specified is an absolute deadline. So changing the time on the
clock would change the wakeup time.
Or do you mean creating a specific ``logical'' clock and not manipulating
its time even if the ``main'' system clock is being tuned?
> ---
> Because they don't have spurious (or apparently spurious) wakeups. You
> have to wait for a condition variable in a loop. If the wait took a
> delta time (wait up to 5 seconds), you would have to recalculate the
> wait time each pass, which would be irritating. So condvars take a
> fixed wakeup time, so you can keep calling them in a loop until either
> the thing you want happens or a timeout occurs.
They don't, indeed.
So, how does e.g. pthread_mutex_timedlock() behave when time on the
clock is changed while the thread is waiting?
> POSIX explicitly allows completely spurious wakeups. But you can also
> get an "apparently spurious" wakeup because another thread consumed
> the event that woke you up before you got to it.
Yes, indeed. I should have thought about it.
> ---
>
> Other synchronization tools don't take an absolute wakeup time. It's
Don't they? AFAIK we always specify the *absolute* time, not the time
interval - for pthread_mutex_timedlock(), pthread_rwlock_timedrdlock(),
sem_timedwiait(), etc.
Isn't it so?
Thanks and best regards
Bartlomiej
> Dear David,
> Thanks a lot for your answer.
You're welcome.
> OK, so what are possible values of this attribute? Is it something more
> than CLOCK_REALTIME and CLOCK_MONOTONIC?
Those are the useful options on typical systems.
> >> We can do a pthread_cond_timedwait(), but we do not any explicit clock id
> >> to do that.
> > If pthread_cond_timedwait took an explicit clock ID, then a condvar
> > would have to support waits against system time and waits against
> > elapsed time. This could mean that a change in the system time would
> > change the thread wakeup order. That would be a bizarre requirement.
> > So it makes more sense for the clock ID to be a condvar attribute.
> But what is specified is an absolute deadline. So changing the time on the
> clock would change the wakeup time.
Yes, but not the *order* of wakeup.
> > Because they don't have spurious (or apparently spurious) wakeups. You
> > have to wait for a condition variable in a loop. If the wait took a
> > delta time (wait up to 5 seconds), you would have to recalculate the
> > wait time each pass, which would be irritating. So condvars take a
> > fixed wakeup time, so you can keep calling them in a loop until either
> > the thing you want happens or a timeout occurs.
> They don't, indeed.
> So, how does e.g. pthread_mutex_timedlock() behave when time on the
> clock is changed while the thread is waiting?
It is not affected because the time is an amount of time to wait. So
there's no issue.
But suppose I want to wait 5 seconds for a cv. I have to calculate an
absolute time because I may need to wait in a loop and don't want to
wait 5 seconds each time. But if I do that, what happens if the time
jumps back 5 seconds? Then I wait too long.
> > Other synchronization tools don't take an absolute wakeup time. It's
> Don't they? AFAIK we always specify the *absolute* time, not the time
> interval - for pthread_mutex_timedlock(), pthread_rwlock_timedrdlock(),
> sem_timedwiait(), etc.
> Isn't it so?
You're right! I'm so used to calling them through wrappers that take
relative times. Yes, I agree, it would be handy to be able to set them
to CLOCK_MONOTONIC.
DS