mirror of
https://github.com/torvalds/linux.git
synced 2024-12-29 06:12:08 +00:00
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
This commit is contained in:
commit
c5db6a3bde
@ -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)
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user