Skip to content

Commit

Permalink
Merge branch 'timers-urgent-for-linus' of git://git.kernel.org/pub/sc…
Browse files Browse the repository at this point in the history
…m/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
  • Loading branch information
torvalds committed May 24, 2015
2 parents 9bd4459 + f7bcb70 commit c5db6a3
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 12 deletions.
27 changes: 21 additions & 6 deletions include/linux/ktime.h
Original file line number Diff line number Diff line change
Expand Up @@ -166,19 +166,34 @@ static inline bool ktime_before(const ktime_t cmp1, const ktime_t cmp2)
}

#if BITS_PER_LONG < 64
extern u64 __ktime_divns(const ktime_t kt, s64 div);
static inline u64 ktime_divns(const ktime_t kt, s64 div)
extern s64 __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)) {
u64 ns = kt.tv64;
do_div(ns, div);
return ns;
s64 ns = kt.tv64;
u64 tmp = ns < 0 ? -ns : ns;

do_div(tmp, div);
return ns < 0 ? -tmp : tmp;
} else {
return __ktime_divns(kt, div);
}
}
#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

static inline s64 ktime_to_us(const ktime_t kt)
Expand Down
14 changes: 8 additions & 6 deletions kernel/time/hrtimer.c
Original file line number Diff line number Diff line change
Expand Up @@ -266,21 +266,23 @@ lock_hrtimer_base(const struct hrtimer *timer, unsigned long *flags)
/*
* 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;
s64 dclc;
u64 tmp;

dclc = ktime_to_ns(kt);
tmp = dclc < 0 ? -dclc : dclc;

/* Make sure the divisor is less than 2^32: */
while (div >> 32) {
sft++;
div >>= 1;
}
dclc >>= sft;
do_div(dclc, (unsigned long) div);

return dclc;
tmp >>= sft;
do_div(tmp, (unsigned long) div);
return dclc < 0 ? -tmp : tmp;
}
EXPORT_SYMBOL_GPL(__ktime_divns);
#endif /* BITS_PER_LONG >= 64 */
Expand Down

0 comments on commit c5db6a3

Please sign in to comment.