aboutsummaryrefslogtreecommitdiffstats
path: root/fs/select.c
diff options
context:
space:
mode:
authorJohn Stultz <john.stultz@linaro.org>2016-03-17 17:20:51 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-03-17 18:09:34 -0400
commitda8b44d5a9f8bf26da637b7336508ca534d6b319 (patch)
treef8ce464a2adfa25d255ada3bd4ec762e0af9628a /fs/select.c
parent0a687aace3b8e215e08eed8a67014f5b8f133ab0 (diff)
timer: convert timer_slack_ns from unsigned long to u64
This patchset introduces a /proc/<pid>/timerslack_ns interface which would allow controlling processes to be able to set the timerslack value on other processes in order to save power by avoiding wakeups (Something Android currently does via out-of-tree patches). The first patch tries to fix the internal timer_slack_ns usage which was defined as a long, which limits the slack range to ~4 seconds on 32bit systems. It converts it to a u64, which provides the same basically unlimited slack (500 years) on both 32bit and 64bit machines. The second patch introduces the /proc/<pid>/timerslack_ns interface which allows the full 64bit slack range for a task to be read or set on both 32bit and 64bit machines. With these two patches, on a 32bit machine, after setting the slack on bash to 10 seconds: $ time sleep 1 real 0m10.747s user 0m0.001s sys 0m0.005s The first patch is a little ugly, since I had to chase the slack delta arguments through a number of functions converting them to u64s. Let me know if it makes sense to break that up more or not. Other than that things are fairly straightforward. This patch (of 2): The timer_slack_ns value in the task struct is currently a unsigned long. This means that on 32bit applications, the maximum slack is just over 4 seconds. However, on 64bit machines, its much much larger (~500 years). This disparity could make application development a little (as well as the default_slack) to a u64. This means both 32bit and 64bit systems have the same effective internal slack range. Now the existing ABI via PR_GET_TIMERSLACK and PR_SET_TIMERSLACK specify the interface as a unsigned long, so we preserve that limitation on 32bit systems, where SET_TIMERSLACK can only set the slack to a unsigned long value, and GET_TIMERSLACK will return ULONG_MAX if the slack is actually larger then what can be stored by an unsigned long. This patch also modifies hrtimer functions which specified the slack delta as a unsigned long. Signed-off-by: John Stultz <john.stultz@linaro.org> Cc: Arjan van de Ven <arjan@linux.intel.com> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Oren Laadan <orenl@cellrox.com> Cc: Ruchi Kandoi <kandoiruchi@google.com> Cc: Rom Lemarchand <romlem@android.com> Cc: Kees Cook <keescook@chromium.org> Cc: Android Kernel Team <kernel-team@android.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/select.c')
-rw-r--r--fs/select.c8
1 files changed, 4 insertions, 4 deletions
diff --git a/fs/select.c b/fs/select.c
index 79d0d4953cad..869293988c2a 100644
--- a/fs/select.c
+++ b/fs/select.c
@@ -70,9 +70,9 @@ static long __estimate_accuracy(struct timespec *tv)
70 return slack; 70 return slack;
71} 71}
72 72
73long select_estimate_accuracy(struct timespec *tv) 73u64 select_estimate_accuracy(struct timespec *tv)
74{ 74{
75 unsigned long ret; 75 u64 ret;
76 struct timespec now; 76 struct timespec now;
77 77
78 /* 78 /*
@@ -402,7 +402,7 @@ int do_select(int n, fd_set_bits *fds, struct timespec *end_time)
402 struct poll_wqueues table; 402 struct poll_wqueues table;
403 poll_table *wait; 403 poll_table *wait;
404 int retval, i, timed_out = 0; 404 int retval, i, timed_out = 0;
405 unsigned long slack = 0; 405 u64 slack = 0;
406 unsigned int busy_flag = net_busy_loop_on() ? POLL_BUSY_LOOP : 0; 406 unsigned int busy_flag = net_busy_loop_on() ? POLL_BUSY_LOOP : 0;
407 unsigned long busy_end = 0; 407 unsigned long busy_end = 0;
408 408
@@ -784,7 +784,7 @@ static int do_poll(struct poll_list *list, struct poll_wqueues *wait,
784 poll_table* pt = &wait->pt; 784 poll_table* pt = &wait->pt;
785 ktime_t expire, *to = NULL; 785 ktime_t expire, *to = NULL;
786 int timed_out = 0, count = 0; 786 int timed_out = 0, count = 0;
787 unsigned long slack = 0; 787 u64 slack = 0;
788 unsigned int busy_flag = net_busy_loop_on() ? POLL_BUSY_LOOP : 0; 788 unsigned int busy_flag = net_busy_loop_on() ? POLL_BUSY_LOOP : 0;
789 unsigned long busy_end = 0; 789 unsigned long busy_end = 0;
790 790