#define TIMED_WAIT 300
g_timed_wait.tv_sec = time(NULL) + TIMED_WAIT;
g_timed_wait.tv_nsec = 0;
a)
status = pthread_cond_timedwait(&mutex_ptr->cond, &mutex_ptr->mutex,
&g_timed_wait);
b)
In my code I want to wakeup after 5 minutes.
First situation :
What will happens if at a) we are interrupted by a higher priority thread that
will change the date of the system, lets say it will come back by a month
in the past ?
Will pthread_cond_wait call wake after 1 month and 5 minutes ?
Second situation :
What will happens if at b) someone change the date of the system (one month
back)?
What the POSIX behaviour related to those kind of situations ?
Thanks.
--
Posted from wwwgate6.motorola.com [129.188.33.226]
via Mailgate.ORG Server - http://www.Mailgate.ORG
> What will happens if at a) we are interrupted by a higher priority thread that
> will change the date of the system, lets say it will come back by a month
> in the past ?
> Will pthread_cond_wait call wake after 1 month and 5 minutes ?
>
> Second situation :
>
> What will happens if at b) someone change the date of the system (one month
> back)?
There should be a thread somewhere in your program that monitors the
system clock. If it detects a significant jump, it should signal all
condition variables.
DS
> Could someone tell me what will happens if the following condition(s)
> occurs :
>
> #define TIMED_WAIT 300
>
> g_timed_wait.tv_sec = time(NULL) + TIMED_WAIT;
> g_timed_wait.tv_nsec = 0;
>
> a)
> status = pthread_cond_timedwait(&mutex_ptr->cond, &mutex_ptr->mutex,
> &g_timed_wait);
> b)
>
> In my code I want to wakeup after 5 minutes.
>
> First situation :
>
> What will happens if at a) we are interrupted by a higher priority thread
> that will change the date of the system, lets say it will come back by a
> month in the past ?
> Will pthread_cond_wait call wake after 1 month and 5 minutes ?
Of course it needn't be a "higher priority thread". It could be some other
process. For example, an NTP daemon configured to set time backwards.
(Though you SHOULDN'T ever configure NTP to do that, it's possible. You're
always better off correcting a fast clock by slowing the advance of time
until reality catches up than setting the clock back.)
Setting the clock FORWARD would also disrupt your wait time. In some cases,
waking early could be as bad as waking late.
> Second situation :
>
> What will happens if at b) someone change the date of the system (one
> month back)?
>
> What the POSIX behaviour related to those kind of situations?
POSIX time is UTC. The most common time changes are modifications of the
local offsets from UTC, daylight savings time changes -- and POSIX timers
such as pthread_cond_timedwait() are completely unaware of such changes.
However, if you set the system clock (UTC), then you've changed the system
time. All time functions based on CLOCK TIME, as is
pthread_cond_timedwait() MUST respond to the new time rather than the old
time.
You may like to pretend that you're waiting 300 seconds in the construct
above, but you're not. You're waiting UNTIL a time that you happen to have
constructed as being 300 seconds in your current future. The actual wait is
based on the absolute clock time, and the system is completely unaware of
your 300 seconds.
There are situations where you really want to wait for some DELTA time
rather than until an ABSOLUTE time. Such syntax, however, doesn't work well
with the pthread_cond_timedwait() model. Condition variables would be
either too hard to use reliably, or too expensive to use, if wakeups were
guaranteed to signal a change in predicate. Thus, you always need to be
prepared for "spurious wakeups", which is why you have to wait in a loop,
retesting the predicate condition. If you specify the timeout as a DELTA
time, you'd need to recompute the delta on each iteration of the loop, and
there's simply no reliable way to do that. (You'd need to know the elapsed
time from computation of your original delta until computation of your new
delta, which would mean tracking the absolute time, which would be broken
by system clock changes...)
The POSIX solution is called CLOCK_MONOTONIC. It's a new clock ID for the
POSIX timer services, representing a system clock (probably virtual) that
increases by a fixed and unalterable rate of 1 nanosecond for each real
elapsed nanosecond, and can never be altered otherwise. The absolute value
isn't meaningful... but it allows you to compute an "absolute time" that
represents a fixed and unalterable delta time from your current time. A new
condition variable attribute allows you to specify the clock ID on which
the timed wait should operate. (pthread_condattr_setclock)
(By the way, your computation of the timeout is wrong. The time() function
returns seconds, and you're simply adding 300 and setting tv_nsec to 0. But
your actual current time is "<s> seconds and <n> nanoseconds", so your
expiration time is <n> nanoseconds short of the presumably desired 300
seconds. In most cases the error isn't important, but it's still
technically wrong. Expiration times for pthread_cond_timedwait should be
computed from the result of clock_gettime(CLOCK_REALTIME). If you don't
have that, try gettimeofday(), which returns seconds and microseconds...
still technically inaccurate, but few systems keep time at a finer
granularity than that anyway.)
The proper POSIX way to set up a delta wait would be:
static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t c;
struct timespec delta;
pthread_condattr_t ca;
pthread_condattr_init (&ca);
pthread_condattr_setclock (&ca, CLOCK_MONOTONIC);
pthread_cond_init (&c, &ca);
clock_gettime (CLOCK_MONOTONIC, &delta);
delta.tv_sec += 300;
pthread_mutex_lock (&m);
while (!predicate) {
status = pthread_cond_timedwait (&c, &m, &delta);
if (status)
break;
}
One complication, though. The CLOCK_MONOTONIC clock ID, and the clock
condition variable attribute, are OPTIONS specified by the 1003.1j-2000
amendment to POSIX, which is not yet widely implemented. To check the
capabilities of your system, check the preprocessor symbol
_POSIX_MONOTONIC_CLOCK, which should be defined by <unistd.h> if your
system supports the option. (You could also check _SC_MONOTONIC_CLOCK with
sysconf()... but without the option your references to CLOCK_MONONTONIC and
pthread_condattr_setclock won't even compile, so a runtime check is "less
useful".)
/------------------[ David.B...@compaq.com ]------------------\
| Compaq Computer Corporation POSIX Thread Architect |
| My book: http://www.awl.com/cseng/titles/0-201-63392-2/ |
\-----[ http://home.earthlink.net/~anneart/family/dave.html ]-----/
Ok, this is new to me, although I can see what David is recommending.
How would one actually go about this in practice? Have the monitoring
thread wake up once per second and ensure that the clock is no more
than one second advanced? I am trying to think of some relativly
trivial algorithm that would do what he is suggesting.
If this is, as David is suggesting, common practice, then are there
any code examples or templates knocking around?
And in the thread that is waiting, which gets awoken if the clock
should change; what would one do there? Examine some flag which
indicates that a clock change has occurred and recalculate the wait?
More details please!
--
PGP Key 0xEB7180EC
at http://keyserver.pgp.com/pks/lookup?op=get&search=0xeb7180ec
> > There should be a thread somewhere in your program that monitors the
> >system clock. If it detects a significant jump, it should signal all
> >condition variables.
> Ok, this is new to me, although I can see what David is recommending.
> How would one actually go about this in practice? Have the monitoring
> thread wake up once per second and ensure that the clock is no more
> than one second advanced? I am trying to think of some relativly
> trivial algorithm that would do what he is suggesting.
Yep, that's about how it works. That same thread, when it detects a
clock jump forwards or backwards, can do all the work necessary to deal
with clock jumps.
> If this is, as David is suggesting, common practice, then are there
> any code examples or templates knocking around?
I don't know if it's common practice, but I do it, and I know of no
other way to make my code resilient against clock jumps.
> And in the thread that is waiting, which gets awoken if the clock
> should change; what would one do there? Examine some flag which
> indicates that a clock change has occurred and recalculate the wait?
Usually you don't care why you got woken up, you just deal with the
wakeup. If you need a reasonably reliable way to tell how much wall
clock has passed since you started waiting, check the counter of how
many times the clock monitoring thread has looped before and after. And
don't code the thread to sleep for one second each time because you will
accumulate error, compute how many milliseconds there are until the next
second boundary and sleep a few hundred less than that. Depending upon
your application, looping every five or ten seconds may be sufficient.
DS