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   [email protected]
HRT (High-res-timers):  http://sourceforge.net/projects/high-res-timers/
Source: MontaVista Software, Inc. George Anzinger <[email protected]>
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 <[email protected]>
    
 posix-timers.c |   17 +++--------------
 1 files changed, 3 insertions(+), 14 deletions(-)

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();
        }

Reply via email to