Date: Wed, 22 Feb 2017 08:46:05 -0700 From: Ian Lepore <ian@freebsd.org> To: Eric van Gyzen <vangyzen@FreeBSD.org>, Sebastian Huber <sebastian.huber@embedded-brains.de>, FreeBSD <freebsd-hackers@freebsd.org> Subject: Re: Absolute timeouts and clock adjustments Message-ID: <1487778365.73144.144.camel@freebsd.org> In-Reply-To: <1ff4d78a-a157-53c5-af7e-b516bc1b6187@FreeBSD.org> References: <58AD5802.30908@embedded-brains.de> <1ff4d78a-a157-53c5-af7e-b516bc1b6187@FreeBSD.org>
next in thread | previous in thread | raw e-mail | index | archive | help
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
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?1487778365.73144.144.camel>