summaryrefslogtreecommitdiff
path: root/memory.c
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2013-05-06 10:46:11 +0200
committerPaolo Bonzini <pbonzini@redhat.com>2013-07-04 17:42:45 +0200
commitdfde4e6e1a868f60033ece0590b1f75e6c57fa16 (patch)
treea84c1cddd96c6dc60fd7a5d35949b4fcaf9a32ed /memory.c
parent3ce10901ca8da9142dcdcde198fda1a4c290934c (diff)
downloadqemu-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.c21
1 files changed, 21 insertions, 0 deletions
diff --git a/memory.c b/memory.c
index 24027c5077..543e0cc7c8 100644
--- a/memory.c
+++ b/memory.c
@@ -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;
}