Absolute timeouts and clock adjustments
Ian Lepore
ian at freebsd.org
Wed Feb 22 15:46:18 UTC 2017
On Wed, 2017-02-22 at 09:19 -0600, Eric van Gyzen wrote:
> On 02/22/2017 03:21, Sebastian Huber wrote:
> >
> > Hello,
> >
> > I try to figure out how the timeout mechanisms work in current
> > FreeBSD. My
> > interpretation (which could be completely wrong) of POSIX is
> > something like this
> > should happen:
> >
> > now 2017-02-22
> > sem_timedwait(s, 2023-12-13)
> > external entity adjusts time to 2050-01-01
> > timeout of sem_timedwait() occurs due to the time adjustment
> This is correct.
>
> >
> > Inside the kernel all absolute timeouts seem to use the uptime. The
> > sem_timedwait() seems to end up eventually in:
> >
> > /*
> > * Put thread into sleep state, before sleeping, check if
> > * thread was removed from umtx queue.
> > */
> > static inline int
> > umtxq_sleep(struct umtx_q *uq, const char *wmesg, struct
> > abs_timeout *abstime)
> > {
> > struct umtxq_chain *uc;
> > int error, timo;
> >
> > uc = umtxq_getchain(&uq->uq_key);
> > UMTXQ_LOCKED_ASSERT(uc);
> > for (;;) {
> > if (!(uq->uq_flags & UQF_UMTXQ))
> > return (0);
> > if (abstime != NULL) {
> > timo = abs_timeout_gethz(abstime);
> > if (timo < 0)
> > return (ETIMEDOUT);
> > } else
> > timo = 0;
> > error = msleep(uq, &uc->uc_lock, PCATCH | PDROP, wmesg,
> > timo);
> > if (error != EWOULDBLOCK) {
> > umtxq_lock(&uq->uq_key);
> > break;
> > }
> > if (abstime != NULL)
> > abs_timeout_update(abstime);
> > umtxq_lock(&uq->uq_key);
> > }
> > return (error);
> > }
> >
> > The abs_timeout_gethz() returns the interval length in ticks of
> > [abstime->cur,
> > abstime->end]. Since the msleep() uses the uptime, does this mean
> > that timeouts
> > trigger not immediately due to time adjustments in FreeBSD?
> This is also correct. The sleep will not be affected by the clock
> adjustment.
> This is contrary to POSIX.
>
> Note that CentOS 6 (Linux 3.10) behaves the same way. Fedora 24
> (Linux 4.8)
> behaves according to POSIX. I don't know when this changed. I also
> don't know
> if it's configurable.
>
> By a curious coincidence, I'm working on adding a new
> sem_clockwait_np()
> function to FreeBSD. It allows the caller to specify the reference
> clock and
> choose between absolute and relative mode. In relative mode, the
> remaining time
> can be returned.
>
> https://reviews.freebsd.org/D9656
>
> My changes will not make sem_timedwait() comply with POSIX, but they
> will let
> the caller use CLOCK_MONOTONIC and avoid the issue.
>
> Eric
Using CLOCK_MONOTONIC doesn't avoid the issue, it just explicitly asks
for the current behavior. If the behavior you need is to wake up when
CLOCK_REALTIME exceeds some value, you're still screwed.
It would be easy enough to fix the current behavior by adding something
like "if (timo > hz) timo = hz;" to the existing loop so that
CLOCK_REALTIME gets re-checked once a second.
-- Ian
More information about the freebsd-hackers
mailing list