mirror of
https://github.com/adulau/aha.git
synced 2024-12-28 03:36:19 +00:00
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 changed entirely based on other peoples lkml feedback. Signed-off-by: Arjan van de Ven <arjan@linux.intel.com>
This commit is contained in:
parent
6976675d94
commit
90d6e24a36
1 changed files with 62 additions and 2 deletions
64
fs/select.c
64
fs/select.c
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -593,6 +649,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 +657,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 +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);
|
||||
|
|
Loading…
Reference in a new issue