131 lines
4.6 KiB
Diff
131 lines
4.6 KiB
Diff
From: Anna-Maria Gleixner <anna-maria@linutronix.de>
|
|
Date: Sun, 22 Oct 2017 23:39:53 +0200
|
|
Subject: [PATCH 15/36] hrtimer: Make the remote enqueue check unconditional
|
|
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.14/older/patches-4.14.6-rt7.tar.xz
|
|
|
|
hrtimer_cpu_base.expires_next is used to cache the next event armed in the
|
|
timer hardware. The value is used to check whether an hrtimer can be
|
|
enqueued remotely. If the new hrtimer is expiring before expires_next, then
|
|
remote enqueue is not possible as the remote hrtimer hardware cannot be
|
|
accessed for reprogramming to an earlier expiry time.
|
|
|
|
The remote enqueue check is currently conditional on
|
|
CONFIG_HIGH_RES_TIMERS=y and hrtimer_cpu_base.hres_active. There is no
|
|
compelling reason to make this conditional.
|
|
|
|
Move hrtimer_cpu_base.expires_next out of the CONFIG_HIGH_RES_TIMERS=y
|
|
guarded area and remove the conditionals in hrtimer_check_target().
|
|
|
|
The check is currently a NOOP for the CONFIG_HIGH_RES_TIMERS=n and the
|
|
!hrtimer_cpu_base.hres_active case because in these cases nothing updates
|
|
hrtimer_cpu_base.expires_next yet. This will be changed with later patches
|
|
which further reduce the #ifdef zoo in this code.
|
|
|
|
Signed-off-by: Anna-Maria Gleixner <anna-maria@linutronix.de>
|
|
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
|
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
|
---
|
|
include/linux/hrtimer.h | 6 +++---
|
|
kernel/time/hrtimer.c | 26 ++++++--------------------
|
|
2 files changed, 9 insertions(+), 23 deletions(-)
|
|
|
|
--- a/include/linux/hrtimer.h
|
|
+++ b/include/linux/hrtimer.h
|
|
@@ -164,13 +164,13 @@ enum hrtimer_base_type {
|
|
* @hres_active: State of high resolution mode
|
|
* @in_hrtirq: hrtimer_interrupt() is currently executing
|
|
* @hang_detected: The last hrtimer interrupt detected a hang
|
|
- * @expires_next: absolute time of the next event, is required for remote
|
|
- * hrtimer enqueue
|
|
* @next_timer: Pointer to the first expiring timer
|
|
* @nr_events: Total number of hrtimer interrupt events
|
|
* @nr_retries: Total number of hrtimer interrupt retries
|
|
* @nr_hangs: Total number of hrtimer interrupt hangs
|
|
* @max_hang_time: Maximum time spent in hrtimer_interrupt
|
|
+ * @expires_next: absolute time of the next event, is required for remote
|
|
+ * hrtimer enqueue
|
|
* @clock_base: array of clock bases for this cpu
|
|
*
|
|
* Note: next_timer is just an optimization for __remove_hrtimer().
|
|
@@ -186,13 +186,13 @@ struct hrtimer_cpu_base {
|
|
#ifdef CONFIG_HIGH_RES_TIMERS
|
|
unsigned int in_hrtirq : 1,
|
|
hang_detected : 1;
|
|
- ktime_t expires_next;
|
|
struct hrtimer *next_timer;
|
|
unsigned int nr_events;
|
|
unsigned short nr_retries;
|
|
unsigned short nr_hangs;
|
|
unsigned int max_hang_time;
|
|
#endif
|
|
+ ktime_t expires_next;
|
|
struct hrtimer_clock_base clock_base[HRTIMER_MAX_CLOCK_BASES];
|
|
} ____cacheline_aligned;
|
|
|
|
--- a/kernel/time/hrtimer.c
|
|
+++ b/kernel/time/hrtimer.c
|
|
@@ -154,26 +154,21 @@ struct hrtimer_clock_base *lock_hrtimer_
|
|
}
|
|
|
|
/*
|
|
- * With HIGHRES=y we do not migrate the timer when it is expiring
|
|
- * before the next event on the target cpu because we cannot reprogram
|
|
- * the target cpu hardware and we would cause it to fire late.
|
|
+ * We do not migrate the timer when it is expiring before the next
|
|
+ * event on the target cpu. When high resolution is enabled, we cannot
|
|
+ * reprogram the target cpu hardware and we would cause it to fire
|
|
+ * late. To keep it simple, we handle the high resolution enabled and
|
|
+ * disabled case similar.
|
|
*
|
|
* Called with cpu_base->lock of target cpu held.
|
|
*/
|
|
static int
|
|
hrtimer_check_target(struct hrtimer *timer, struct hrtimer_clock_base *new_base)
|
|
{
|
|
-#ifdef CONFIG_HIGH_RES_TIMERS
|
|
ktime_t expires;
|
|
|
|
- if (!new_base->cpu_base->hres_active)
|
|
- return 0;
|
|
-
|
|
expires = ktime_sub(hrtimer_get_expires(timer), new_base->offset);
|
|
return expires <= new_base->cpu_base->expires_next;
|
|
-#else
|
|
- return 0;
|
|
-#endif
|
|
}
|
|
|
|
static inline
|
|
@@ -657,14 +652,6 @@ static void hrtimer_reprogram(struct hrt
|
|
}
|
|
|
|
/*
|
|
- * Initialize the high resolution related parts of cpu_base
|
|
- */
|
|
-static inline void hrtimer_init_hres(struct hrtimer_cpu_base *base)
|
|
-{
|
|
- base->expires_next = KTIME_MAX;
|
|
-}
|
|
-
|
|
-/*
|
|
* Retrigger next event is called after clock was set
|
|
*
|
|
* Called with interrupts disabled via on_each_cpu()
|
|
@@ -729,7 +716,6 @@ static inline int hrtimer_reprogram(stru
|
|
{
|
|
return 0;
|
|
}
|
|
-static inline void hrtimer_init_hres(struct hrtimer_cpu_base *base) { }
|
|
static inline void retrigger_next_event(void *arg) { }
|
|
|
|
#endif /* CONFIG_HIGH_RES_TIMERS */
|
|
@@ -1601,7 +1587,7 @@ int hrtimers_prepare_cpu(unsigned int cp
|
|
|
|
cpu_base->cpu = cpu;
|
|
cpu_base->hres_active = 0;
|
|
- hrtimer_init_hres(cpu_base);
|
|
+ cpu_base->expires_next = KTIME_MAX;
|
|
return 0;
|
|
}
|
|
|