qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Avi Kivity <avi@redhat.com>
To: qemu-devel@nongnu.org
Subject: [Qemu-devel] [PATCH 04/10] memory: switch memory listeners to a QTAILQ
Date: Wed,  8 Feb 2012 17:27:53 +0200	[thread overview]
Message-ID: <1328714879-18906-5-git-send-email-avi@redhat.com> (raw)
In-Reply-To: <1328714879-18906-1-git-send-email-avi@redhat.com>

This allows reverse iteration, which in turns allows consistent ordering
among multiple listeners:

  l1->add
  l2->add
  l2->del
  l1->del

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 hw/vhost.c |    1 +
 kvm-all.c  |    1 +
 memory.c   |   70 ++++++++++++++++++++++++++++++++++++++++++------------------
 memory.h   |    4 ++-
 xen-all.c  |    1 +
 5 files changed, 55 insertions(+), 22 deletions(-)

diff --git a/hw/vhost.c b/hw/vhost.c
index 5ece659..4737145 100644
--- a/hw/vhost.c
+++ b/hw/vhost.c
@@ -751,6 +751,7 @@ int vhost_dev_init(struct vhost_dev *hdev, int devfd, bool force)
         .log_sync = vhost_log_sync,
         .log_global_start = vhost_log_global_start,
         .log_global_stop = vhost_log_global_stop,
+        .priority = 10
     };
     hdev->mem = g_malloc0(offsetof(struct vhost_memory, regions));
     hdev->n_mem_sections = 0;
diff --git a/kvm-all.c b/kvm-all.c
index 0b87658..6835fd4 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -726,6 +726,7 @@ static void kvm_log_global_stop(struct MemoryListener *listener)
     .log_sync = kvm_log_sync,
     .log_global_start = kvm_log_global_start,
     .log_global_stop = kvm_log_global_stop,
+    .priority = 10,
 };
 
 static void kvm_handle_interrupt(CPUState *env, int mask)
diff --git a/memory.c b/memory.c
index 6afe414..cb2b4f1 100644
--- a/memory.c
+++ b/memory.c
@@ -27,8 +27,8 @@
 static bool memory_region_update_pending = false;
 static bool global_dirty_log = false;
 
-static QLIST_HEAD(, MemoryListener) memory_listeners
-    = QLIST_HEAD_INITIALIZER(memory_listeners);
+static QTAILQ_HEAD(memory_listeners, MemoryListener) memory_listeners
+    = QTAILQ_HEAD_INITIALIZER(memory_listeners);
 
 typedef struct AddrRange AddrRange;
 
@@ -678,17 +678,31 @@ static void address_space_update_ioeventfds(AddressSpace *as)
     as->ioeventfd_nb = ioeventfd_nb;
 }
 
-#define MEMORY_LISTENER_CALL(_callback, _args...)               \
-    do {                                                        \
-        MemoryListener *_listener;                              \
-                                                                \
-        QLIST_FOREACH(_listener, &memory_listeners, link) {     \
-            _listener->_callback(_listener, ##_args);           \
-        }                                                       \
+enum ListenerDirection { Forward, Reverse };
+
+#define MEMORY_LISTENER_CALL(_callback, _direction, _args...)           \
+    do {                                                                \
+        MemoryListener *_listener;                                      \
+                                                                        \
+        switch (_direction) {                                           \
+        case Forward:                                                   \
+            QTAILQ_FOREACH(_listener, &memory_listeners, link) {        \
+                _listener->_callback(_listener, ##_args);               \
+            }                                                           \
+            break;                                                      \
+        case Reverse:                                                   \
+            QTAILQ_FOREACH_REVERSE(_listener, &memory_listeners,        \
+                                   memory_listeners, link) {            \
+                _listener->_callback(_listener, ##_args);               \
+            }                                                           \
+            break;                                                      \
+        default:                                                        \
+            abort();                                                    \
+        }                                                               \
     } while (0)
 
-#define MEMORY_LISTENER_UPDATE_REGION(fr, as, callback)                 \
-    MEMORY_LISTENER_CALL(callback, &(MemoryRegionSection) {             \
+#define MEMORY_LISTENER_UPDATE_REGION(fr, as, dir, callback)            \
+    MEMORY_LISTENER_CALL(callback, dir, &(MemoryRegionSection) {        \
         .mr = (fr)->mr,                                                 \
         .address_space = (as)->root,                                    \
         .offset_within_region = (fr)->offset_in_region,                 \
@@ -728,7 +742,7 @@ static void address_space_update_topology_pass(AddressSpace *as,
             /* In old, but (not in new, or in new but attributes changed). */
 
             if (!adding) {
-                MEMORY_LISTENER_UPDATE_REGION(frold, as, region_del);
+                MEMORY_LISTENER_UPDATE_REGION(frold, as, Reverse, region_del);
                 as->ops->range_del(as, frold);
             }
 
@@ -738,11 +752,11 @@ static void address_space_update_topology_pass(AddressSpace *as,
 
             if (adding) {
                 if (frold->dirty_log_mask && !frnew->dirty_log_mask) {
-                    MEMORY_LISTENER_UPDATE_REGION(frnew, as, log_stop);
+                    MEMORY_LISTENER_UPDATE_REGION(frnew, as, Reverse, log_stop);
                     as->ops->log_stop(as, frnew);
                 } else if (frnew->dirty_log_mask && !frold->dirty_log_mask) {
                     as->ops->log_start(as, frnew);
-                    MEMORY_LISTENER_UPDATE_REGION(frnew, as, log_start);
+                    MEMORY_LISTENER_UPDATE_REGION(frnew, as, Forward, log_start);
                 }
             }
 
@@ -753,7 +767,7 @@ static void address_space_update_topology_pass(AddressSpace *as,
 
             if (adding) {
                 as->ops->range_add(as, frnew);
-                MEMORY_LISTENER_UPDATE_REGION(frnew, as, region_add);
+                MEMORY_LISTENER_UPDATE_REGION(frnew, as, Forward, region_add);
             }
 
             ++inew;
@@ -1142,7 +1156,8 @@ void memory_region_sync_dirty_bitmap(MemoryRegion *mr)
 
     FOR_EACH_FLAT_RANGE(fr, &address_space_memory.current_map) {
         if (fr->mr == mr) {
-            MEMORY_LISTENER_UPDATE_REGION(fr, &address_space_memory, log_sync);
+            MEMORY_LISTENER_UPDATE_REGION(fr, &address_space_memory,
+                                          Forward, log_sync);
         }
     }
 }
@@ -1469,7 +1484,7 @@ void memory_global_sync_dirty_bitmap(MemoryRegion *address_space)
     FlatRange *fr;
 
     FOR_EACH_FLAT_RANGE(fr, &as->current_map) {
-        MEMORY_LISTENER_UPDATE_REGION(fr, as, log_sync);
+        MEMORY_LISTENER_UPDATE_REGION(fr, as, Forward, log_sync);
     }
 }
 
@@ -1477,13 +1492,13 @@ void memory_global_dirty_log_start(void)
 {
     cpu_physical_memory_set_dirty_tracking(1);
     global_dirty_log = true;
-    MEMORY_LISTENER_CALL(log_global_start);
+    MEMORY_LISTENER_CALL(log_global_start, Forward);
 }
 
 void memory_global_dirty_log_stop(void)
 {
     global_dirty_log = false;
-    MEMORY_LISTENER_CALL(log_global_stop);
+    MEMORY_LISTENER_CALL(log_global_stop, Reverse);
     cpu_physical_memory_set_dirty_tracking(0);
 }
 
@@ -1509,14 +1524,27 @@ static void listener_add_address_space(MemoryListener *listener,
 
 void memory_listener_register(MemoryListener *listener)
 {
-    QLIST_INSERT_HEAD(&memory_listeners, listener, link);
+    MemoryListener *other = NULL;
+
+    if (QTAILQ_EMPTY(&memory_listeners)
+        || listener->priority >= QTAILQ_LAST(&memory_listeners,
+                                             memory_listeners)->priority) {
+        QTAILQ_INSERT_TAIL(&memory_listeners, listener, link);
+    } else {
+        QTAILQ_FOREACH(other, &memory_listeners, link) {
+            if (listener->priority < other->priority) {
+                break;
+            }
+        }
+        QTAILQ_INSERT_BEFORE(other, listener, link);
+    }
     listener_add_address_space(listener, &address_space_memory);
     listener_add_address_space(listener, &address_space_io);
 }
 
 void memory_listener_unregister(MemoryListener *listener)
 {
-    QLIST_REMOVE(listener, link);
+    QTAILQ_REMOVE(&memory_listeners, listener, link);
 }
 
 void set_system_memory_map(MemoryRegion *mr)
diff --git a/memory.h b/memory.h
index 4763286..954dc86 100644
--- a/memory.h
+++ b/memory.h
@@ -185,7 +185,9 @@ struct MemoryListener {
     void (*log_sync)(MemoryListener *listener, MemoryRegionSection *section);
     void (*log_global_start)(MemoryListener *listener);
     void (*log_global_stop)(MemoryListener *listener);
-    QLIST_ENTRY(MemoryListener) link;
+    /* Lower = earlier (during add), later (during del) */
+    unsigned priority;
+    QTAILQ_ENTRY(MemoryListener) link;
 };
 
 /**
diff --git a/xen-all.c b/xen-all.c
index fd39168..8cb84ef 100644
--- a/xen-all.c
+++ b/xen-all.c
@@ -495,6 +495,7 @@ static void xen_log_global_stop(MemoryListener *listener)
     .log_sync = xen_log_sync,
     .log_global_start = xen_log_global_start,
     .log_global_stop = xen_log_global_stop,
+    .priority = 10,
 };
 
 /* VCPU Operations, MMIO, IO ring ... */
-- 
1.7.9

  parent reply	other threads:[~2012-02-08 15:28 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-02-08 15:27 [Qemu-devel] [PATCH 00/10] Remove AddressSpaceOps Avi Kivity
2012-02-08 15:27 ` [Qemu-devel] [PATCH 01/10] ioport: change portio_list not to use memory_region_set_offset() Avi Kivity
2012-02-08 15:27 ` [Qemu-devel] [PATCH 02/10] memory: remove memory_region_set_offset() Avi Kivity
2012-02-08 15:27 ` [Qemu-devel] [PATCH 03/10] memory: add shorthand for invoking a callback on all listeners Avi Kivity
2012-02-08 15:27 ` Avi Kivity [this message]
2012-02-08 15:27 ` [Qemu-devel] [PATCH 05/10] memory: code motion: move MEMORY_LISTENER_CALL() Avi Kivity
2012-02-08 15:27 ` [Qemu-devel] [PATCH 06/10] memory: move ioeventfd ops to MemoryListener Avi Kivity
2012-02-08 15:27 ` [Qemu-devel] [PATCH 07/10] memory: add a readonly attribute to MemoryRegionSection Avi Kivity
2012-02-08 15:27 ` [Qemu-devel] [PATCH 08/10] memory: don't pass ->readable attribute to cpu_register_physical_memory_log Avi Kivity
2012-02-08 15:27 ` [Qemu-devel] [PATCH 09/10] memory: use a MemoryListener for core memory map updates too Avi Kivity
2012-02-09  7:58   ` Paolo Bonzini
2012-02-09  9:28     ` Avi Kivity
2012-02-08 15:27 ` [Qemu-devel] [PATCH 10/10] memory: drop AddressSpaceOps Avi Kivity
2012-02-08 15:35 ` [Qemu-devel] [PATCH 00/10] Remove AddressSpaceOps Avi Kivity
2012-02-08 23:28 ` Richard Henderson

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=1328714879-18906-5-git-send-email-avi@redhat.com \
    --to=avi@redhat.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).