Andrew Hunter
d78c9300c5
jiffies: Fix timeval conversion to jiffies
...
timeval_to_jiffies tried to round a timeval up to an integral number
of jiffies, but the logic for doing so was incorrect: intervals
corresponding to exactly N jiffies would become N+1. This manifested
itself particularly repeatedly stopping/starting an itimer:
setitimer(ITIMER_PROF, &val, NULL);
setitimer(ITIMER_PROF, NULL, &val);
would add a full tick to val, _even if it was exactly representable in
terms of jiffies_ (say, the result of a previous rounding.) Doing
this repeatedly would cause unbounded growth in val. So fix the math.
Here's what was wrong with the conversion: we essentially computed
(eliding seconds)
jiffies = usec * (NSEC_PER_USEC/TICK_NSEC)
by using scaling arithmetic, which took the best approximation of
NSEC_PER_USEC/TICK_NSEC with denominator of 2^USEC_JIFFIE_SC =
x/(2^USEC_JIFFIE_SC), and computed:
jiffies = (usec * x) >> USEC_JIFFIE_SC
and rounded this calculation up in the intermediate form (since we
can't necessarily exactly represent TICK_NSEC in usec.) But the
scaling arithmetic is a (very slight) *over*approximation of the true
value; that is, instead of dividing by (1 usec/ 1 jiffie), we
effectively divided by (1 usec/1 jiffie)-epsilon (rounding
down). This would normally be fine, but we want to round timeouts up,
and we did so by adding 2^USEC_JIFFIE_SC - 1 before the shift; this
would be fine if our division was exact, but dividing this by the
slightly smaller factor was equivalent to adding just _over_ 1 to the
final result (instead of just _under_ 1, as desired.)
In particular, with HZ=1000, we consistently computed that 10000 usec
was 11 jiffies; the same was true for any exact multiple of
TICK_NSEC.
We could possibly still round in the intermediate form, adding
something less than 2^USEC_JIFFIE_SC - 1, but easier still is to
convert usec->nsec, round in nanoseconds, and then convert using
time*spec*_to_jiffies. This adds one constant multiplication, and is
not observably slower in microbenchmarks on recent x86 hardware.
Tested: the following program:
int main() {
struct itimerval zero = {{0, 0}, {0, 0}};
/* Initially set to 10 ms. */
struct itimerval initial = zero;
initial.it_interval.tv_usec = 10000;
setitimer(ITIMER_PROF, &initial, NULL);
/* Save and restore several times. */
for (size_t i = 0; i < 10; ++i) {
struct itimerval prev;
setitimer(ITIMER_PROF, &zero, &prev);
/* on old kernels, this goes up by TICK_USEC every iteration */
printf("previous value: %ld %ld %ld %ld\n",
prev.it_interval.tv_sec, prev.it_interval.tv_usec,
prev.it_value.tv_sec, prev.it_value.tv_usec);
setitimer(ITIMER_PROF, &prev, NULL);
}
return 0;
}
Cc: stable@vger.kernel.org
Cc: Thomas Gleixner <tglx@linutronix.de >
Cc: Ingo Molnar <mingo@redhat.com >
Cc: Paul Turner <pjt@google.com >
Cc: Richard Cochran <richardcochran@gmail.com >
Cc: Prarit Bhargava <prarit@redhat.com >
Reviewed-by: Paul Turner <pjt@google.com >
Reported-by: Aaron Jacobs <jacobsa@google.com >
Signed-off-by: Andrew Hunter <ahh@google.com >
[jstultz: Tweaked to apply to 3.17-rc]
Signed-off-by: John Stultz <john.stultz@linaro.org >
2014-09-12 13:59:03 -07:00
..
2014-06-10 10:28:45 -07:00
2014-07-31 13:45:32 -04:00
2014-08-06 18:01:23 -07:00
2014-05-19 09:38:24 +02:00
2014-07-08 15:08:45 +04:00
2014-07-25 15:16:27 -07:00
2014-04-04 21:07:28 -07:00
2014-08-08 15:57:26 -07:00
2014-07-23 10:22:35 +09:00
2014-08-21 07:44:36 -05:00
2014-05-16 00:55:30 +02:00
2014-08-09 09:15:07 -07:00
2014-08-05 17:46:42 -07:00
2014-08-07 23:37:07 -07:00
2014-08-05 17:38:45 -07:00
2014-06-04 23:13:41 -07:00
2014-05-06 17:54:53 -04:00
2014-08-07 17:17:39 -07:00
2014-08-14 11:09:05 -06:00
2014-08-06 09:38:14 -07:00
2014-08-11 11:42:39 +02:00
2014-07-21 19:39:55 -07:00
2014-04-29 18:25:14 +02:00
2014-07-22 12:46:11 +05:30
2014-07-11 14:08:26 +02:00
2014-08-25 16:15:32 -07:00
2014-08-05 18:29:21 +01:00
2014-06-04 16:54:05 -07:00
2014-08-30 19:28:04 +01:00
2014-07-18 13:45:24 -04:00
2014-08-13 18:13:19 -06:00
2014-08-06 09:38:14 -07:00
2014-08-07 14:40:09 -04:00
2014-08-09 09:15:07 -07:00
2014-07-30 10:42:55 -07:00
2014-07-30 15:39:46 -04:00
2014-07-09 16:02:41 +02:00
2014-07-07 21:34:43 -07:00
2014-05-07 16:08:08 -04:00
2014-06-21 11:37:35 +01:00
2014-04-18 11:40:30 +02:00
2014-04-10 17:51:29 -04:00
2014-04-03 16:20:49 -07:00
2014-05-27 01:29:01 +02:00
2014-04-07 16:36:05 -07:00
2014-07-01 10:36:47 -06:00
2014-08-06 18:01:27 -07:00
2014-04-18 11:40:30 +02:00
2014-06-12 10:30:18 -07:00
2014-08-15 12:38:41 -06:00
2014-07-01 10:34:38 -06:00
2014-06-04 16:54:04 -07:00
2014-08-16 19:13:33 -07:00
2014-06-04 16:54:02 -07:00
2014-07-24 21:53:47 +10:00
2014-05-19 16:37:06 -04:00
2014-07-15 11:05:10 -04:00
2014-07-02 16:15:55 -07:00
2014-07-23 15:01:52 -07:00
2014-08-06 18:01:16 -07:00
2014-06-04 16:54:06 -07:00
2014-04-02 12:51:41 -07:00
2014-04-09 13:44:35 -07:00
2014-04-15 09:15:39 -07:00
2014-06-12 19:18:49 -07:00
2014-07-03 11:32:43 +01:00
2014-05-27 13:56:21 -07:00
2014-05-28 13:37:21 -07:00
2014-06-25 13:26:47 -07:00
2014-06-06 16:08:18 -07:00
2014-07-21 13:43:19 +02:00
2014-06-09 18:10:34 -07:00
2014-06-12 14:27:40 -07:00
2014-06-04 16:54:08 -07:00
2014-04-07 16:36:06 -07:00
2014-05-16 14:26:52 -04:00
2014-06-25 16:04:00 -07:00
2014-07-17 16:15:35 -04:00
2014-08-01 22:35:55 +08:00
2014-08-07 14:40:10 -04:00
2014-05-08 14:28:07 +08:00
2014-05-24 22:33:41 +09:00
2014-06-04 09:46:34 -04:00
2014-08-05 15:59:35 -07:00
2014-07-08 13:36:52 -07:00
2014-08-06 18:01:16 -07:00
2014-06-05 15:57:04 -07:00
2014-08-11 07:14:01 -07:00
2014-07-23 16:04:47 +02:00
2014-07-10 18:35:01 +02:00
2014-07-10 18:35:01 +02:00
2014-07-10 18:35:23 +02:00
2014-06-26 15:46:55 -03:00
2014-08-08 15:57:33 -07:00
2014-06-22 16:34:11 -06:00
2014-04-03 16:21:06 -07:00
2014-06-03 02:42:44 +01:00
2014-04-29 09:45:56 +09:00
2014-06-04 13:34:30 +09:00
2014-07-01 13:32:32 +03:00
2014-04-01 23:19:14 -04:00
2014-07-08 13:41:08 -07:00
2014-08-02 15:03:58 -07:00
2014-05-26 14:33:10 +02:00
2014-07-08 15:28:16 -07:00
2014-08-07 14:40:08 -04:00
2014-08-11 11:44:11 -07:00
2014-08-06 18:01:12 -07:00
2014-08-09 17:33:44 -07:00
2014-08-22 13:18:48 -04:00
2014-04-18 14:20:48 +02:00
2014-08-06 18:01:15 -07:00
2014-08-06 18:01:24 -07:00
2014-05-20 10:30:40 +09:00
2014-05-14 16:39:49 -07:00
2014-05-05 10:59:49 +01:00
2014-04-29 22:11:53 +01:00
2014-08-08 17:39:48 -07:00
2014-08-06 18:01:22 -07:00
2014-08-04 10:07:36 +02:00
2014-07-23 10:17:54 -07:00
2014-08-06 18:01:19 -07:00
2014-08-06 18:01:19 -07:00
2014-07-15 04:49:40 -04:00
2014-05-03 19:24:26 -04:00
2014-08-19 10:19:39 -05:00
2014-06-06 16:08:13 -07:00
2014-07-21 12:14:04 +02:00
2014-07-08 16:12:53 -07:00
2014-05-23 15:04:02 -04:00
2014-06-02 16:05:24 -07:00
2014-06-02 14:56:01 -07:00
2014-08-11 12:16:51 -07:00
2014-07-25 11:47:46 -07:00
2014-07-09 09:15:01 -07:00
2014-05-27 14:26:31 -07:00
2014-05-14 16:40:04 -07:00
2014-07-04 12:35:59 +02:00
2014-06-12 13:46:37 +02:00
2014-07-23 12:02:30 +02:00
2014-07-08 09:40:06 +02:00
2014-08-08 15:57:32 -07:00
2014-07-23 16:04:47 +02:00
2014-04-17 12:30:40 -07:00
2014-04-17 12:23:07 -07:00
2014-07-07 21:14:21 -07:00
2014-06-16 16:26:54 +02:00
2014-07-17 13:30:00 +00:00
2014-05-03 23:15:39 +02:00
2014-06-21 23:03:36 +02:00
2014-08-02 15:03:58 -07:00
2014-08-28 22:22:29 -04:00
2014-09-12 13:59:03 -07:00
2014-06-04 16:54:08 -07:00
2014-04-01 11:22:57 -07:00
2014-08-10 21:31:58 -07:00
2014-07-10 11:38:23 -07:00
2014-08-08 15:57:33 -07:00
2014-07-22 21:46:08 +01:00
2014-07-22 21:55:45 +01:00
2014-08-06 18:01:24 -07:00
2014-06-06 16:08:17 -07:00
2014-04-25 12:00:49 -07:00
2014-06-12 19:18:49 -07:00
2014-07-28 14:16:30 -04:00
2014-07-23 10:17:54 -07:00
2014-08-06 14:24:47 +02:00
2014-07-03 12:02:14 -07:00
2014-04-07 16:36:14 -07:00
2014-07-23 10:30:34 -04:00
2014-05-05 16:07:37 -07:00
2014-04-03 16:21:01 -07:00
2014-08-06 18:01:24 -07:00
2014-03-31 14:13:25 -07:00
2014-04-24 05:00:36 +00:00
2014-06-06 16:08:07 -07:00
2014-05-27 17:38:11 -07:00
2014-04-16 15:09:51 -04:00
2014-08-06 18:01:15 -07:00
2014-08-08 15:57:18 -07:00
2014-08-06 18:01:21 -07:00
2014-06-04 16:53:51 -07:00
2014-07-11 18:27:56 -07:00
2014-06-04 16:54:06 -07:00
2014-05-27 17:43:11 -07:00
2014-08-08 15:57:23 -07:00
2014-08-08 15:57:27 -07:00
2014-08-06 18:01:18 -07:00
2014-08-06 18:01:22 -07:00
2014-08-06 18:01:20 -07:00
2014-04-09 13:44:35 -07:00
2014-07-27 20:52:44 +09:30
2014-07-27 20:52:42 +09:30
2014-07-17 22:07:37 +02:00
2014-08-11 11:44:11 -07:00
2014-07-03 16:55:07 -06:00
2014-07-17 12:32:47 +02:00
2014-07-16 12:58:36 +00:00
2014-04-01 23:19:10 -04:00
2014-05-14 00:37:34 -04:00
2014-07-24 01:15:04 -07:00
2014-07-31 21:34:20 -07:00
2014-06-03 23:32:12 -07:00
2014-03-29 17:58:37 -04:00
2014-06-06 19:22:49 -04:00
2014-07-12 18:41:25 -04:00
2014-08-03 17:14:13 -04:00
2014-08-22 18:04:43 -04:00
2014-07-12 18:41:25 -04:00
2014-05-29 11:11:48 -04:00
2014-04-03 16:21:26 -07:00
2014-05-16 17:23:41 -04:00
2014-07-22 15:05:06 -07:00
2014-08-06 18:01:21 -07:00
2014-07-29 18:08:50 -07:00
2014-04-07 10:59:19 -07:00
2014-06-13 10:43:34 -04:00
2014-07-23 12:02:30 +02:00
2014-07-26 00:21:41 +05:30
2014-07-29 21:26:45 -06:00
2014-05-21 11:14:46 +02:00
2014-05-23 11:40:25 +09:00
2014-07-02 00:24:14 -07:00
2014-06-04 04:45:46 -05:00
2014-07-07 13:33:46 +01:00
2014-08-01 12:22:21 -06:00
2014-08-11 14:06:23 +01:00
2014-07-09 14:58:37 +01:00
2014-07-21 23:32:51 -07:00
2014-06-10 14:35:22 -07:00
2014-07-29 12:38:07 +02:00
2014-08-06 18:01:21 -07:00
2014-07-16 13:28:05 +02:00
2014-08-08 15:57:18 -07:00
2014-08-06 18:01:17 -07:00
2014-06-04 16:54:09 -07:00
2014-08-06 18:01:20 -07:00
2014-04-03 16:21:00 -07:00
2014-07-10 16:49:15 -06:00
2014-07-23 01:00:45 +02:00
2014-08-04 17:32:24 -07:00
2014-07-09 14:58:37 +01:00
2014-08-04 10:09:27 -07:00
2014-06-28 08:10:14 -04:00
2014-06-17 19:12:39 -04:00
2014-06-06 07:56:22 +02:00
2014-06-05 15:38:57 -07:00
2014-07-30 20:00:21 -07:00
2014-08-04 10:07:11 -07:00
2014-04-12 14:49:50 -07:00
2014-07-08 15:31:26 -07:00
2014-06-04 16:54:07 -07:00
2014-05-07 00:39:03 +02:00
2014-07-23 01:00:36 +02:00
2014-05-16 23:15:44 +02:00
2014-07-18 23:40:23 +02:00
2014-08-13 15:13:44 +10:00
2014-06-04 16:54:21 -07:00
2014-05-18 19:01:33 -07:00
2014-07-07 16:57:18 -07:00
2014-07-03 17:27:23 -07:00
2014-05-07 10:15:31 +02:00
2014-05-21 11:19:36 +02:00
2014-07-15 22:40:22 +02:00
2014-04-03 16:20:54 -07:00
2014-04-03 16:21:01 -07:00
2014-06-25 11:22:03 -07:00
2014-08-06 18:01:24 -07:00
2014-07-09 09:14:17 -07:00
2014-05-14 09:46:09 -07:00
2014-05-14 09:46:09 -07:00
2014-04-16 08:56:09 +02:00
2014-07-25 19:01:53 +01:00
2014-04-07 16:35:54 -07:00
2014-07-08 13:41:08 -07:00
2014-04-14 16:47:28 +02:00
2014-04-11 09:29:16 +02:00
2014-08-14 15:13:39 -07:00
2014-06-10 09:46:00 -04:00
2014-08-08 15:57:24 -07:00
2014-04-07 16:36:07 -07:00
2014-06-04 16:54:12 -07:00
2014-06-19 21:17:37 -07:00
2014-06-21 22:05:30 +02:00
2014-07-10 12:37:33 -07:00
2014-07-16 14:56:55 +02:00
2014-07-16 14:57:13 +02:00
2014-08-08 15:57:26 -07:00
2014-04-22 13:38:33 -07:00
2014-08-14 18:13:46 -06:00
2014-07-18 12:13:40 -07:00
2014-07-30 01:31:46 +10:00
2014-08-05 17:46:42 -07:00
2014-08-28 11:59:38 +05:30
2014-07-17 18:23:35 -07:00
2014-07-17 18:21:21 -07:00
2014-04-19 22:42:19 -07:00
2014-07-23 01:10:45 +02:00
2014-07-09 10:55:57 +02:00
2014-07-02 16:01:51 +02:00
2014-05-02 21:48:33 +05:30
2014-08-08 15:57:26 -07:00
2014-08-08 15:57:31 -07:00
2014-08-06 13:03:44 +02:00
2014-08-11 12:16:51 -07:00
2014-06-04 16:54:08 -07:00
2014-05-06 13:04:59 -07:00
2014-06-06 16:08:18 -07:00
2014-04-24 13:44:53 -04:00
2014-06-27 11:47:58 -07:00
2014-06-12 00:21:11 -04:00
2014-07-31 14:13:29 -07:00
2014-05-23 11:23:27 +09:00
2014-06-16 23:29:39 +02:00
2014-08-08 15:57:17 -07:00
2014-06-04 16:54:07 -07:00
2014-06-04 16:53:55 -07:00
2014-06-04 16:53:57 -07:00
2014-08-08 15:57:32 -07:00
2014-08-08 15:57:24 -07:00
2014-05-27 14:29:56 -07:00
2014-06-27 15:53:35 -07:00
2014-07-22 10:12:05 +08:00
2014-06-04 16:53:56 -07:00
2014-09-04 22:35:59 +02:00
2014-07-23 10:17:53 -07:00
2014-07-23 10:17:54 -07:00
2014-07-30 09:26:25 +02:00
2014-07-23 15:01:55 -07:00
2014-07-18 11:49:57 +02:00
2014-06-04 16:53:59 -07:00
2014-05-14 09:46:32 -07:00
2014-07-29 23:10:56 +02:00
2014-07-01 07:13:39 -04:00
2014-08-06 13:03:43 +02:00
2014-08-07 20:39:36 -04:00
2014-07-10 16:05:19 -07:00
2014-04-24 16:16:33 -07:00
2014-07-11 17:54:28 -07:00
2014-05-20 16:54:21 -06:00
2014-05-23 16:28:53 -04:00
2014-08-07 14:40:11 -04:00
2014-06-12 19:18:49 -07:00
2014-06-30 22:47:18 -07:00
2014-05-27 16:11:49 -07:00
2014-08-08 15:57:22 -07:00
2014-07-09 14:58:37 +01:00
2014-05-15 17:02:21 +01:00
2014-08-08 10:39:16 -06:00
2014-06-02 12:41:33 -07:00
2014-04-28 11:34:13 +09:30
2014-06-04 16:53:57 -07:00
2014-04-07 16:35:53 -07:00
2014-08-06 18:01:19 -07:00
2014-06-04 16:53:57 -07:00
2014-07-16 15:10:41 +02:00
2014-05-22 11:35:51 -04:00
2014-07-16 15:10:39 +02:00
2014-08-06 18:01:23 -07:00
2014-08-08 15:57:26 -07:00
2014-08-06 18:01:23 -07:00