[PATCH -mm2] ktimers rounding fix
From: Thomas Gleixner
Date: Wed Nov 23 2005 - 05:12:52 EST
The rounding for the 64bit scalar representation was taking only
the lower 32bit into account, which is wrong because 2^32 is not a
multiple of 10. The patch implements seperate ktime_modulo
macros / functions for the hybrid and the scalar representation of
ktime_t.
Signed-off-by: Thomas Gleixner <tglx@xxxxxxxxxxxxx>
Index: linux-2.6.15-rc1-mm2/include/linux/ktime.h
===================================================================
--- linux-2.6.15-rc1-mm2.orig/include/linux/ktime.h
+++ linux-2.6.15-rc1-mm2/include/linux/ktime.h
@@ -133,6 +133,14 @@ typedef s64 ktime_t;
/* Convert ktime_t to nanoseconds - NOP in the scalar storage format: */
#define ktime_to_ns(kt) (kt)
+#if (BITS_PER_LONG == 64)
+/*
+ * Calc ktime_t modulo div.
+ * div is less than NSEC_PER_SEC and (NSEC_PER_SEC % div) = 0 !
+ */
+#define ktime_modulo(kt, div) (unsigned long)(kt % div)
+#endif
+
#else
/*
@@ -341,6 +349,12 @@ static inline u64 ktime_to_ns(ktime_t kt
return (u64) kt.tv.sec * NSEC_PER_SEC + kt.tv.nsec;
}
+/*
+ * Calc ktime_t modulo div.
+ * div is less than NSEC_PER_SEC and (NSEC_PER_SEC % div) = 0 !
+ */
+#define ktime_modulo(kt, div) ((unsigned long)kt.tv.nsec % div)
+
#endif
/*
Index: linux-2.6.15-rc1-mm2/kernel/ktimers.c
===================================================================
--- linux-2.6.15-rc1-mm2.orig/kernel/ktimers.c
+++ linux-2.6.15-rc1-mm2/kernel/ktimers.c
@@ -243,8 +243,9 @@ lock_ktimer_base(struct ktimer *timer, u
* Functions for the union type storage format of ktime_t which are
* too large for inlining:
*/
-#if (BITS_PER_LONG < 64) && !defined(CONFIG_KTIME_SCALAR)
+#if (BITS_PER_LONG < 64)
+#ifndef CONFIG_KTIME_SCALAR
/**
* ktime_add_ns - Add a scalar nanoseconds value to a ktime_t variable
*
@@ -267,6 +268,25 @@ ktime_t ktime_add_ns(ktime_t kt, u64 nse
return ktime_add(kt, tmp);
}
+
+#else
+
+/**
+ * ktime_modulo - Calc ktime_t modulo div
+ *
+ * @kt: dividend
+ * @div: divisor
+ *
+ * Return ktime_t modulo div.
+ *
+ * div is less than NSEC_PER_SEC and (NSEC_PER_SEC % div) = 0 !
+ */
+static unsigned long ktime_modulo(ktime_t kt, unsigned long div)
+{
+ return do_div(kt, div);
+}
+
+#endif
#endif
/*
@@ -394,8 +414,7 @@ static int enqueue_ktimer(struct ktimer
if (mode & KTIMER_ROUND) {
unsigned long rem;
- rem = ((unsigned long)ktime_get_low(timer->expires)) %
- base->resolution;
+ rem = ktime_modulo(timer->expires, base->resolution);
if (rem)
timer->expires = ktime_add_ns(timer->expires,
base->resolution - rem);
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/