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>
This commit is contained in:
Paolo Bonzini 2016-09-23 11:08:54 +02:00
parent adaad61c3c
commit 0a752eeea8
1 changed files with 15 additions and 3 deletions

View File

@ -1642,14 +1642,26 @@ bool memory_region_test_and_clear_dirty(MemoryRegion *mr, hwaddr addr,
void memory_region_sync_dirty_bitmap(MemoryRegion *mr) void memory_region_sync_dirty_bitmap(MemoryRegion *mr)
{ {
MemoryListener *listener;
AddressSpace *as; AddressSpace *as;
FlatView *view;
FlatRange *fr; FlatRange *fr;
QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) { /* If the same address space has multiple log_sync listeners, we
FlatView *view = address_space_get_flatview(as); * 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) { FOR_EACH_FLAT_RANGE(fr, view) {
if (fr->mr == mr) { 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); flatview_unref(view);