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 1/5] select: add a timespec version of the timeout to select/poll
Date: Fri, 29 Aug 2008 08:06:30 -0700 [thread overview]
Message-ID: <20080829080630.5e0ea608@infradead.org> (raw)
In-Reply-To: <20080829080549.6906b744@infradead.org>
From: Arjan van de Ven <arjan@linux.intel.com>
Date: Wed, 27 Aug 2008 11:24:52 -0700
Subject: [PATCH] select: add a timespec version of the timeout to select/poll
This patch adds the end_time parameter to the various pieces in the select()
and poll() paths; but does not use it yet (that is for later patches in
the series). This end_time is the timespec accuracy of the end time (eg
nanoseconds) rather than the current jiffies-juggling that happens all
over the poll/select code. It's also an absolute time, so we can always
see how long there is to go just by looking at the delta between the
end time and the current time.
Signed-off-by: Arjan van de Ven <arjan@linux.intel.com>
---
fs/compat.c | 28 ++++++++++++++++++++----
fs/select.c | 56 ++++++++++++++++++++++++++++++++++++++++---------
include/linux/poll.h | 6 ++--
3 files changed, 71 insertions(+), 19 deletions(-)
diff --git a/fs/compat.c b/fs/compat.c
index c9d1472..7c9b2a1 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -1513,7 +1513,8 @@ int compat_set_fd_set(unsigned long nr, compat_ulong_t __user *ufdset,
((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1)
int compat_core_sys_select(int n, compat_ulong_t __user *inp,
- compat_ulong_t __user *outp, compat_ulong_t __user *exp, s64 *timeout)
+ compat_ulong_t __user *outp, compat_ulong_t __user *exp, s64 *timeout,
+ struct timespec *end_time)
{
fd_set_bits fds;
void *bits;
@@ -1560,7 +1561,7 @@ int compat_core_sys_select(int n, compat_ulong_t __user *inp,
zero_fd_set(n, fds.res_out);
zero_fd_set(n, fds.res_ex);
- ret = do_select(n, &fds, timeout);
+ ret = do_select(n, &fds, timeout, end_time);
if (ret < 0)
goto out;
@@ -1589,6 +1590,7 @@ asmlinkage long compat_sys_select(int n, compat_ulong_t __user *inp,
s64 timeout = -1;
struct compat_timeval tv;
int ret;
+ struct timespec end_time;
if (tvp) {
if (copy_from_user(&tv, tvp, sizeof(tv)))
@@ -1604,9 +1606,12 @@ asmlinkage long compat_sys_select(int n, compat_ulong_t __user *inp,
timeout = DIV_ROUND_UP(tv.tv_usec, 1000000/HZ);
timeout += tv.tv_sec * HZ;
}
+ ktime_get_ts(&end_time);
+ timespec_add_ns(&end_time, tv.tv_usec*1000);
+ end_time.tv_sec += tv.tv_sec;
}
- ret = compat_core_sys_select(n, inp, outp, exp, &timeout);
+ ret = compat_core_sys_select(n, inp, outp, exp, &timeout, &end_time);
if (tvp) {
struct compat_timeval rtv;
@@ -1645,6 +1650,8 @@ asmlinkage long compat_sys_pselect7(int n, compat_ulong_t __user *inp,
sigset_t ksigmask, sigsaved;
s64 timeout = MAX_SCHEDULE_TIMEOUT;
struct compat_timespec ts;
+ struct timespec end_time;
+
int ret;
if (tsp) {
@@ -1653,6 +1660,11 @@ asmlinkage long compat_sys_pselect7(int n, compat_ulong_t __user *inp,
if (ts.tv_sec < 0 || ts.tv_nsec < 0)
return -EINVAL;
+ ktime_get_ts(&end_time);
+ end_time.tv_sec += ts.tv_sec;
+ timespec_add_ns(&end_time, ts.tv_nsec);
+ } else {
+ memset(&end_time, 0, sizeof(end_time));
}
if (sigmask) {
@@ -1679,7 +1691,7 @@ asmlinkage long compat_sys_pselect7(int n, compat_ulong_t __user *inp,
}
}
- ret = compat_core_sys_select(n, inp, outp, exp, &timeout);
+ ret = compat_core_sys_select(n, inp, outp, exp, &timeout, &end_time);
} while (!ret && !timeout && tsp && (ts.tv_sec || ts.tv_nsec));
@@ -1755,6 +1767,7 @@ asmlinkage long compat_sys_ppoll(struct pollfd __user *ufds,
compat_sigset_t ss32;
sigset_t ksigmask, sigsaved;
struct compat_timespec ts;
+ struct timespec end_time;
s64 timeout = -1;
int ret;
@@ -1767,6 +1780,11 @@ asmlinkage long compat_sys_ppoll(struct pollfd __user *ufds,
an s64. Otherwise the compiler bitches at us */
timeout = DIV_ROUND_UP(ts.tv_nsec, 1000000000/HZ);
timeout += ts.tv_sec * HZ;
+ ktime_get_ts(&end_time);
+ end_time.tv_sec += ts.tv_sec;
+ timespec_add_ns(&end_time, ts.tv_nsec);
+ } else {
+ memset(&end_time, 0, sizeof(end_time));
}
if (sigmask) {
@@ -1780,7 +1798,7 @@ asmlinkage long compat_sys_ppoll(struct pollfd __user *ufds,
sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
}
- ret = do_sys_poll(ufds, nfds, &timeout);
+ ret = do_sys_poll(ufds, nfds, &timeout, &end_time);
/* We can restart this syscall, usually */
if (ret == -EINTR) {
diff --git a/fs/select.c b/fs/select.c
index da0e882..6a6e33a 100644
--- a/fs/select.c
+++ b/fs/select.c
@@ -182,7 +182,7 @@ get_max:
#define POLLOUT_SET (POLLWRBAND | POLLWRNORM | POLLOUT | POLLERR)
#define POLLEX_SET (POLLPRI)
-int do_select(int n, fd_set_bits *fds, s64 *timeout)
+int do_select(int n, fd_set_bits *fds, s64 *timeout, struct timespec *end_time)
{
struct poll_wqueues table;
poll_table *wait;
@@ -300,7 +300,7 @@ int do_select(int n, fd_set_bits *fds, s64 *timeout)
((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1)
int core_sys_select(int n, fd_set __user *inp, fd_set __user *outp,
- fd_set __user *exp, s64 *timeout)
+ fd_set __user *exp, s64 *timeout, struct timespec *end_time)
{
fd_set_bits fds;
void *bits;
@@ -351,7 +351,7 @@ int core_sys_select(int n, fd_set __user *inp, fd_set __user *outp,
zero_fd_set(n, fds.res_out);
zero_fd_set(n, fds.res_ex);
- ret = do_select(n, &fds, timeout);
+ ret = do_select(n, &fds, timeout, end_time);
if (ret < 0)
goto out;
@@ -380,6 +380,9 @@ asmlinkage long sys_select(int n, fd_set __user *inp, fd_set __user *outp,
s64 timeout = -1;
struct timeval tv;
int ret;
+ struct timespec end_time;
+
+ memset(&end_time, 0, sizeof(end_time));
if (tvp) {
if (copy_from_user(&tv, tvp, sizeof(tv)))
@@ -388,6 +391,11 @@ asmlinkage long sys_select(int n, fd_set __user *inp, fd_set __user *outp,
if (tv.tv_sec < 0 || tv.tv_usec < 0)
return -EINVAL;
+ ktime_get_ts(&end_time);
+ timespec_add_ns(&end_time, tv.tv_usec*1000);
+ end_time.tv_sec += tv.tv_sec;
+
+
/* Cast to u64 to make GCC stop complaining */
if ((u64)tv.tv_sec >= (u64)MAX_INT64_SECONDS)
timeout = -1; /* infinite */
@@ -397,7 +405,7 @@ asmlinkage long sys_select(int n, fd_set __user *inp, fd_set __user *outp,
}
}
- ret = core_sys_select(n, inp, outp, exp, &timeout);
+ ret = core_sys_select(n, inp, outp, exp, &timeout, &end_time);
if (tvp) {
struct timeval rtv;
@@ -434,15 +442,22 @@ asmlinkage long sys_pselect7(int n, fd_set __user *inp, fd_set __user *outp,
s64 timeout = MAX_SCHEDULE_TIMEOUT;
sigset_t ksigmask, sigsaved;
struct timespec ts;
+ struct timespec end_time;
int ret;
+ memset(&end_time, 0, sizeof(end_time));
+
if (tsp) {
+ ktime_get_ts(&end_time);
if (copy_from_user(&ts, tsp, sizeof(ts)))
return -EFAULT;
if (ts.tv_sec < 0 || ts.tv_nsec < 0)
return -EINVAL;
+ end_time.tv_sec += ts.tv_sec;
+ timespec_add_ns(&end_time, ts.tv_nsec);
+
/* Cast to u64 to make GCC stop complaining */
if ((u64)ts.tv_sec >= (u64)MAX_INT64_SECONDS)
timeout = -1; /* infinite */
@@ -463,7 +478,7 @@ asmlinkage long sys_pselect7(int n, fd_set __user *inp, fd_set __user *outp,
sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
}
- ret = core_sys_select(n, inp, outp, exp, &timeout);
+ ret = core_sys_select(n, inp, outp, exp, &timeout, &end_time);
if (tsp) {
struct timespec rts;
@@ -574,7 +589,8 @@ static inline unsigned int do_pollfd(struct pollfd *pollfd, poll_table *pwait)
}
static int do_poll(unsigned int nfds, struct poll_list *list,
- struct poll_wqueues *wait, s64 *timeout)
+ struct poll_wqueues *wait, s64 *timeout,
+ struct timespec *end_time)
{
int count = 0;
poll_table* pt = &wait->pt;
@@ -646,7 +662,8 @@ static int do_poll(unsigned int nfds, struct poll_list *list,
#define N_STACK_PPS ((sizeof(stack_pps) - sizeof(struct poll_list)) / \
sizeof(struct pollfd))
-int do_sys_poll(struct pollfd __user *ufds, unsigned int nfds, s64 *timeout)
+int do_sys_poll(struct pollfd __user *ufds, unsigned int nfds, s64 *timeout,
+ struct timespec *end_time)
{
struct poll_wqueues table;
int err = -EFAULT, fdcount, len, size;
@@ -686,7 +703,7 @@ int do_sys_poll(struct pollfd __user *ufds, unsigned int nfds, s64 *timeout)
}
poll_initwait(&table);
- fdcount = do_poll(nfds, head, &table, timeout);
+ fdcount = do_poll(nfds, head, &table, timeout, end_time);
poll_freewait(&table);
for (walk = head; walk; walk = walk->next) {
@@ -716,8 +733,15 @@ static long do_restart_poll(struct restart_block *restart_block)
int nfds = restart_block->arg1;
s64 timeout = ((s64)restart_block->arg3<<32) | (s64)restart_block->arg2;
int ret;
+ struct timespec end_time;
+
+ memset(&end_time, 0, sizeof(end_time));
+ if (timeout) {
+ ktime_get_ts(&end_time);
+ timespec_add_ns(&end_time, timeout * NSEC_PER_SEC/HZ);
+ }
- ret = do_sys_poll(ufds, nfds, &timeout);
+ ret = do_sys_poll(ufds, nfds, &timeout, &end_time);
if (ret == -EINTR) {
restart_block->fn = do_restart_poll;
restart_block->arg2 = timeout & 0xFFFFFFFF;
@@ -732,6 +756,7 @@ asmlinkage long sys_poll(struct pollfd __user *ufds, unsigned int nfds,
{
s64 timeout_jiffies;
int ret;
+ struct timespec end_time;
if (timeout_msecs > 0) {
#if HZ > 1000
@@ -741,12 +766,15 @@ asmlinkage long sys_poll(struct pollfd __user *ufds, unsigned int nfds,
else
#endif
timeout_jiffies = msecs_to_jiffies(timeout_msecs) + 1;
+ ktime_get_ts(&end_time);
+ timespec_add_ns(&end_time, timeout_msecs*1000*1000);
} else {
/* Infinite (< 0) or no (0) timeout */
timeout_jiffies = timeout_msecs;
+ memset(&end_time, 0, sizeof(end_time));
}
- ret = do_sys_poll(ufds, nfds, &timeout_jiffies);
+ ret = do_sys_poll(ufds, nfds, &timeout_jiffies, &end_time);
if (ret == -EINTR) {
struct restart_block *restart_block;
restart_block = ¤t_thread_info()->restart_block;
@@ -768,6 +796,7 @@ asmlinkage long sys_ppoll(struct pollfd __user *ufds, unsigned int nfds,
sigset_t ksigmask, sigsaved;
struct timespec ts;
s64 timeout = -1;
+ struct timespec end_time;
int ret;
if (tsp) {
@@ -781,6 +810,11 @@ asmlinkage long sys_ppoll(struct pollfd __user *ufds, unsigned int nfds,
timeout = DIV_ROUND_UP(ts.tv_nsec, NSEC_PER_SEC/HZ);
timeout += ts.tv_sec * HZ;
}
+ ktime_get_ts(&end_time);
+ end_time.tv_sec += ts.tv_sec;
+ timespec_add_ns(&end_time, ts.tv_nsec);
+ } else {
+ memset(&end_time, 0, sizeof(end_time));
}
if (sigmask) {
@@ -794,7 +828,7 @@ asmlinkage long sys_ppoll(struct pollfd __user *ufds, unsigned int nfds,
sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
}
- ret = do_sys_poll(ufds, nfds, &timeout);
+ ret = do_sys_poll(ufds, nfds, &timeout, &end_time);
/* We can restart this syscall, usually */
if (ret == -EINTR) {
diff --git a/include/linux/poll.h b/include/linux/poll.h
index ef45382..ba9d4ce 100644
--- a/include/linux/poll.h
+++ b/include/linux/poll.h
@@ -114,11 +114,11 @@ void zero_fd_set(unsigned long nr, unsigned long *fdset)
#define MAX_INT64_SECONDS (((s64)(~((u64)0)>>1)/HZ)-1)
-extern int do_select(int n, fd_set_bits *fds, s64 *timeout);
+extern int do_select(int n, fd_set_bits *fds, s64 *timeout, struct timespec *end_time);
extern int do_sys_poll(struct pollfd __user * ufds, unsigned int nfds,
- s64 *timeout);
+ s64 *timeout, struct timespec *end_time);
extern int core_sys_select(int n, fd_set __user *inp, fd_set __user *outp,
- fd_set __user *exp, s64 *timeout);
+ fd_set __user *exp, s64 *timeout, struct timespec *end_time);
#endif /* KERNEL */
--
1.5.5.1
next prev parent reply other threads:[~2008-08-29 15:23 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 ` Arjan van de Ven [this message]
2008-08-30 2:10 ` [PATCH 1/5] select: add a timespec version of the timeout to select/poll Andrew Morton
2008-08-30 2:54 ` Linus Torvalds
2008-08-29 15:07 ` [PATCH 2/5] select: return accurate remainer in select() and ppoll() Arjan van de Ven
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=20080829080630.5e0ea608@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox