All of lore.kernel.org
 help / color / mirror / Atom feed
From: Helge Deller <deller@gmx.de>
To: linux-parisc@vger.kernel.org,
	Thomas Gleixner <tglx@linutronix.de>,
	linux-m68k@lists.linux-m68k.org, dhowells@redhat.com,
	linux-kernel@vger.kernel.org
Subject: [PATCH parisc,frv,m68k] timerfd: Fix timeout values with CONFIG_TIME_LOW_RES=y
Date: Sun, 10 Jan 2016 21:57:39 +0100	[thread overview]
Message-ID: <20160110205739.GA21713@p100.box> (raw)
In-Reply-To: <20160104222757.GA969@p100.box>

On architectures where CONFIG_TIME_LOW_RES is set (currently parisc,
m68k, frv) calling timerfd_settime() to set a timeout and directly
afterwards calling timerfd_gettime() to get the remaining time shows a
behaviour that the remaining time can be higher than the originally set
timeout.

Here is an example showing the problem, that the nsec value of it_value
is higher than the set nsec value: 
  timerfd_settime: interval (sec=0, nsec=100000000) it_value (sec=0, nsec=100000000) 
  timerfd_gettime: interval (sec=0, nsec=100000000) it_value (sec=0, nsec=103029949) 

This happens because in hrtimer_start_range_ns() the expiry time is
rounded to the next jiffies period to avoid short timeouts. When running
with HZ=250 this is 4ms which can be seen in the example above.

This behaviour confuses userspace programs. For example, the debian
liblinux-fd-perl and libnanomsg-raw-perl packges fail to build because
the timeout is higher than expected.

Fix this problem by subtracting the value added by
hrtimer_start_range_ns() before returning the timeout back to userspace.

Signed-off-by: Helge Deller <deller@gmx.de>

diff --git a/fs/timerfd.c b/fs/timerfd.c
index b94fa6c..098ac0a 100644
--- a/fs/timerfd.c
+++ b/fs/timerfd.c
@@ -152,8 +152,17 @@ static ktime_t timerfd_get_remaining(struct timerfd_ctx *ctx)
 
 	if (isalarm(ctx))
 		remaining = alarm_expires_remaining(&ctx->t.alarm);
-	else
+	else {
 		remaining = hrtimer_expires_remaining(&ctx->t.tmr);
+#ifdef CONFIG_TIME_LOW_RES
+		/* Expiry time was rounded up in hrtimer_start_range_ns()
+		 * to the next jiffies period to avoid short timeouts.
+		 * Subtract it here again to avoid userspace seeing higher
+		 * values than originally programmed. */
+		if (!(ctx->settime_flags & TFD_TIMER_ABSTIME))
+			remaining.tv64 -= hrtimer_resolution;
+#endif
+	}
 
 	return remaining.tv64 < 0 ? ktime_set(0, 0): remaining;
 }

WARNING: multiple messages have this Message-ID (diff)
From: Helge Deller <deller@gmx.de>
To: linux-parisc@vger.kernel.org,
	Thomas Gleixner <tglx@linutronix.de>,
	linux-m68k@vger.kernel.org, dhowells@redhat.com,
	linux-kernel@vger.kernel.org
Subject: [PATCH parisc,frv,m68k] timerfd: Fix timeout values with CONFIG_TIME_LOW_RES=y
Date: Sun, 10 Jan 2016 21:57:39 +0100	[thread overview]
Message-ID: <20160110205739.GA21713@p100.box> (raw)
In-Reply-To: <20160104222757.GA969@p100.box>

On architectures where CONFIG_TIME_LOW_RES is set (currently parisc,
m68k, frv) calling timerfd_settime() to set a timeout and directly
afterwards calling timerfd_gettime() to get the remaining time shows a
behaviour that the remaining time can be higher than the originally set
timeout.

Here is an example showing the problem, that the nsec value of it_value
is higher than the set nsec value: 
  timerfd_settime: interval (sec=0, nsec=100000000) it_value (sec=0, nsec=100000000) 
  timerfd_gettime: interval (sec=0, nsec=100000000) it_value (sec=0, nsec=103029949) 

This happens because in hrtimer_start_range_ns() the expiry time is
rounded to the next jiffies period to avoid short timeouts. When running
with HZ=250 this is 4ms which can be seen in the example above.

This behaviour confuses userspace programs. For example, the debian
liblinux-fd-perl and libnanomsg-raw-perl packges fail to build because
the timeout is higher than expected.

Fix this problem by subtracting the value added by
hrtimer_start_range_ns() before returning the timeout back to userspace.

Signed-off-by: Helge Deller <deller@gmx.de>

diff --git a/fs/timerfd.c b/fs/timerfd.c
index b94fa6c..098ac0a 100644
--- a/fs/timerfd.c
+++ b/fs/timerfd.c
@@ -152,8 +152,17 @@ static ktime_t timerfd_get_remaining(struct timerfd_ctx *ctx)
 
 	if (isalarm(ctx))
 		remaining = alarm_expires_remaining(&ctx->t.alarm);
-	else
+	else {
 		remaining = hrtimer_expires_remaining(&ctx->t.tmr);
+#ifdef CONFIG_TIME_LOW_RES
+		/* Expiry time was rounded up in hrtimer_start_range_ns()
+		 * to the next jiffies period to avoid short timeouts.
+		 * Subtract it here again to avoid userspace seeing higher
+		 * values than originally programmed. */
+		if (!(ctx->settime_flags & TFD_TIMER_ABSTIME))
+			remaining.tv64 -= hrtimer_resolution;
+#endif
+	}
 
 	return remaining.tv64 < 0 ? ktime_set(0, 0): remaining;
 }

  reply	other threads:[~2016-01-10 20:57 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-12-26 12:26 timerfd_settime/timerfd_gettime issue ? Helge Deller
2015-12-29  9:44 ` Thomas Gleixner
2015-12-29 20:13   ` Helge Deller
2015-12-30  9:57     ` Thomas Gleixner
2016-01-04 22:27       ` Helge Deller
2016-01-10 20:57         ` Helge Deller [this message]
2016-01-10 20:57           ` [PATCH parisc,frv,m68k] timerfd: Fix timeout values with CONFIG_TIME_LOW_RES=y Helge Deller

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20160110205739.GA21713@p100.box \
    --to=deller@gmx.de \
    --cc=dhowells@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-m68k@lists.linux-m68k.org \
    --cc=linux-parisc@vger.kernel.org \
    --cc=tglx@linutronix.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.