History

Merge branch 'timers-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull timer fix from Thomas Gleixner: "One more fix from the timer departement: - Handle division of negative nanosecond values proper on 32bit. A recent cleanup wrecked the sign handling of the dividend and dropped the check for negative divisors" * 'timers-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: ktime: Fix ktime_divns to do signed division

Linus Torvalds committed 11 years ago

Commit c5db6a32 parents 9bd4459 f7bcb702 files · +29 −12Browse files

Unified · Split

2 files
  1. include/linux/ktime.h +21 −6
  2. kernel/time/hrtimer.c +8 −6
include/linux/ktime.h+21−6
@@ -166,19 +166,34 @@ static inline bool ktime_before(const ktime_t cmp1, const ktime_t cmp2) · 165 unmodified lines
166166 }
167167
168168 #if BITS_PER_LONG < 64
169−extern u64 __ktime_divns(const ktime_t kt, s64 div);
170−static inline u64 ktime_divns(const ktime_t kt, s64 div)
169+extern s64 __ktime_divns(const ktime_t kt, s64 div);
170+static inline s64 ktime_divns(const ktime_t kt, s64 div)
171171 {
172+ /*
173+ * Negative divisors could cause an inf loop,
174+ * so bug out here.
175+ */
176+ BUG_ON(div < 0);
172177 if (__builtin_constant_p(div) && !(div >> 32)) {
173− u64 ns = kt.tv64;
174− do_div(ns, div);
175− return ns;
178+ s64 ns = kt.tv64;
179+ u64 tmp = ns < 0 ? -ns : ns;
180+
181+ do_div(tmp, div);
182+ return ns < 0 ? -tmp : tmp;
176183 } else {
177184 return __ktime_divns(kt, div);
178185 }
179186 }
180187 #else /* BITS_PER_LONG < 64 */
181−# define ktime_divns(kt, div) (u64)((kt).tv64 / (div))
188+static inline s64 ktime_divns(const ktime_t kt, s64 div)
189+{
190+ /*
191+ * 32-bit implementation cannot handle negative divisors,
192+ * so catch them on 64bit as well.
193+ */
194+ WARN_ON(div < 0);
195+ return kt.tv64 / div;
196+}
182197 #endif
183198
184199 static inline s64 ktime_to_us(const ktime_t kt)
kernel/time/hrtimer.c+8−6
@@ -266,21 +266,23 @@ lock_hrtimer_base(const struct hrtimer *timer, unsigned long *flags) · 265 unmodified lines
266266 /*
267267 * Divide a ktime value by a nanosecond value
268268 */
269−u64 __ktime_divns(const ktime_t kt, s64 div)
269+s64 __ktime_divns(const ktime_t kt, s64 div)
270270 {
271− u64 dclc;
272271 int sft = 0;
272+ s64 dclc;
273+ u64 tmp;
273274
274275 dclc = ktime_to_ns(kt);
276+ tmp = dclc < 0 ? -dclc : dclc;
277+
275278 /* Make sure the divisor is less than 2^32: */
276279 while (div >> 32) {
277280 sft++;
278281 div >>= 1;
279282 }
280− dclc >>= sft;
281− do_div(dclc, (unsigned long) div);
282−
283− return dclc;
283+ tmp >>= sft;
284+ do_div(tmp, (unsigned long) div);
285+ return dclc < 0 ? -tmp : tmp;
284286 }
285287 EXPORT_SYMBOL_GPL(__ktime_divns);
286288 #endif /* BITS_PER_LONG >= 64 */