From: Arjan van de Ven <arjan@infradead.org>
To: linux-kernel@vger.kernel.org
Cc: Arjan van de Ven <arjan@infradead.org>,
mingo@elte.hu, tglx@tglx.de, torvalds@linux-foundation.org
Subject: [PATCH 2/5] select: return accurate remainer in select() and ppoll()
Date: Fri, 29 Aug 2008 08:07:08 -0700 [thread overview]
Message-ID: <20080829080708.4a301d23@infradead.org> (raw)
In-Reply-To: <20080829080549.6906b744@infradead.org>
From: Arjan van de Ven <arjan@linux.intel.com>
Date: Thu, 28 Aug 2008 13:40:29 -0700
Subject: [PATCH] select: return accurate remainer in select() and ppoll()
On Linux, select() and ppoll() write back the time remaining into the timeout
value. Now that we have a nanosecond level end time, we can also give a very
accurate remainder back; this patch adds the logic to do this.
Signed-off-by: Arjan van de Ven <arjan@linux.intel.com>
---
fs/compat.c | 39 ++++++++++++++++++++++++++++++---------
fs/select.c | 47 ++++++++++++++++++++++++++++++++++++-----------
2 files changed, 66 insertions(+), 20 deletions(-)
diff --git a/fs/compat.c b/fs/compat.c
index 7c9b2a1..b7c68f1 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -1615,11 +1615,22 @@ asmlinkage long compat_sys_select(int n, compat_ulong_t __user *inp,
if (tvp) {
struct compat_timeval rtv;
+ struct timespec now;
if (current->personality & STICKY_TIMEOUTS)
goto sticky;
rtv.tv_usec = jiffies_to_usecs(do_div((*(u64*)&timeout), HZ));
rtv.tv_sec = timeout;
+
+ ktime_get_ts(&now);
+ now = timespec_sub(end_time, now);
+ if (now.tv_sec < 0 || now.tv_nsec < 0) {
+ memset(&rtv, 0, sizeof(rtv));
+ } else {
+ rtv.tv_sec = now.tv_sec;
+ rtv.tv_usec = now.tv_nsec / NSEC_PER_USEC;
+ }
+
if (compat_timeval_compare(&rtv, &tv) >= 0)
rtv = tv;
if (copy_to_user(tvp, &rtv, sizeof(rtv))) {
@@ -1697,16 +1708,20 @@ asmlinkage long compat_sys_pselect7(int n, compat_ulong_t __user *inp,
if (tsp) {
struct compat_timespec rts;
+ struct timespec now;
if (current->personality & STICKY_TIMEOUTS)
goto sticky;
- rts.tv_sec = timeout / HZ;
- rts.tv_nsec = (timeout % HZ) * (NSEC_PER_SEC/HZ);
- if (rts.tv_nsec >= NSEC_PER_SEC) {
- rts.tv_sec++;
- rts.tv_nsec -= NSEC_PER_SEC;
+ ktime_get_ts(&now);
+ now = timespec_sub(end_time, now);
+ if (now.tv_sec < 0 || now.tv_nsec < 0) {
+ memset(&rts, 0, sizeof(rts));
+ } else {
+ rts.tv_nsec = now.tv_nsec;
+ rts.tv_sec = now.tv_sec;
}
+
if (compat_timespec_compare(&rts, &ts) >= 0)
rts = ts;
if (copy_to_user(tsp, &rts, sizeof(rts))) {
@@ -1818,13 +1833,19 @@ asmlinkage long compat_sys_ppoll(struct pollfd __user *ufds,
if (tsp && timeout >= 0) {
struct compat_timespec rts;
+ struct timespec now;
if (current->personality & STICKY_TIMEOUTS)
goto sticky;
- /* Yes, we know it's actually an s64, but it's also positive. */
- rts.tv_nsec = jiffies_to_usecs(do_div((*(u64*)&timeout), HZ)) *
- 1000;
- rts.tv_sec = timeout;
+ ktime_get_ts(&now);
+ now = timespec_sub(end_time, now);
+ if (now.tv_sec < 0 || now.tv_nsec < 0) {
+ memset(&rts, 0, sizeof(rts));
+ } else {
+ rts.tv_nsec = now.tv_nsec;
+ rts.tv_sec = now.tv_sec;
+ }
+
if (compat_timespec_compare(&rts, &ts) >= 0)
rts = ts;
if (copy_to_user(tsp, &rts, sizeof(rts))) {
diff --git a/fs/select.c b/fs/select.c
index 6a6e33a..3ce5943 100644
--- a/fs/select.c
+++ b/fs/select.c
@@ -409,13 +409,24 @@ asmlinkage long sys_select(int n, fd_set __user *inp, fd_set __user *outp,
if (tvp) {
struct timeval rtv;
+ struct timespec now;
if (current->personality & STICKY_TIMEOUTS)
goto sticky;
- rtv.tv_usec = jiffies_to_usecs(do_div((*(u64*)&timeout), HZ));
- rtv.tv_sec = timeout;
+
+ ktime_get_ts(&now);
+ now = timespec_sub(end_time, now);
+ if (now.tv_sec < 0 || now.tv_nsec < 0) {
+ rtv.tv_usec = 0;
+ rtv.tv_sec = 0;
+ } else {
+ rtv.tv_usec = now.tv_nsec / NSEC_PER_USEC;
+ rtv.tv_sec = now.tv_sec;
+ }
+
if (timeval_compare(&rtv, &tv) >= 0)
rtv = tv;
+
if (copy_to_user(tvp, &rtv, sizeof(rtv))) {
sticky:
/*
@@ -481,15 +492,24 @@ asmlinkage long sys_pselect7(int n, fd_set __user *inp, fd_set __user *outp,
ret = core_sys_select(n, inp, outp, exp, &timeout, &end_time);
if (tsp) {
- struct timespec rts;
+ struct timespec rts, now;
if (current->personality & STICKY_TIMEOUTS)
goto sticky;
- rts.tv_nsec = jiffies_to_usecs(do_div((*(u64*)&timeout), HZ)) *
- 1000;
- rts.tv_sec = timeout;
+
+ ktime_get_ts(&now);
+ now = timespec_sub(end_time, now);
+ if (now.tv_sec < 0 || now.tv_nsec < 0) {
+ rts.tv_nsec = 0;
+ rts.tv_sec = 0;
+ } else {
+ rts.tv_nsec = now.tv_nsec;
+ rts.tv_sec = now.tv_sec;
+ }
+
if (timespec_compare(&rts, &ts) >= 0)
rts = ts;
+
if (copy_to_user(tsp, &rts, sizeof(rts))) {
sticky:
/*
@@ -847,16 +867,21 @@ asmlinkage long sys_ppoll(struct pollfd __user *ufds, unsigned int nfds,
sigprocmask(SIG_SETMASK, &sigsaved, NULL);
if (tsp && timeout >= 0) {
- struct timespec rts;
+ struct timespec rts, now;
if (current->personality & STICKY_TIMEOUTS)
goto sticky;
- /* Yes, we know it's actually an s64, but it's also positive. */
- rts.tv_nsec = jiffies_to_usecs(do_div((*(u64*)&timeout), HZ)) *
- 1000;
- rts.tv_sec = timeout;
+
+ ktime_get_ts(&now);
+ now = timespec_sub(end_time, now);
+ if (now.tv_sec < 0 || now.tv_nsec < 0)
+ memset(&rts, 0, sizeof(rts));
+ else
+ rts = now;
+
if (timespec_compare(&rts, &ts) >= 0)
rts = ts;
+
if (copy_to_user(tsp, &rts, sizeof(rts))) {
sticky:
/*
--
1.5.5.1
next prev parent reply other threads:[~2008-08-29 15:21 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-08-29 15:05 [patch 0/5] Nano/Microsecond resolution for select() and poll() Arjan van de Ven
2008-08-29 15:06 ` [PATCH 1/5] select: add a timespec version of the timeout to select/poll Arjan van de Ven
2008-08-30 2:10 ` Andrew Morton
2008-08-30 2:54 ` Linus Torvalds
2008-08-29 15:07 ` Arjan van de Ven [this message]
2008-08-29 15:07 ` [PATCH 3/5] select: introduce a schedule_hrtimeout() function Arjan van de Ven
2008-08-29 15:08 ` [PATCH 4/5] select: make select() use schedule_hrtimeout() Arjan van de Ven
2008-08-29 15:36 ` Arnd Bergmann
2008-08-29 15:59 ` Daniel Walker
2008-08-29 16:20 ` Linus Torvalds
2008-08-29 16:11 ` Alan Cox
2008-08-29 17:26 ` Linus Torvalds
2008-08-29 17:42 ` Arjan van de Ven
2008-08-29 18:18 ` Alan Cox
2008-08-29 18:46 ` Linus Torvalds
2008-08-29 18:33 ` Alan Cox
2008-08-30 15:25 ` Arjan van de Ven
2008-08-29 16:30 ` Arjan van de Ven
2008-08-29 15:08 ` [PATCH 5/5] select: make poll() use schedule_hrtimeout() as well Arjan van de Ven
2008-08-29 15:54 ` [patch 0/5] Nano/Microsecond resolution for select() and poll() Arnd Bergmann
2008-08-29 16:12 ` Arjan van de Ven
2008-08-29 22:15 ` Brian Wellington
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=20080829080708.4a301d23@infradead.org \
--to=arjan@infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@elte.hu \
--cc=tglx@tglx.de \
--cc=torvalds@linux-foundation.org \
/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.