xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
From: Dario Faggioli <dario.faggioli@citrix.com>
To: xen-devel@lists.xenproject.org
Cc: Stefano Stabellini <sstabellini@kernel.org>,
	George Dunlap <George.Dunlap@eu.citrix.com>,
	Andrew Cooper <andrew.cooper3@citrix.com>,
	Tim Deegan <tim@xen.org>, Julien Grall <julien.grall@arm.com>,
	Jan Beulich <jbeulich@suse.com>
Subject: [PATCH v2 1/3] xen: RCU: let the RCU idle timer handler run
Date: Thu, 28 Sep 2017 12:15:59 +0200	[thread overview]
Message-ID: <150659375919.4057.11728919580033384187.stgit@Solace.fritz.box> (raw)
In-Reply-To: <150659250903.4057.6425247157210641083.stgit@Solace.fritz.box>

If stop_timer() is called between when the RCU
idle timer's interrupt arrives (and TIMER_SOFTIRQ is
raised) and when softirqs are checked and handled, the
timer is deactivated, and the handler never runs.

This happens to the RCU idle timer because stop_timer()
is called on it during the wakeup from idle (e.g., C-states,
on x86) path.

To fix that, we avoid calling stop_timer(), in case we see
that the timer itself is:
- still active,
- expired (i.e., it's expiry time is in the past).
In fact, that indicates (for this particular timer) that
it has fired, and we are just about to handle the TIMER_SOFTIRQ
(which will perform the timer deactivation and run its handler).

Signed-off-by: Dario Faggioli <dario.faggioli@citrix.com>
---
Cc: Andrew Cooper <andrew.cooper3@citrix.com>
Cc: George Dunlap <George.Dunlap@eu.citrix.com>
Cc: Jan Beulich <jbeulich@suse.com>
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Julien Grall <julien.grall@arm.com>
Cc: Tim Deegan <tim@xen.org>
---
Changes from v1:
- logic changed completely: instead of avoiding deactivate_timer() in
  stop_timer(), we avoid stop_timer() in rcu_idle_timer_stop() (if
  appropriate, of course).
---
 xen/common/rcupdate.c   |   16 +++++++++++++++-
 xen/common/timer.c      |   17 +++++++++++++++++
 xen/include/xen/timer.h |    3 +++
 3 files changed, 35 insertions(+), 1 deletion(-)

diff --git a/xen/common/rcupdate.c b/xen/common/rcupdate.c
index 871936f..4a02cdd 100644
--- a/xen/common/rcupdate.c
+++ b/xen/common/rcupdate.c
@@ -465,7 +465,21 @@ void rcu_idle_timer_stop()
         return;
 
     rdp->idle_timer_active = false;
-    stop_timer(&rdp->idle_timer);
+
+    /*
+     * In general, as the CPU is becoming active again, we don't need the
+     * idle timer, and so we want to stop it.
+     *
+     * However, in case we are here because idle_timer has (just) fired and
+     * has woken up the CPU, we skip stop_timer() now. In fact, if we stop
+     * it, then the TIMER_SOFTIRQ handler wouldn't find idle_timer among the
+     * active timers any longer, and hence won't call rcu_idle_timer_handler().
+     *
+     * Therefore, if we see that the timer is expired already, leave it alone.
+     * It will be finally deactiveted by the TIMER_SOFTIRQ handler.
+     */
+    if ( !timer_is_expired(&rdp->idle_timer, NOW()) )
+        stop_timer(&rdp->idle_timer);
 }
 
 static void rcu_idle_timer_handler(void* data)
diff --git a/xen/common/timer.c b/xen/common/timer.c
index d9ff669..a768aa3 100644
--- a/xen/common/timer.c
+++ b/xen/common/timer.c
@@ -332,6 +332,23 @@ void stop_timer(struct timer *timer)
 }
 
 
+bool timer_is_expired(struct timer *timer, s_time_t now)
+{
+    unsigned long flags;
+    bool ret = false;
+
+    if ( !timer_lock_irqsave(timer, flags) )
+        return ret;
+
+    if ( active_timer(timer) && timer->expires <= now )
+        ret = true;
+
+    timer_unlock_irqrestore(timer, flags);
+
+    return ret;
+}
+
+
 void migrate_timer(struct timer *timer, unsigned int new_cpu)
 {
     unsigned int old_cpu;
diff --git a/xen/include/xen/timer.h b/xen/include/xen/timer.h
index 9531800..a095007 100644
--- a/xen/include/xen/timer.h
+++ b/xen/include/xen/timer.h
@@ -70,6 +70,9 @@ void set_timer(struct timer *timer, s_time_t expires);
  */
 void stop_timer(struct timer *timer);
 
+/* True if a timer is active, but with its expiry time before now. */
+bool timer_is_expired(struct timer *timer, s_time_t now);
+
 /* Migrate a timer to a different CPU. The timer may be currently active. */
 void migrate_timer(struct timer *timer, unsigned int new_cpu);
 


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

  reply	other threads:[~2017-09-28 10:16 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-09-28 10:15 [PATCH v2 0/3] xen: RCU: Improve the idle timer handling Dario Faggioli
2017-09-28 10:15 ` Dario Faggioli [this message]
2017-09-28 12:59   ` [PATCH v2 1/3] xen: RCU: let the RCU idle timer handler run Jan Beulich
2017-09-28 14:08     ` Dario Faggioli
2017-09-28 15:35       ` Jan Beulich
2017-09-28 10:16 ` [PATCH v2 2/3] xen: RCU: make the period of the idle timer configurable Dario Faggioli
2017-09-28 13:06   ` Jan Beulich
2017-09-28 14:58     ` Dario Faggioli
2017-09-28 15:35       ` Jan Beulich
2017-09-28 17:16     ` Dario Faggioli
2017-10-04  5:45       ` Jan Beulich
2017-09-28 10:16 ` [PATCH v2 3/3] xen: RCU: make the period of the idle timer adaptive Dario Faggioli
2017-09-28 13:08   ` Jan Beulich

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=150659375919.4057.11728919580033384187.stgit@Solace.fritz.box \
    --to=dario.faggioli@citrix.com \
    --cc=George.Dunlap@eu.citrix.com \
    --cc=andrew.cooper3@citrix.com \
    --cc=jbeulich@suse.com \
    --cc=julien.grall@arm.com \
    --cc=sstabellini@kernel.org \
    --cc=tim@xen.org \
    --cc=xen-devel@lists.xenproject.org \
    /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).