Commit c5db6a3b authored by Linus Torvalds's avatar Linus Torvalds

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
parents 9bd4459a f7bcb70e
...@@ -166,19 +166,34 @@ static inline bool ktime_before(const ktime_t cmp1, const ktime_t cmp2) ...@@ -166,19 +166,34 @@ static inline bool ktime_before(const ktime_t cmp1, const ktime_t cmp2)
} }
#if BITS_PER_LONG < 64 #if BITS_PER_LONG < 64
extern u64 __ktime_divns(const ktime_t kt, s64 div); extern s64 __ktime_divns(const ktime_t kt, s64 div);
static inline u64 ktime_divns(const ktime_t kt, s64 div) static inline s64 ktime_divns(const ktime_t kt, s64 div)
{ {
/*
* Negative divisors could cause an inf loop,
* so bug out here.
*/
BUG_ON(div < 0);
if (__builtin_constant_p(div) && !(div >> 32)) { if (__builtin_constant_p(div) && !(div >> 32)) {
u64 ns = kt.tv64; s64 ns = kt.tv64;
do_div(ns, div); u64 tmp = ns < 0 ? -ns : ns;
return ns;
do_div(tmp, div);
return ns < 0 ? -tmp : tmp;
} else { } else {
return __ktime_divns(kt, div); return __ktime_divns(kt, div);
} }
} }
#else /* BITS_PER_LONG < 64 */ #else /* BITS_PER_LONG < 64 */
# define ktime_divns(kt, div) (u64)((kt).tv64 / (div)) static inline s64 ktime_divns(const ktime_t kt, s64 div)
{
/*
* 32-bit implementation cannot handle negative divisors,
* so catch them on 64bit as well.
*/
WARN_ON(div < 0);
return kt.tv64 / div;
}
#endif #endif
static inline s64 ktime_to_us(const ktime_t kt) static inline s64 ktime_to_us(const ktime_t kt)
......
...@@ -266,21 +266,23 @@ lock_hrtimer_base(const struct hrtimer *timer, unsigned long *flags) ...@@ -266,21 +266,23 @@ lock_hrtimer_base(const struct hrtimer *timer, unsigned long *flags)
/* /*
* Divide a ktime value by a nanosecond value * Divide a ktime value by a nanosecond value
*/ */
u64 __ktime_divns(const ktime_t kt, s64 div) s64 __ktime_divns(const ktime_t kt, s64 div)
{ {
u64 dclc;
int sft = 0; int sft = 0;
s64 dclc;
u64 tmp;
dclc = ktime_to_ns(kt); dclc = ktime_to_ns(kt);
tmp = dclc < 0 ? -dclc : dclc;
/* Make sure the divisor is less than 2^32: */ /* Make sure the divisor is less than 2^32: */
while (div >> 32) { while (div >> 32) {
sft++; sft++;
div >>= 1; div >>= 1;
} }
dclc >>= sft; tmp >>= sft;
do_div(dclc, (unsigned long) div); do_div(tmp, (unsigned long) div);
return dclc < 0 ? -tmp : tmp;
return dclc;
} }
EXPORT_SYMBOL_GPL(__ktime_divns); EXPORT_SYMBOL_GPL(__ktime_divns);
#endif /* BITS_PER_LONG >= 64 */ #endif /* BITS_PER_LONG >= 64 */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment