fix normalize problem in posix timers.
diff mbox series

Message ID 42E92C42.8000003@mvista.com
State New, archived
Headers show
Series
  • fix normalize problem in posix timers.
Related show

Commit Message

George Anzinger July 28, 2005, 7:04 p.m. UTC
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.  Patch is attached.
-
George Anzinger   george@mvista.com
HRT (High-res-timers):  http://sourceforge.net/projects/high-res-timers/
Source: MontaVista Software, Inc. George Anzinger <george@mvista.com>
Type: Defect Fix 
Description:
	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>
    
 posix-timers.c |   17 +++--------------
 1 files changed, 3 insertions(+), 14 deletions(-)

Patch
diff mbox series

Index: linux-2.6.13-rc/kernel/posix-timers.c
===================================================================
--- linux-2.6.13-rc.orig/kernel/posix-timers.c
+++ linux-2.6.13-rc/kernel/posix-timers.c
@@ -915,21 +915,10 @@  static int adjust_abs_time(struct k_cloc
 			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();
 	}