summaryrefslogtreecommitdiff
path: root/kernel/posix-timers.c
diff options
context:
space:
mode:
authorGeorge Anzinger <george@mvista.com>2005-07-28 21:16:16 -0700
committerLinus Torvalds <torvalds@g5.osdl.org>2005-07-28 21:46:05 -0700
commit78fa74a23b16bdb0d944272b696915c4e0bb3ee1 (patch)
tree5f0d83021afeb7adffce9b41557e1d2e3c8c08bd /kernel/posix-timers.c
parenta2d76bd8fa29f9b6dbf3ee8f6bc7bdda21bc5ce8 (diff)
downloadlwn-78fa74a23b16bdb0d944272b696915c4e0bb3ee1.tar.gz
lwn-78fa74a23b16bdb0d944272b696915c4e0bb3ee1.zip
[PATCH] posix timers: fix normalization problem
(We found this (after a customer complained) and it is in the kernel.org kernel. Seems that for CLOCK_MONOTONIC absolute timers and clock_nanosleep calls both the request time and wall_to_monotonic are subtracted prior to the normalize resulting in an overflow in the existing normalize test. This causes the result to be shifted ~4 seconds ahead instead of ~2 seconds back in time.) The normalize code in posix-timers.c fails when the tv_nsec member is ~1.2 seconds negative. This can happen on absolute timers (and clock_nanosleeps) requested on CLOCK_MONOTONIC (both the request time and wall_to_monotonic are subtracted resulting in the possibility of a number close to -2 seconds.) This fix uses the set_normalized_timespec() (which does not have an overflow problem) to fix the problem and as a side effect makes the code cleaner. Signed-off-by: George Anzinger <george@mvista.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'kernel/posix-timers.c')
-rw-r--r--kernel/posix-timers.c17
1 files changed, 3 insertions, 14 deletions
diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c
index 5b7b4736d82b..10b2ad749d14 100644
--- a/kernel/posix-timers.c
+++ b/kernel/posix-timers.c
@@ -896,21 +896,10 @@ static int adjust_abs_time(struct k_clock *clock, struct timespec *tp,
jiffies_64_f = get_jiffies_64();
}
/*
- * Take away now to get delta
+ * Take away now to get delta and normalize
*/
- oc.tv_sec -= now.tv_sec;
- oc.tv_nsec -= now.tv_nsec;
- /*
- * Normalize...
- */
- while ((oc.tv_nsec - NSEC_PER_SEC) >= 0) {
- oc.tv_nsec -= NSEC_PER_SEC;
- oc.tv_sec++;
- }
- while ((oc.tv_nsec) < 0) {
- oc.tv_nsec += NSEC_PER_SEC;
- oc.tv_sec--;
- }
+ set_normalized_timespec(&oc, oc.tv_sec - now.tv_sec,
+ oc.tv_nsec - now.tv_nsec);
}else{
jiffies_64_f = get_jiffies_64();
}