|
@@ -325,6 +325,23 @@ u64 ktime_divns(const ktime_t kt, s64 div)
|
|
|
}
|
|
|
#endif /* BITS_PER_LONG >= 64 */
|
|
|
|
|
|
+/*
|
|
|
+ * Add two ktime values and do a safety check for overflow:
|
|
|
+ */
|
|
|
+ktime_t ktime_add_safe(const ktime_t lhs, const ktime_t rhs)
|
|
|
+{
|
|
|
+ ktime_t res = ktime_add(lhs, rhs);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * We use KTIME_SEC_MAX here, the maximum timeout which we can
|
|
|
+ * return to user space in a timespec:
|
|
|
+ */
|
|
|
+ if (res.tv64 < 0 || res.tv64 < lhs.tv64 || res.tv64 < rhs.tv64)
|
|
|
+ res = ktime_set(KTIME_SEC_MAX, 0);
|
|
|
+
|
|
|
+ return res;
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* Check, whether the timer is on the callback pending list
|
|
|
*/
|
|
@@ -682,13 +699,7 @@ u64 hrtimer_forward(struct hrtimer *timer, ktime_t now, ktime_t interval)
|
|
|
*/
|
|
|
orun++;
|
|
|
}
|
|
|
- timer->expires = ktime_add(timer->expires, interval);
|
|
|
- /*
|
|
|
- * Make sure, that the result did not wrap with a very large
|
|
|
- * interval.
|
|
|
- */
|
|
|
- if (timer->expires.tv64 < 0)
|
|
|
- timer->expires = ktime_set(KTIME_SEC_MAX, 0);
|
|
|
+ timer->expires = ktime_add_safe(timer->expires, interval);
|
|
|
|
|
|
return orun;
|
|
|
}
|
|
@@ -839,7 +850,7 @@ hrtimer_start(struct hrtimer *timer, ktime_t tim, const enum hrtimer_mode mode)
|
|
|
new_base = switch_hrtimer_base(timer, base);
|
|
|
|
|
|
if (mode == HRTIMER_MODE_REL) {
|
|
|
- tim = ktime_add(tim, new_base->get_time());
|
|
|
+ tim = ktime_add_safe(tim, new_base->get_time());
|
|
|
/*
|
|
|
* CONFIG_TIME_LOW_RES is a temporary way for architectures
|
|
|
* to signal that they simply return xtime in
|
|
@@ -848,16 +859,8 @@ hrtimer_start(struct hrtimer *timer, ktime_t tim, const enum hrtimer_mode mode)
|
|
|
* timeouts. This will go away with the GTOD framework.
|
|
|
*/
|
|
|
#ifdef CONFIG_TIME_LOW_RES
|
|
|
- tim = ktime_add(tim, base->resolution);
|
|
|
+ tim = ktime_add_safe(tim, base->resolution);
|
|
|
#endif
|
|
|
- /*
|
|
|
- * Careful here: User space might have asked for a
|
|
|
- * very long sleep, so the add above might result in a
|
|
|
- * negative number, which enqueues the timer in front
|
|
|
- * of the queue.
|
|
|
- */
|
|
|
- if (tim.tv64 < 0)
|
|
|
- tim.tv64 = KTIME_MAX;
|
|
|
}
|
|
|
timer->expires = tim;
|
|
|
|