diff options
Diffstat (limited to 'memory.c')
-rw-r--r-- | memory.c | 27 |
1 files changed, 27 insertions, 0 deletions
@@ -2124,7 +2124,9 @@ void address_space_init(AddressSpace *as, MemoryRegion *root, const char *name) { memory_region_ref(root); memory_region_transaction_begin(); + as->ref_count = 1; as->root = root; + as->malloced = false; as->current_map = g_new(FlatView, 1); flatview_init(as->current_map); as->ioeventfd_nb = 0; @@ -2139,6 +2141,7 @@ void address_space_init(AddressSpace *as, MemoryRegion *root, const char *name) static void do_address_space_destroy(AddressSpace *as) { MemoryListener *listener; + bool do_free = as->malloced; address_space_destroy_dispatch(as); @@ -2150,12 +2153,36 @@ static void do_address_space_destroy(AddressSpace *as) g_free(as->name); g_free(as->ioeventfds); memory_region_unref(as->root); + if (do_free) { + g_free(as); + } +} + +AddressSpace *address_space_init_shareable(MemoryRegion *root, const char *name) +{ + AddressSpace *as; + + QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) { + if (root == as->root && as->malloced) { + as->ref_count++; + return as; + } + } + + as = g_malloc0(sizeof *as); + address_space_init(as, root, name); + as->malloced = true; + return as; } void address_space_destroy(AddressSpace *as) { MemoryRegion *root = as->root; + as->ref_count--; + if (as->ref_count) { + return; + } /* Flush out anything from MemoryListeners listening in on this */ memory_region_transaction_begin(); as->root = NULL; |