diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2013-05-06 10:46:11 +0200 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2013-07-04 17:42:45 +0200 |
commit | dfde4e6e1a868f60033ece0590b1f75e6c57fa16 (patch) | |
tree | a84c1cddd96c6dc60fd7a5d35949b4fcaf9a32ed /memory.c | |
parent | 3ce10901ca8da9142dcdcde198fda1a4c290934c (diff) | |
download | qemu-dfde4e6e1a868f60033ece0590b1f75e6c57fa16.tar.gz qemu-dfde4e6e1a868f60033ece0590b1f75e6c57fa16.tar.bz2 qemu-dfde4e6e1a868f60033ece0590b1f75e6c57fa16.zip |
memory: add ref/unref calls
Add ref/unref calls at the following places:
- places where memory regions are stashed by a listener and
used outside the BQL (including in Xen or KVM).
- memory_region_find callsites
- creation of aliases and containers (only the aliased/contained
region gets a reference to avoid loops)
- around calls to del_subregion/add_subregion, where the region
could disappear after the first call
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'memory.c')
-rw-r--r-- | memory.c | 21 |
1 files changed, 21 insertions, 0 deletions
@@ -148,6 +148,7 @@ static bool memory_listener_match(MemoryListener *listener, } \ } while (0) +/* No need to ref/unref .mr, the FlatRange keeps it alive. */ #define MEMORY_LISTENER_UPDATE_REGION(fr, as, dir, callback) \ MEMORY_LISTENER_CALL(callback, dir, (&(MemoryRegionSection) { \ .mr = (fr)->mr, \ @@ -263,11 +264,17 @@ static void flatview_insert(FlatView *view, unsigned pos, FlatRange *range) memmove(view->ranges + pos + 1, view->ranges + pos, (view->nr - pos) * sizeof(FlatRange)); view->ranges[pos] = *range; + memory_region_ref(range->mr); ++view->nr; } static void flatview_destroy(FlatView *view) { + int i; + + for (i = 0; i < view->nr; i++) { + memory_region_unref(view->ranges[i].mr); + } g_free(view->ranges); } @@ -709,6 +716,11 @@ static void memory_region_destructor_ram(MemoryRegion *mr) qemu_ram_free(mr->ram_addr); } +static void memory_region_destructor_alias(MemoryRegion *mr) +{ + memory_region_unref(mr->alias); +} + static void memory_region_destructor_ram_from_ptr(MemoryRegion *mr) { qemu_ram_free_from_ptr(mr->ram_addr); @@ -964,6 +976,8 @@ void memory_region_init_alias(MemoryRegion *mr, uint64_t size) { memory_region_init(mr, owner, name, size); + memory_region_ref(orig); + mr->destructor = memory_region_destructor_alias; mr->alias = orig; mr->alias_offset = offset; } @@ -1342,6 +1356,7 @@ static void memory_region_add_subregion_common(MemoryRegion *mr, memory_region_transaction_begin(); assert(!subregion->parent); + memory_region_ref(subregion); subregion->parent = mr; subregion->addr = offset; QTAILQ_FOREACH(other, &mr->subregions, subregions_link) { @@ -1404,6 +1419,7 @@ void memory_region_del_subregion(MemoryRegion *mr, assert(subregion->parent == mr); subregion->parent = NULL; QTAILQ_REMOVE(&mr->subregions, subregion, subregions_link); + memory_region_unref(subregion); memory_region_update_pending |= mr->enabled && subregion->enabled; memory_region_transaction_commit(); } @@ -1431,12 +1447,14 @@ void memory_region_set_address(MemoryRegion *mr, hwaddr addr) } memory_region_transaction_begin(); + memory_region_ref(mr); memory_region_del_subregion(parent, mr); if (may_overlap) { memory_region_add_subregion_overlap(parent, addr, mr, priority); } else { memory_region_add_subregion(parent, addr, mr); } + memory_region_unref(mr); memory_region_transaction_commit(); } @@ -1484,6 +1502,7 @@ bool memory_region_present(MemoryRegion *parent, hwaddr addr) if (!mr) { return false; } + memory_region_unref(mr); return true; } @@ -1523,6 +1542,8 @@ MemoryRegionSection memory_region_find(MemoryRegion *mr, ret.size = range.size; ret.offset_within_address_space = int128_get64(range.start); ret.readonly = fr->readonly; + memory_region_ref(ret.mr); + return ret; } |