Skip to content

Commit c5db6a3

Browse files
committed
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
2 parents 9bd4459 + f7bcb70 commit c5db6a3

File tree

2 files changed

+29
-12
lines changed

2 files changed

+29
-12
lines changed

include/linux/ktime.h

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -166,19 +166,34 @@ static inline bool ktime_before(const ktime_t cmp1, const ktime_t cmp2)
166166
}
167167

168168
#if BITS_PER_LONG < 64
169-
extern u64 __ktime_divns(const ktime_t kt, s64 div);
170-
static inline u64 ktime_divns(const ktime_t kt, s64 div)
169+
extern s64 __ktime_divns(const ktime_t kt, s64 div);
170+
static inline s64 ktime_divns(const ktime_t kt, s64 div)
171171
{
172+
/*
173+
* Negative divisors could cause an inf loop,
174+
* so bug out here.
175+
*/
176+
BUG_ON(div < 0);
172177
if (__builtin_constant_p(div) && !(div >> 32)) {
173-
u64 ns = kt.tv64;
174-
do_div(ns, div);
175-
return ns;
178+
s64 ns = kt.tv64;
179+
u64 tmp = ns < 0 ? -ns : ns;
180+
181+
do_div(tmp, div);
182+
return ns < 0 ? -tmp : tmp;
176183
} else {
177184
return __ktime_divns(kt, div);
178185
}
179186
}
180187
#else /* BITS_PER_LONG < 64 */
181-
# define ktime_divns(kt, div) (u64)((kt).tv64 / (div))
188+
static 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+
}
182197
#endif
183198

184199
static inline s64 ktime_to_us(const ktime_t kt)

kernel/time/hrtimer.c

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -266,21 +266,23 @@ lock_hrtimer_base(const struct hrtimer *timer, unsigned long *flags)
266266
/*
267267
* Divide a ktime value by a nanosecond value
268268
*/
269-
u64 __ktime_divns(const ktime_t kt, s64 div)
269+
s64 __ktime_divns(const ktime_t kt, s64 div)
270270
{
271-
u64 dclc;
272271
int sft = 0;
272+
s64 dclc;
273+
u64 tmp;
273274

274275
dclc = ktime_to_ns(kt);
276+
tmp = dclc < 0 ? -dclc : dclc;
277+
275278
/* Make sure the divisor is less than 2^32: */
276279
while (div >> 32) {
277280
sft++;
278281
div >>= 1;
279282
}
280-
dclc >>= sft;
281-
do_div(dclc, (unsigned long) div);
282-
283-
return dclc;
283+
tmp >>= sft;
284+
do_div(tmp, (unsigned long) div);
285+
return dclc < 0 ? -tmp : tmp;
284286
}
285287
EXPORT_SYMBOL_GPL(__ktime_divns);
286288
#endif /* BITS_PER_LONG >= 64 */

0 commit comments

Comments
 (0)