diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2016-09-23 11:08:54 +0200 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2016-10-24 15:27:19 +0200 |
commit | 0a752eeea810a1c37f5de4edba355c35cfa42524 (patch) | |
tree | 6ba3e696159a2271c89aac298ecef4bda92eb913 /memory.c | |
parent | adaad61c3c8efb5b4f21ad70c6e141215fdbb304 (diff) | |
download | qemu-0a752eeea810a1c37f5de4edba355c35cfa42524.zip |
memory: optimize memory_region_sync_dirty_bitmap
Avoid walking the FlatView of all address spaces. Most of the
address spaces will have no log_sync callback on their listeners.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'memory.c')
-rw-r--r-- | memory.c | 18 |
1 files changed, 15 insertions, 3 deletions
@@ -1642,14 +1642,26 @@ bool memory_region_test_and_clear_dirty(MemoryRegion *mr, hwaddr addr, void memory_region_sync_dirty_bitmap(MemoryRegion *mr) { + MemoryListener *listener; AddressSpace *as; + FlatView *view; FlatRange *fr; - QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) { - FlatView *view = address_space_get_flatview(as); + /* If the same address space has multiple log_sync listeners, we + * visit that address space's FlatView multiple times. But because + * log_sync listeners are rare, it's still cheaper than walking each + * address space once. + */ + QTAILQ_FOREACH(listener, &memory_listeners, link) { + if (!listener->log_sync) { + continue; + } + as = listener->address_space; + view = address_space_get_flatview(as); FOR_EACH_FLAT_RANGE(fr, view) { if (fr->mr == mr) { - MEMORY_LISTENER_UPDATE_REGION(fr, as, Forward, log_sync); + MemoryRegionSection mrs = section_from_flat_range(fr, as); + listener->log_sync(listener, &mrs); } } flatview_unref(view); |