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
166}166}
167 167
168#if BITS_PER_LONG < 64168#if BITS_PER_LONG < 64
169extern u64 __ktime_divns(const ktime_t kt, s64 div);169extern s64 __ktime_divns(const ktime_t kt, s64 div);
170static inline u64 ktime_divns(const ktime_t kt, s64 div)170static inline s64 ktime_divns(const ktime_t kt, s64 div)
171{171{
172 /*
173 * Negative divisors could cause an inf loop,
174 * so bug out here.
175 */
176 BUG_ON(div < 0);
172 if (__builtin_constant_p(div) && !(div >> 32)) {177 if (__builtin_constant_p(div) && !(div >> 32)) {
173 u64 ns = kt.tv64;178 s64 ns = kt.tv64;
174 do_div(ns, div);179 u64 tmp = ns < 0 ? -ns : ns;
175 return ns;180
181 do_div(tmp, div);
182 return ns < 0 ? -tmp : tmp;
176 } else {183 } else {
177 return __ktime_divns(kt, div);184 return __ktime_divns(kt, div);
178 }185 }
179}186}
180#else /* BITS_PER_LONG < 64 */187#else /* BITS_PER_LONG < 64 */
181# define ktime_divns(kt, div) (u64)((kt).tv64 / (div))188static 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}
182#endif197#endif
183 198
184static inline s64 ktime_to_us(const ktime_t kt)199static 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
266/*266/*
267 * Divide a ktime value by a nanosecond value267 * Divide a ktime value by a nanosecond value
268 */268 */
269u64 __ktime_divns(const ktime_t kt, s64 div)269s64 __ktime_divns(const ktime_t kt, s64 div)
270{270{
271 u64 dclc;
272 int sft = 0;271 int sft = 0;
272 s64 dclc;
273 u64 tmp;
273 274
274 dclc = ktime_to_ns(kt);275 dclc = ktime_to_ns(kt);
276 tmp = dclc < 0 ? -dclc : dclc;
277
275 /* Make sure the divisor is less than 2^32: */278 /* Make sure the divisor is less than 2^32: */
276 while (div >> 32) {279 while (div >> 32) {
277 sft++;280 sft++;
278 div >>= 1;281 div >>= 1;
279 }282 }
280 dclc >>= sft;283 tmp >>= sft;
281 do_div(dclc, (unsigned long) div);284 do_div(tmp, (unsigned long) div);
282 285 return dclc < 0 ? -tmp : tmp;
283 return dclc;
284}286}
285EXPORT_SYMBOL_GPL(__ktime_divns);287EXPORT_SYMBOL_GPL(__ktime_divns);
286#endif /* BITS_PER_LONG >= 64 */288#endif /* BITS_PER_LONG >= 64 */