qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Paolo Bonzini <pbonzini@redhat.com>
To: qemu-devel@nongnu.org
Cc: Artem Pisarenko <artem.k.pisarenko@gmail.com>
Subject: [Qemu-devel] [PULL 04/48] qemu-timer: avoid checkpoints for virtual clock timers in external subsystems
Date: Thu, 18 Oct 2018 22:31:31 +0200	[thread overview]
Message-ID: <1539894735-14232-5-git-send-email-pbonzini@redhat.com> (raw)
In-Reply-To: <1539894735-14232-1-git-send-email-pbonzini@redhat.com>

From: Artem Pisarenko <artem.k.pisarenko@gmail.com>

Adds EXTERNAL attribute definition to qemu timers subsystem and assigns
it to virtual clock timers, used in slirp (ICMP IPv6) and ui (key queue).
Virtual clock processing in rr mode can use this attribute instead of a
separate clock type.

Fixes: 87f4fe7653baf55b5c2f2753fe6003f473c07342
Fixes: 775a412bf83f6bc0c5c02091ee06cf649b34c593
Fixes: 9888091404a702d7ec79d51b088d994b9fc121bd
Signed-off-by: Artem Pisarenko <artem.k.pisarenko@gmail.com>
Message-Id: <e771f96ab94e86b54b9a783c974f2af3009fe5d1.1539764043.git.artem.k.pisarenko@gmail.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 include/qemu/timer.h | 10 +++++++++-
 slirp/ip6_icmp.c     |  4 +++-
 ui/input.c           |  5 +++--
 util/qemu-timer.c    | 50 +++++++++++++++++++++++++++++++++++++++++++-------
 4 files changed, 58 insertions(+), 11 deletions(-)

diff --git a/include/qemu/timer.h b/include/qemu/timer.h
index 8ff1092..9f37c92 100644
--- a/include/qemu/timer.h
+++ b/include/qemu/timer.h
@@ -60,9 +60,17 @@ typedef enum {
  * Each attribute corresponds to one bit. Attributes modify the processing
  * of timers when they fire.
  *
- * No attributes defined currently.
+ * The following attributes are available:
+ *
+ * QEMU_TIMER_ATTR_EXTERNAL: drives external subsystem
+ *
+ * Timers with this attribute do not recorded in rr mode, therefore it could be
+ * used for the subsystems that operate outside the guest core. Applicable only
+ * with virtual clock type.
  */
 
+#define QEMU_TIMER_ATTR_EXTERNAL BIT(0)
+
 typedef struct QEMUTimerList QEMUTimerList;
 
 struct QEMUTimerListGroup {
diff --git a/slirp/ip6_icmp.c b/slirp/ip6_icmp.c
index ee333d0..cd1e0b9 100644
--- a/slirp/ip6_icmp.c
+++ b/slirp/ip6_icmp.c
@@ -27,7 +27,9 @@ void icmp6_init(Slirp *slirp)
         return;
     }
 
-    slirp->ra_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, ra_timer_handler, slirp);
+    slirp->ra_timer = timer_new_full(NULL, QEMU_CLOCK_VIRTUAL,
+                                     SCALE_MS, QEMU_TIMER_ATTR_EXTERNAL,
+                                     ra_timer_handler, slirp);
     timer_mod(slirp->ra_timer,
               qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + NDP_Interval);
 }
diff --git a/ui/input.c b/ui/input.c
index 51b1019..7c9a410 100644
--- a/ui/input.c
+++ b/ui/input.c
@@ -448,8 +448,9 @@ void qemu_input_event_send_key_delay(uint32_t delay_ms)
     }
 
     if (!kbd_timer) {
-        kbd_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, qemu_input_queue_process,
-                                 &kbd_queue);
+        kbd_timer = timer_new_full(NULL, QEMU_CLOCK_VIRTUAL,
+                                   SCALE_MS, QEMU_TIMER_ATTR_EXTERNAL,
+                                   qemu_input_queue_process, &kbd_queue);
     }
     if (queue_count < queue_limit) {
         qemu_input_queue_delay(&kbd_queue, kbd_timer,
diff --git a/util/qemu-timer.c b/util/qemu-timer.c
index 04527a3..1cc1b2f 100644
--- a/util/qemu-timer.c
+++ b/util/qemu-timer.c
@@ -489,6 +489,7 @@ bool timerlist_run_timers(QEMUTimerList *timer_list)
     bool progress = false;
     QEMUTimerCB *cb;
     void *opaque;
+    bool need_replay_checkpoint = false;
 
     if (!atomic_read(&timer_list->active_timers)) {
         return false;
@@ -504,8 +505,15 @@ bool timerlist_run_timers(QEMUTimerList *timer_list)
         break;
     default:
     case QEMU_CLOCK_VIRTUAL:
-        if (!replay_checkpoint(CHECKPOINT_CLOCK_VIRTUAL)) {
-            goto out;
+        if (replay_mode != REPLAY_MODE_NONE) {
+            /* Checkpoint for virtual clock is redundant in cases where
+             * it's being triggered with only non-EXTERNAL timers, because
+             * these timers don't change guest state directly.
+             * Since it has conditional dependence on specific timers, it is
+             * subject to race conditions and requires special handling.
+             * See below.
+             */
+            need_replay_checkpoint = true;
         }
         break;
     case QEMU_CLOCK_HOST:
@@ -520,14 +528,39 @@ bool timerlist_run_timers(QEMUTimerList *timer_list)
         break;
     }
 
+    /*
+     * Extract expired timers from active timers list and and process them.
+     *
+     * In rr mode we need "filtered" checkpointing for virtual clock.  The
+     * checkpoint must be recorded/replayed before processing any non-EXTERNAL timer,
+     * and that must only be done once since the clock value stays the same. Because
+     * non-EXTERNAL timers may appear in the timers list while it being processed,
+     * the checkpoint can be issued at a time until no timers are left and we are
+     * done".
+     */
     current_time = qemu_clock_get_ns(timer_list->clock->type);
-    for(;;) {
-        qemu_mutex_lock(&timer_list->active_timers_lock);
-        ts = timer_list->active_timers;
+    qemu_mutex_lock(&timer_list->active_timers_lock);
+    while ((ts = timer_list->active_timers)) {
         if (!timer_expired_ns(ts, current_time)) {
-            qemu_mutex_unlock(&timer_list->active_timers_lock);
+            /* No expired timers left.  The checkpoint can be skipped
+             * if no timers fired or they were all external.
+             */
             break;
         }
+        if (need_replay_checkpoint
+                && !(ts->attributes & QEMU_TIMER_ATTR_EXTERNAL)) {
+            /* once we got here, checkpoint clock only once */
+            need_replay_checkpoint = false;
+            qemu_mutex_unlock(&timer_list->active_timers_lock);
+            if (!replay_checkpoint(CHECKPOINT_CLOCK_VIRTUAL)) {
+                goto out;
+            }
+            qemu_mutex_lock(&timer_list->active_timers_lock);
+            /* The lock was released; start over again in case the list was
+             * modified.
+             */
+            continue;
+        }
 
         /* remove timer from the list before calling the callback */
         timer_list->active_timers = ts->next;
@@ -535,12 +568,15 @@ bool timerlist_run_timers(QEMUTimerList *timer_list)
         ts->expire_time = -1;
         cb = ts->cb;
         opaque = ts->opaque;
-        qemu_mutex_unlock(&timer_list->active_timers_lock);
 
         /* run the callback (the timer list can be modified) */
+        qemu_mutex_unlock(&timer_list->active_timers_lock);
         cb(opaque);
+        qemu_mutex_lock(&timer_list->active_timers_lock);
+
         progress = true;
     }
+    qemu_mutex_unlock(&timer_list->active_timers_lock);
 
 out:
     qemu_event_set(&timer_list->timers_done_ev);
-- 
1.8.3.1

  parent reply	other threads:[~2018-10-18 20:32 UTC|newest]

Thread overview: 57+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-10-18 20:31 [Qemu-devel] [PULL 00/48] Miscellaneous patches for 2018-10-18 Paolo Bonzini
2018-10-18 20:31 ` [Qemu-devel] [PULL 01/48] es1370: more fixes for ADC_FRAMEADR and ADC_FRAMECNT Paolo Bonzini
2018-10-18 20:31 ` [Qemu-devel] [PULL 02/48] Revert some patches from recent [PATCH v6] "Fixing record/replay and adding reverse debugging" Paolo Bonzini
2018-10-18 20:31 ` [Qemu-devel] [PULL 03/48] qemu-timer: introduce timer attributes Paolo Bonzini
2018-11-05 23:16   ` Eric Blake
2018-11-06  5:01     ` Artem Pisarenko
2018-11-06  9:45     ` Paolo Bonzini
2018-11-07 20:21       ` Eric Blake
2018-11-08  9:37         ` Peter Maydell
2018-10-18 20:31 ` Paolo Bonzini [this message]
2018-10-18 20:31 ` [Qemu-devel] [PULL 05/48] qemu-timer: optimize record/replay checkpointing for all clocks Paolo Bonzini
2018-10-19  6:59   ` Artem Pisarenko
2018-10-18 20:31 ` [Qemu-devel] [PULL 06/48] target-i386: kvm: do not initialize padding fields Paolo Bonzini
2018-10-19  9:03   ` Peter Maydell
2018-10-19 11:44     ` Paolo Bonzini
2018-10-18 20:31 ` [Qemu-devel] [PULL 07/48] linux-headers: update to 4.20-rc1 Paolo Bonzini
2018-10-18 20:31 ` [Qemu-devel] [PULL 08/48] target-i386 : add coalesced_pio API Paolo Bonzini
2018-10-18 20:31 ` [Qemu-devel] [PULL 09/48] target-i386: add rtc 0x70 port as coalesced_pio Paolo Bonzini
2018-10-18 20:31 ` [Qemu-devel] [PULL 10/48] target-i386: add i440fx 0xcf8 " Paolo Bonzini
2018-10-18 20:31 ` [Qemu-devel] [PULL 11/48] target-i386: add q35 " Paolo Bonzini
2018-10-18 20:31 ` [Qemu-devel] [PULL 12/48] replay: don't process events at virtual clock checkpoint Paolo Bonzini
2018-10-18 20:31 ` [Qemu-devel] [PULL 13/48] i386/kvm: add support for Hyper-V IPI send Paolo Bonzini
2018-10-18 20:31 ` [Qemu-devel] [PULL 14/48] i386: hvf: Fix register refs if REX is present Paolo Bonzini
2018-10-18 20:31 ` [Qemu-devel] [PULL 15/48] i386: hvf: Remove hvf_disabled Paolo Bonzini
2018-10-18 20:31 ` [Qemu-devel] [PULL 16/48] vl: improve/fix documentation related to RTC function Paolo Bonzini
2018-10-18 20:31 ` [Qemu-devel] [PULL 17/48] vl: refactor -rtc option references Paolo Bonzini
2018-10-18 20:31 ` [Qemu-devel] [PULL 18/48] Fixes RTC bug with base datetime shifts in clock=vm Paolo Bonzini
2018-10-18 20:31 ` [Qemu-devel] [PULL 19/48] vl, qapi: offset calculation in RTC_CHANGE event reverted Paolo Bonzini
2018-10-18 20:31 ` [Qemu-devel] [PULL 20/48] call HotplugHandler->plug() as the last step in device realization Paolo Bonzini
2018-10-18 20:31 ` [Qemu-devel] [PULL 21/48] hw: edu: drop DO_UPCAST Paolo Bonzini
2018-10-18 20:31 ` [Qemu-devel] [PULL 22/48] scsi-disk: fix double completion of failing passthrough requests Paolo Bonzini
2018-10-18 20:31 ` [Qemu-devel] [PULL 23/48] scsi-disk: fix rerror/werror=ignore Paolo Bonzini
2018-10-18 20:31 ` [Qemu-devel] [PULL 24/48] hyperv_testdev: refactor for better maintainability Paolo Bonzini
2018-10-18 20:31 ` [Qemu-devel] [PULL 25/48] hyperv_testdev: drop unnecessary includes Paolo Bonzini
2018-10-18 20:31 ` [Qemu-devel] [PULL 26/48] hyperv: cosmetic: g_malloc -> g_new Paolo Bonzini
2018-10-18 20:31 ` [Qemu-devel] [PULL 27/48] hyperv: synic: only setup ack notifier if there's a callback Paolo Bonzini
2018-10-18 20:31 ` [Qemu-devel] [PULL 28/48] hyperv: allow passing arbitrary data to sint ack callback Paolo Bonzini
2018-10-18 20:31 ` [Qemu-devel] [PULL 29/48] hyperv: address HvSintRoute by X86CPU pointer Paolo Bonzini
2018-10-18 20:31 ` [Qemu-devel] [PULL 30/48] hyperv: make HvSintRoute reference-counted Paolo Bonzini
2018-10-18 20:31 ` [Qemu-devel] [PULL 31/48] hyperv: rename kvm_hv_sint_route_set_sint Paolo Bonzini
2018-10-18 20:31 ` [Qemu-devel] [PULL 32/48] hyperv: split hyperv-proto.h into x86 and arch-independent parts Paolo Bonzini
2018-10-18 20:32 ` [Qemu-devel] [PULL 33/48] hyperv: make hyperv_vp_index inline Paolo Bonzini
2018-10-18 20:32 ` [Qemu-devel] [PULL 34/48] hyperv: factor out arch-independent API into hw/hyperv Paolo Bonzini
2018-10-18 20:32 ` [Qemu-devel] [PULL 35/48] default-configs: collect CONFIG_HYPERV* in hyperv.mak Paolo Bonzini
2018-10-18 20:32 ` [Qemu-devel] [PULL 36/48] i386: add hyperv-stub for CONFIG_HYPERV=n Paolo Bonzini
2018-10-18 20:32 ` [Qemu-devel] [PULL 37/48] hyperv:synic: split capability testing and setting Paolo Bonzini
2018-10-18 20:32 ` [Qemu-devel] [PULL 39/48] hyperv: only add SynIC in compatible configurations Paolo Bonzini
2018-10-18 20:32 ` [Qemu-devel] [PULL 40/48] hyperv: make overlay pages for SynIC Paolo Bonzini
2018-10-18 20:32 ` [Qemu-devel] [PULL 41/48] hyperv: add synic message delivery Paolo Bonzini
2018-10-18 20:32 ` [Qemu-devel] [PULL 42/48] hyperv: add synic event flag signaling Paolo Bonzini
2018-10-18 20:32 ` [Qemu-devel] [PULL 43/48] hyperv: process SIGNAL_EVENT hypercall Paolo Bonzini
2018-10-18 20:32 ` [Qemu-devel] [PULL 44/48] hyperv: add support for KVM_HYPERV_EVENTFD Paolo Bonzini
2018-10-18 20:32 ` [Qemu-devel] [PULL 45/48] hyperv: process POST_MESSAGE hypercall Paolo Bonzini
2018-10-18 20:32 ` [Qemu-devel] [PULL 46/48] hyperv_testdev: add SynIC message and event testmodes Paolo Bonzini
2018-10-18 20:32 ` [Qemu-devel] [PULL 47/48] target/i386: kvm: just return after migrate_add_blocker failed Paolo Bonzini
2018-10-18 20:32 ` [Qemu-devel] [PULL 48/48] replay: pass raw icount value to replay_save_clock Paolo Bonzini
2018-10-19  7:32 ` [Qemu-devel] [PULL 00/48] Miscellaneous patches for 2018-10-18 Paolo Bonzini

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=1539894735-14232-5-git-send-email-pbonzini@redhat.com \
    --to=pbonzini@redhat.com \
    --cc=artem.k.pisarenko@gmail.com \
    --cc=qemu-devel@nongnu.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).