Skip to content

Commit

Permalink
hrtimer: make select() and poll() use the hrtimer range feature
Browse files Browse the repository at this point in the history
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 changed entirely based on other peoples lkml feedback.

Signed-off-by: Arjan van de Ven <arjan@linux.intel.com>
  • Loading branch information
Arjan van de Ven committed Sep 6, 2008
1 parent 6976675 commit 90d6e24
Showing 1 changed file with 62 additions and 2 deletions.
64 changes: 62 additions & 2 deletions fs/select.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,58 @@

#include <asm/uaccess.h>


/*
* Estimate expected accuracy in ns from a timeval.
*
* After quite a bit of churning around, we've settled on
* a simple thing of taking 0.1% of the timeout as the
* slack, with a cap of 100 msec.
* "nice" tasks get a 0.5% slack instead.
*
* Consider this comment an open invitation to come up with even
* better solutions..
*/

static unsigned long __estimate_accuracy(struct timespec *tv)
{
unsigned long slack;
int divfactor = 1000;

if (task_nice(current))
divfactor = divfactor / 5;

slack = tv->tv_nsec / divfactor;
slack += tv->tv_sec * (NSEC_PER_SEC/divfactor);

if (slack > 100 * NSEC_PER_MSEC)
slack = 100 * NSEC_PER_MSEC;
return slack;
}

static unsigned long estimate_accuracy(struct timespec *tv)
{
unsigned long ret;
struct timespec now;

/*
* Realtime tasks get a slack of 0 for obvious reasons.
*/

if (current->policy == SCHED_FIFO ||
current->policy == SCHED_RR)
return 0;

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;
Expand Down Expand Up @@ -262,6 +314,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);
Expand All @@ -278,6 +331,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;
Expand Down Expand Up @@ -353,7 +409,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);
Expand Down Expand Up @@ -593,13 +649,17 @@ 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) {
pt = NULL;
timed_out = 1;
}

if (end_time)
slack = estimate_accuracy(end_time);

for (;;) {
struct poll_list *walk;

Expand Down Expand Up @@ -646,7 +706,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);
Expand Down

0 comments on commit 90d6e24

Please sign in to comment.