lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20080901161459.0990a16b@infradead.org>
Date:	Mon, 1 Sep 2008 16:14:59 -0700
From:	Arjan van de Ven <arjan@...radead.org>
To:	linux-kernel@...r.kernel.org
Cc:	Arjan van de Ven <arjan@...radead.org>,
	torvalds@...ux-foundation.org, dwmw2@...radead.org,
	drepper@...hat.com, mingo@...e.hu, tglx@...x.de
Subject: [PATCH 13/13] hrtimer: make select() and poll() use the hrtimer
 range feature


From: Arjan van de Ven <arjan@...ux.intel.com>
Subject: [PATCH] hrtimer: make select() and poll() use the hrtimer range feature

This patch makes the select() and poll() hrtimers use the new range
feature and settings from the task struct.

In addition, this includes the estimate_accuracy() function that Linus
posted to lkml (but with a few steps added based on experiments).

Signed-off-by: Arjan van de Ven <arjan@...ux.intel.com>
---
 fs/select.c |   68 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 66 insertions(+), 2 deletions(-)

diff --git a/fs/select.c b/fs/select.c
index f6dceb5..21bf77d 100644
--- a/fs/select.c
+++ b/fs/select.c
@@ -28,6 +28,62 @@
 
 #include <asm/uaccess.h>
 
+
+/* Estimate expected accuracy in ns from a timeval */
+
+static unsigned long __estimate_accuracy(struct timespec *tv)
+{
+	/*
+	 * Tens of ms if we're looking at seconds, even
+	 * more for 10s+ sleeping
+	 */
+	if (tv->tv_sec) {
+		/* 100 milliseconds for long sleeps */
+		if (tv->tv_sec > 10)
+			return 100 * NSEC_PER_MSEC;
+
+		/*
+		 * Tens of ms for second-granularity sleeps. This,
+		 * btw, is the historical Linux 100Hz timer range.
+		 */
+		return 10 * NSEC_PER_MSEC;
+	}
+
+	/* 5 msec if we're looking at 100+ milliseconds */
+	if (tv->tv_nsec > 100 * NSEC_PER_MSEC)
+		return 5 * NSEC_PER_MSEC;
+
+	/* A msec if we're looking at 10+ milliseconds */
+	if (tv->tv_nsec > 10 * NSEC_PER_MSEC)
+		return NSEC_PER_MSEC;
+
+	/* half a msec if we're looking at milliseconds */
+	if (tv->tv_nsec > NSEC_PER_MSEC)
+		return NSEC_PER_MSEC/2;
+
+	/* Single usecs if we're looking at microseconds */
+	if (tv->tv_nsec > NSEC_PER_USEC)
+		return NSEC_PER_USEC;
+
+	/* Aim for tenths of nanosecs otherwise */
+	return 10;
+}
+
+static unsigned long estimate_accuracy(struct timespec *tv)
+{
+	unsigned long ret;
+	struct timespec now;
+
+	ktime_get_ts(&now);
+	now = timespec_sub(*tv, now);
+	ret = __estimate_accuracy(&now);
+	if (ret < current->timer_slack_ns)
+		return current->timer_slack_ns;
+	return ret;
+}
+
+
+
 struct poll_table_page {
 	struct poll_table_page * next;
 	struct poll_table_entry * entry;
@@ -262,6 +318,7 @@ int do_select(int n, fd_set_bits *fds, struct timespec *end_time)
 	struct poll_wqueues table;
 	poll_table *wait;
 	int retval, i, timed_out = 0;
+	unsigned long slack = 0;
 
 	rcu_read_lock();
 	retval = max_select_fd(n, fds);
@@ -278,6 +335,9 @@ int do_select(int n, fd_set_bits *fds, struct timespec *end_time)
 		timed_out = 1;
 	}
 
+	if (end_time)
+		slack = estimate_accuracy(end_time);
+
 	retval = 0;
 	for (;;) {
 		unsigned long *rinp, *routp, *rexp, *inp, *outp, *exp;
@@ -353,7 +413,7 @@ int do_select(int n, fd_set_bits *fds, struct timespec *end_time)
 			to = &expire;
 		}
 
-		if (!schedule_hrtimeout(to, HRTIMER_MODE_ABS))
+		if (!schedule_hrtimeout_range(to, slack, HRTIMER_MODE_ABS))
 			timed_out = 1;
 	}
 	__set_current_state(TASK_RUNNING);
@@ -593,6 +653,7 @@ static int do_poll(unsigned int nfds,  struct poll_list *list,
 	poll_table* pt = &wait->pt;
 	ktime_t expire, *to = NULL;
 	int timed_out = 0, count = 0;
+	unsigned long slack = 0;
 
 	/* Optimise the no-wait case */
 	if (end_time && !end_time->tv_sec && !end_time->tv_nsec) {
@@ -600,6 +661,9 @@ static int do_poll(unsigned int nfds,  struct poll_list *list,
 		timed_out = 1;
 	}
 
+	if (end_time)
+		slack = estimate_accuracy(end_time);
+
 	for (;;) {
 		struct poll_list *walk;
 
@@ -646,7 +710,7 @@ static int do_poll(unsigned int nfds,  struct poll_list *list,
 			to = &expire;
 		}
 
-		if (!schedule_hrtimeout(to, HRTIMER_MODE_ABS))
+		if (!schedule_hrtimeout_range(to, slack, HRTIMER_MODE_ABS))
 			timed_out = 1;
 	}
 	__set_current_state(TASK_RUNNING);
-- 
1.5.5.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ