linux-pm.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Thomas Gleixner <tglx@linutronix.de>
To: LKML <linux-kernel@vger.kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>,
	John Stultz <john.stultz@linaro.org>,
	Eric Dumazet <edumazet@google.com>,
	Anna-Maria Gleixner <anna-maria@linutronix.de>,
	"Rafael J. Wysocki" <rafael.j.wysocki@intel.com>,
	linux-pm@vger.kernel.org, Arjan van de Ven <arjan@infradead.org>,
	"Paul E. McKenney" <paulmck@linux.vnet.ibm.com>,
	Frederic Weisbecker <fweisbec@gmail.com>,
	Rik van Riel <riel@redhat.com>,
	Richard Cochran <rcochran@linutronix.de>
Subject: [patch V2 05/10] timer: Retrieve next expiry of pinned/non-pinned timers seperately
Date: Tue, 18 Apr 2017 13:11:07 +0200	[thread overview]
Message-ID: <20170418111400.778021491@linutronix.de> (raw)
In-Reply-To: 20170418111102.490432548@linutronix.de

[-- Attachment #1: timer_Provide_both_pinned_and_movable_expiration_times.patch --]
[-- Type: text/plain, Size: 4686 bytes --]

To prepare for the conversion of the NOHZ timer placement to a pull at
expiry time model it's required to have seperate expiry times for the
pinned and the non-pinned (movable) timers.

No functional change

Signed-off-by: Richard Cochran <rcochran@linutronix.de>
Signed-off-by: Anna-Maria Gleixner <anna-maria@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

---
 kernel/time/tick-internal.h |    3 ++-
 kernel/time/tick-sched.c    |   10 ++++++----
 kernel/time/timer.c         |   41 +++++++++++++++++++++++++++++++++++------
 3 files changed, 43 insertions(+), 11 deletions(-)

--- a/kernel/time/tick-internal.h
+++ b/kernel/time/tick-internal.h
@@ -163,5 +163,6 @@ static inline void timers_update_migrati
 
 DECLARE_PER_CPU(struct hrtimer_cpu_base, hrtimer_bases);
 
-extern u64 get_next_timer_interrupt(unsigned long basej, u64 basem);
+extern u64 get_next_timer_interrupt(unsigned long basej, u64 basem,
+				    u64 *global_evt);
 void timer_clear_idle(void);
--- a/kernel/time/tick-sched.c
+++ b/kernel/time/tick-sched.c
@@ -666,7 +666,7 @@ static ktime_t tick_nohz_stop_sched_tick
 					 ktime_t now, int cpu)
 {
 	struct clock_event_device *dev = __this_cpu_read(tick_cpu_device.evtdev);
-	u64 basemono, next_tick, next_tmr, next_rcu, delta, expires;
+	u64 basemono, next_tick, next_local, next_global, next_rcu, delta, expires;
 	unsigned long seq, basejiff;
 	ktime_t	tick;
 
@@ -689,10 +689,12 @@ static ktime_t tick_nohz_stop_sched_tick
 		 * disabled this also looks at the next expiring
 		 * hrtimer.
 		 */
-		next_tmr = get_next_timer_interrupt(basejiff, basemono);
-		ts->next_timer = next_tmr;
+		next_local = get_next_timer_interrupt(basejiff, basemono,
+						      &next_global);
+		next_local = min(next_local, next_global);
+		ts->next_timer = next_local;
 		/* Take the next rcu event into account */
-		next_tick = next_rcu < next_tmr ? next_rcu : next_tmr;
+		next_tick = next_rcu < next_local ? next_rcu : next_local;
 	}
 
 	/*
--- a/kernel/time/timer.c
+++ b/kernel/time/timer.c
@@ -1472,23 +1472,27 @@ static u64 cmp_next_hrtimer_event(u64 ba
  * get_next_timer_interrupt - return the time (clock mono) of the next timer
  * @basej:	base time jiffies
  * @basem:	base time clock monotonic
+ * @global_evt:	Pointer to store the expiry time of the next global timer
  *
  * Returns the tick aligned clock monotonic time of the next pending
  * timer or KTIME_MAX if no timer is pending.
  */
-u64 get_next_timer_interrupt(unsigned long basej, u64 basem)
+u64 get_next_timer_interrupt(unsigned long basej, u64 basem, u64 *global_evt)
 {
 	unsigned long nextevt, nextevt_local, nextevt_global;
 	bool local_empty, global_empty, local_first, is_idle;
 	struct timer_base *base_local, *base_global;
-	u64 expires = KTIME_MAX;
+	u64 local_evt = KTIME_MAX;
+
+	/* Preset global event */
+	*global_evt = KTIME_MAX;
 
 	/*
 	 * Pretend that there is no timer pending if the cpu is offline.
 	 * Possible pending timers will be migrated later to an active cpu.
 	 */
 	if (cpu_is_offline(smp_processor_id()))
-		return expires;
+		return local_evt;
 
 	base_local = this_cpu_ptr(&timer_bases[BASE_LOCAL]);
 	base_global = this_cpu_ptr(&timer_bases[BASE_GLOBAL]);
@@ -1532,14 +1536,39 @@ u64 get_next_timer_interrupt(unsigned lo
 	spin_unlock(&base_local->lock);
 	spin_unlock(&base_global->lock);
 
-	if (!local_empty || !global_empty) {
+	/*
+	 * If the bases are not marked idle, i.e one of the events is at
+	 * max. one tick away, use the next event for calculating next
+	 * local expiry value. The next global event is left as KTIME_MAX,
+	 * so this CPU will not queue itself in the global expiry
+	 * mechanism.
+	 */
+	if (!is_idle) {
 		/* If we missed a tick already, force 0 delta */
 		if (time_before_eq(nextevt, basej))
 			nextevt = basej;
-		expires = basem + (nextevt - basej) * TICK_NSEC;
+		local_evt = basem + (nextevt - basej) * TICK_NSEC;
+		return cmp_next_hrtimer_event(basem, local_evt);
 	}
 
-	return cmp_next_hrtimer_event(basem, expires);
+	/*
+	 * If the bases are marked idle, i.e. the next event on both the
+	 * local and the global queue are farther away than a tick,
+	 * evaluate both bases. No need to check whether one of the bases
+	 * has an already expired timer as this is caught by the !is_idle
+	 * condition above.
+	 */
+	if (!local_empty)
+		local_evt = basem + (nextevt_local - basej) * TICK_NSEC;
+
+	/*
+	 * If the local queue expires first, there is no requirement for
+	 * queuing the CPU in the global expiry mechanism.
+	 */
+	if (!local_first && !global_empty)
+		*global_evt = basem + (nextevt_global - basej) * TICK_NSEC;
+
+	return cmp_next_hrtimer_event(basem, local_evt);
 }
 
 /**

  parent reply	other threads:[~2017-04-18 16:43 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-04-18 11:11 [patch V2 00/10] timer: Move from a push remote at enqueue to a pull at expiry model Thomas Gleixner
2017-04-18 11:11 ` [patch V2 01/10] timer: Invoke timer_start_debug() where it makes sense Thomas Gleixner
2017-04-18 11:11 ` [patch V2 02/10] timerqueue: Document return values of timerqueue_add/del() Thomas Gleixner
2017-04-18 11:11 ` [patch V2 03/10] timers: Rework idle logic Thomas Gleixner
2017-04-19  6:50   ` Peter Zijlstra
2017-04-21 14:43     ` Frederic Weisbecker
2017-04-18 11:11 ` [patch V2 04/10] timer: Keep the pinned timers separate from the others Thomas Gleixner
2017-04-18 11:11 ` Thomas Gleixner [this message]
2017-04-19  7:05   ` [patch V2 05/10] timer: Retrieve next expiry of pinned/non-pinned timers seperately Peter Zijlstra
2017-04-19  9:56     ` Thomas Gleixner
2017-04-18 11:11 ` [patch V2 06/10] timer: Restructure internal locking Thomas Gleixner
2017-04-19  7:07   ` Peter Zijlstra
2017-04-18 11:11 ` [patch V2 07/10] tick/sched: Split out jiffies update helper function Thomas Gleixner
2017-04-18 11:11 ` [patch V2 08/10] timer: Implement the hierarchical pull model Thomas Gleixner
2017-04-19  7:20   ` Peter Zijlstra
2017-04-19  7:24   ` Peter Zijlstra
2017-04-19  7:34   ` Peter Zijlstra
2017-04-19  7:38   ` Peter Zijlstra
2017-04-19  8:11   ` Peter Zijlstra
2017-04-19  8:31     ` Thomas Gleixner
2017-04-19  8:36       ` Peter Zijlstra
2017-04-19  9:03         ` Thomas Gleixner
2017-04-19  8:52   ` Peter Zijlstra
2017-04-19  9:09   ` Peter Zijlstra
2017-04-19  9:43     ` Thomas Gleixner
2017-04-19  9:52       ` Peter Zijlstra
2017-04-19  9:44     ` Peter Zijlstra
2017-04-19  9:53       ` Peter Zijlstra
2017-04-19  9:20   ` Peter Zijlstra
2017-04-19 10:22   ` Peter Zijlstra
2017-04-18 11:11 ` [patch V2 09/10] timer_migration: Add tracepoints Thomas Gleixner
2017-04-18 11:11 ` [patch V2 10/10] timer: Always queue timers on the local CPU Thomas Gleixner
2017-04-21 19:28 ` [patch V2 00/10] timer: Move from a push remote at enqueue to a pull at expiry model Paul E. McKenney

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170418111400.778021491@linutronix.de \
    --to=tglx@linutronix.de \
    --cc=anna-maria@linutronix.de \
    --cc=arjan@infradead.org \
    --cc=edumazet@google.com \
    --cc=fweisbec@gmail.com \
    --cc=john.stultz@linaro.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pm@vger.kernel.org \
    --cc=paulmck@linux.vnet.ibm.com \
    --cc=peterz@infradead.org \
    --cc=rafael.j.wysocki@intel.com \
    --cc=rcochran@linutronix.de \
    --cc=riel@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).