From patchwork Wed Feb 8 15:27:53 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Avi Kivity X-Patchwork-Id: 140166 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [140.186.70.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 34601B71B7 for ; Thu, 9 Feb 2012 02:28:52 +1100 (EST) Received: from localhost ([::1]:33928 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Rv9Rs-0001B5-Qh for incoming@patchwork.ozlabs.org; Wed, 08 Feb 2012 10:28:44 -0500 Received: from eggs.gnu.org ([140.186.70.92]:50055) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Rv9Rf-00013v-AP for qemu-devel@nongnu.org; Wed, 08 Feb 2012 10:28:32 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Rv9RU-00006O-7d for qemu-devel@nongnu.org; Wed, 08 Feb 2012 10:28:31 -0500 Received: from mx1.redhat.com ([209.132.183.28]:29931) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Rv9RT-00006C-Rz for qemu-devel@nongnu.org; Wed, 08 Feb 2012 10:28:20 -0500 Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q18FSJRm019724 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Wed, 8 Feb 2012 10:28:19 -0500 Received: from cleopatra.tlv.redhat.com (cleopatra.tlv.redhat.com [10.35.255.11]) by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id q18FSHFo025145 for ; Wed, 8 Feb 2012 10:28:18 -0500 Received: from s01.tlv.redhat.com (s01.tlv.redhat.com [10.35.255.8]) by cleopatra.tlv.redhat.com (Postfix) with ESMTP id D84AD250BAD; Wed, 8 Feb 2012 17:28:10 +0200 (IST) From: Avi Kivity To: qemu-devel@nongnu.org Date: Wed, 8 Feb 2012 17:27:53 +0200 Message-Id: <1328714879-18906-5-git-send-email-avi@redhat.com> In-Reply-To: <1328714879-18906-1-git-send-email-avi@redhat.com> References: <1328714879-18906-1-git-send-email-avi@redhat.com> X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 04/10] memory: switch memory listeners to a QTAILQ X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org 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 --- 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 ... */