Forráskód Böngészése

hrtimer: Make the remote enqueue check unconditional

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>
Cc: Christoph Hellwig <hch@lst.de>
Cc: John Stultz <john.stultz@linaro.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: keescook@chromium.org
Link: http://lkml.kernel.org/r/20171221104205.7269-16-anna-maria@linutronix.de
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Anna-Maria Gleixner 7 éve
szülő
commit
07a9a7eae8
2 módosított fájl, 9 hozzáadás és 23 törlés
  1. 3 3
      include/linux/hrtimer.h
  2. 6 20
      kernel/time/hrtimer.c

+ 3 - 3
include/linux/hrtimer.h

@@ -164,13 +164,13 @@ enum  hrtimer_base_type {
  * @hres_active:	State of high resolution mode
  * @hres_active:	State of high resolution mode
  * @in_hrtirq:		hrtimer_interrupt() is currently executing
  * @in_hrtirq:		hrtimer_interrupt() is currently executing
  * @hang_detected:	The last hrtimer interrupt detected a hang
  * @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
  * @next_timer:		Pointer to the first expiring timer
  * @nr_events:		Total number of hrtimer interrupt events
  * @nr_events:		Total number of hrtimer interrupt events
  * @nr_retries:		Total number of hrtimer interrupt retries
  * @nr_retries:		Total number of hrtimer interrupt retries
  * @nr_hangs:		Total number of hrtimer interrupt hangs
  * @nr_hangs:		Total number of hrtimer interrupt hangs
  * @max_hang_time:	Maximum time spent in hrtimer_interrupt
  * @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
  * @clock_base:		array of clock bases for this cpu
  *
  *
  * Note: next_timer is just an optimization for __remove_hrtimer().
  * Note: next_timer is just an optimization for __remove_hrtimer().
@@ -186,13 +186,13 @@ struct hrtimer_cpu_base {
 #ifdef CONFIG_HIGH_RES_TIMERS
 #ifdef CONFIG_HIGH_RES_TIMERS
 	unsigned int			in_hrtirq	: 1,
 	unsigned int			in_hrtirq	: 1,
 					hang_detected	: 1;
 					hang_detected	: 1;
-	ktime_t				expires_next;
 	struct hrtimer			*next_timer;
 	struct hrtimer			*next_timer;
 	unsigned int			nr_events;
 	unsigned int			nr_events;
 	unsigned short			nr_retries;
 	unsigned short			nr_retries;
 	unsigned short			nr_hangs;
 	unsigned short			nr_hangs;
 	unsigned int			max_hang_time;
 	unsigned int			max_hang_time;
 #endif
 #endif
+	ktime_t				expires_next;
 	struct hrtimer_clock_base	clock_base[HRTIMER_MAX_CLOCK_BASES];
 	struct hrtimer_clock_base	clock_base[HRTIMER_MAX_CLOCK_BASES];
 } ____cacheline_aligned;
 } ____cacheline_aligned;
 
 

+ 6 - 20
kernel/time/hrtimer.c

@@ -154,26 +154,21 @@ struct hrtimer_clock_base *lock_hrtimer_base(const struct hrtimer *timer,
 }
 }
 
 
 /*
 /*
- * 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.
  * Called with cpu_base->lock of target cpu held.
  */
  */
 static int
 static int
 hrtimer_check_target(struct hrtimer *timer, struct hrtimer_clock_base *new_base)
 hrtimer_check_target(struct hrtimer *timer, struct hrtimer_clock_base *new_base)
 {
 {
-#ifdef CONFIG_HIGH_RES_TIMERS
 	ktime_t expires;
 	ktime_t expires;
 
 
-	if (!new_base->cpu_base->hres_active)
-		return 0;
-
 	expires = ktime_sub(hrtimer_get_expires(timer), new_base->offset);
 	expires = ktime_sub(hrtimer_get_expires(timer), new_base->offset);
 	return expires <= new_base->cpu_base->expires_next;
 	return expires <= new_base->cpu_base->expires_next;
-#else
-	return 0;
-#endif
 }
 }
 
 
 static inline
 static inline
@@ -656,14 +651,6 @@ static void hrtimer_reprogram(struct hrtimer *timer,
 	tick_program_event(expires, 1);
 	tick_program_event(expires, 1);
 }
 }
 
 
-/*
- * 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
  * Retrigger next event is called after clock was set
  *
  *
@@ -729,7 +716,6 @@ static inline int hrtimer_reprogram(struct hrtimer *timer,
 {
 {
 	return 0;
 	return 0;
 }
 }
-static inline void hrtimer_init_hres(struct hrtimer_cpu_base *base) { }
 static inline void retrigger_next_event(void *arg) { }
 static inline void retrigger_next_event(void *arg) { }
 
 
 #endif /* CONFIG_HIGH_RES_TIMERS */
 #endif /* CONFIG_HIGH_RES_TIMERS */
@@ -1599,7 +1585,7 @@ int hrtimers_prepare_cpu(unsigned int cpu)
 
 
 	cpu_base->cpu = cpu;
 	cpu_base->cpu = cpu;
 	cpu_base->hres_active = 0;
 	cpu_base->hres_active = 0;
-	hrtimer_init_hres(cpu_base);
+	cpu_base->expires_next = KTIME_MAX;
 	return 0;
 	return 0;
 }
 }