diff options
Diffstat (limited to 'memory.c')
-rw-r--r-- | memory.c | 31 |
1 files changed, 24 insertions, 7 deletions
@@ -229,6 +229,7 @@ struct FlatView { FlatRange *ranges; unsigned nr; unsigned nr_allocated; + struct AddressSpaceDispatch *dispatch; }; typedef struct AddressSpaceOps AddressSpaceOps; @@ -289,6 +290,9 @@ static void flatview_destroy(FlatView *view) { int i; + if (view->dispatch) { + address_space_dispatch_free(view->dispatch); + } for (i = 0; i < view->nr; i++) { memory_region_unref(view->ranges[i].mr); } @@ -304,10 +308,25 @@ static bool flatview_ref(FlatView *view) static void flatview_unref(FlatView *view) { if (atomic_fetch_dec(&view->ref) == 1) { - flatview_destroy(view); + call_rcu(view, flatview_destroy, rcu); } } +static FlatView *address_space_to_flatview(AddressSpace *as) +{ + return atomic_rcu_read(&as->current_map); +} + +AddressSpaceDispatch *flatview_to_dispatch(FlatView *fv) +{ + return fv->dispatch; +} + +AddressSpaceDispatch *address_space_to_dispatch(AddressSpace *as) +{ + return flatview_to_dispatch(address_space_to_flatview(as)); +} + static bool can_merge(FlatRange *r1, FlatRange *r2) { return int128_eq(addrrange_end(r1->addr), r2->addr.start) @@ -891,13 +910,13 @@ static void address_space_update_topology(AddressSpace *as) FlatView *new_view = generate_memory_topology(as->root); int i; - mem_begin(as); + new_view->dispatch = mem_begin(as); for (i = 0; i < new_view->nr; i++) { MemoryRegionSection mrs = section_from_flat_range(&new_view->ranges[i], as); - mem_add(as, &mrs); + mem_add(as, new_view, &mrs); } - mem_commit(as); + mem_commit(new_view->dispatch); if (!QTAILQ_EMPTY(&as->listeners)) { address_space_update_topology_pass(as, old_view, new_view, false); @@ -906,7 +925,7 @@ static void address_space_update_topology(AddressSpace *as) /* Writes are protected by the BQL. */ atomic_rcu_set(&as->current_map, new_view); - call_rcu(old_view, flatview_unref, rcu); + flatview_unref(old_view); /* Note that all the old MemoryRegions are still alive up to this * point. This relieves most MemoryListeners from the need to @@ -2636,7 +2655,6 @@ void address_space_init(AddressSpace *as, MemoryRegion *root, const char *name) QTAILQ_INIT(&as->listeners); QTAILQ_INSERT_TAIL(&address_spaces, as, address_spaces_link); as->name = g_strdup(name ? name : "anonymous"); - as->dispatch = NULL; memory_region_update_pending |= root->enabled; memory_region_transaction_commit(); } @@ -2645,7 +2663,6 @@ static void do_address_space_destroy(AddressSpace *as) { bool do_free = as->malloced; - address_space_destroy_dispatch(as); assert(QTAILQ_EMPTY(&as->listeners)); flatview_unref(as->current_map); |