memory: add shorthand for invoking a callback on all listeners

Signed-off-by: Avi Kivity <avi@redhat.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
This commit is contained in:
Avi Kivity 2012-02-08 13:58:44 +02:00
parent 2b50aa1f14
commit 946996e9c1

View file

@ -678,31 +678,23 @@ static void address_space_update_ioeventfds(AddressSpace *as)
as->ioeventfd_nb = ioeventfd_nb; as->ioeventfd_nb = ioeventfd_nb;
} }
typedef void ListenerCallback(MemoryListener *listener, #define MEMORY_LISTENER_CALL(_callback, _args...) \
MemoryRegionSection *mrs); do { \
MemoryListener *_listener; \
\
QLIST_FOREACH(_listener, &memory_listeners, link) { \
_listener->_callback(_listener, ##_args); \
} \
} while (0)
/* Want "void (&MemoryListener::*callback)(const MemoryRegionSection& s)" */ #define MEMORY_LISTENER_UPDATE_REGION(fr, as, callback) \
static void memory_listener_update_region(FlatRange *fr, AddressSpace *as, MEMORY_LISTENER_CALL(callback, &(MemoryRegionSection) { \
size_t callback_offset) .mr = (fr)->mr, \
{ .address_space = (as)->root, \
MemoryRegionSection section = { .offset_within_region = (fr)->offset_in_region, \
.mr = fr->mr, .size = int128_get64((fr)->addr.size), \
.address_space = as->root, .offset_within_address_space = int128_get64((fr)->addr.start), \
.offset_within_region = fr->offset_in_region, })
.size = int128_get64(fr->addr.size),
.offset_within_address_space = int128_get64(fr->addr.start),
};
MemoryListener *listener;
QLIST_FOREACH(listener, &memory_listeners, link) {
ListenerCallback *callback
= *(ListenerCallback **)((void *)listener + callback_offset);
callback(listener, &section);
}
}
#define MEMORY_LISTENER_UPDATE_REGION(fr, as, callback) \
memory_listener_update_region(fr, as, offsetof(MemoryListener, callback))
static void address_space_update_topology_pass(AddressSpace *as, static void address_space_update_topology_pass(AddressSpace *as,
FlatView old_view, FlatView old_view,
@ -1483,23 +1475,15 @@ void memory_global_sync_dirty_bitmap(MemoryRegion *address_space)
void memory_global_dirty_log_start(void) void memory_global_dirty_log_start(void)
{ {
MemoryListener *listener;
cpu_physical_memory_set_dirty_tracking(1); cpu_physical_memory_set_dirty_tracking(1);
global_dirty_log = true; global_dirty_log = true;
QLIST_FOREACH(listener, &memory_listeners, link) { MEMORY_LISTENER_CALL(log_global_start);
listener->log_global_start(listener);
}
} }
void memory_global_dirty_log_stop(void) void memory_global_dirty_log_stop(void)
{ {
MemoryListener *listener;
global_dirty_log = false; global_dirty_log = false;
QLIST_FOREACH(listener, &memory_listeners, link) { MEMORY_LISTENER_CALL(log_global_stop);
listener->log_global_stop(listener);
}
cpu_physical_memory_set_dirty_tracking(0); cpu_physical_memory_set_dirty_tracking(0);
} }