Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 22 Feb 2017 09:19:12 -0600
From:      Eric van Gyzen <vangyzen@FreeBSD.org>
To:        Sebastian Huber <sebastian.huber@embedded-brains.de>, FreeBSD <freebsd-hackers@freebsd.org>
Subject:   Re: Absolute timeouts and clock adjustments
Message-ID:  <1ff4d78a-a157-53c5-af7e-b516bc1b6187@FreeBSD.org>
In-Reply-To: <58AD5802.30908@embedded-brains.de>
References:  <58AD5802.30908@embedded-brains.de>

next in thread | previous in thread | raw e-mail | index | archive | help
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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?1ff4d78a-a157-53c5-af7e-b516bc1b6187>