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
|
#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)
|
||||||
/*
|
/*
|
||||||
* 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 */
|
||||||
|
|
Loading…
Reference in New Issue