mirror of https://github.com/xemu-project/xemu.git
qdev: move deletion of children from finalize to unparent
A device will never be finalized as long as it has a reference from other devices that sit on its buses. To ensure that the references go away, deassociate a bus from its children in the unparent callback for the bus. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
This commit is contained in:
parent
9d127820eb
commit
6853d27a12
37
hw/qdev.c
37
hw/qdev.c
|
@ -433,6 +433,25 @@ static void qbus_realize(BusState *bus, DeviceState *parent, const char *name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void bus_unparent(Object *obj)
|
||||||
|
{
|
||||||
|
BusState *bus = BUS(obj);
|
||||||
|
BusChild *kid;
|
||||||
|
|
||||||
|
while ((kid = QTAILQ_FIRST(&bus->children)) != NULL) {
|
||||||
|
DeviceState *dev = kid->child;
|
||||||
|
qdev_free(dev);
|
||||||
|
}
|
||||||
|
if (bus->parent) {
|
||||||
|
QLIST_REMOVE(bus, sibling);
|
||||||
|
bus->parent->num_child_bus--;
|
||||||
|
bus->parent = NULL;
|
||||||
|
} else {
|
||||||
|
assert(bus != sysbus_get_default()); /* main_system_bus is never freed */
|
||||||
|
qemu_unregister_reset(qbus_reset_all_fn, bus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void qbus_create_inplace(void *bus, const char *typename,
|
void qbus_create_inplace(void *bus, const char *typename,
|
||||||
DeviceState *parent, const char *name)
|
DeviceState *parent, const char *name)
|
||||||
{
|
{
|
||||||
|
@ -805,22 +824,15 @@ static void qbus_initfn(Object *obj)
|
||||||
QTAILQ_INIT(&bus->children);
|
QTAILQ_INIT(&bus->children);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void bus_class_init(ObjectClass *class, void *data)
|
||||||
|
{
|
||||||
|
class->unparent = bus_unparent;
|
||||||
|
}
|
||||||
|
|
||||||
static void qbus_finalize(Object *obj)
|
static void qbus_finalize(Object *obj)
|
||||||
{
|
{
|
||||||
BusState *bus = BUS(obj);
|
BusState *bus = BUS(obj);
|
||||||
BusChild *kid;
|
|
||||||
|
|
||||||
while ((kid = QTAILQ_FIRST(&bus->children)) != NULL) {
|
|
||||||
DeviceState *dev = kid->child;
|
|
||||||
qdev_free(dev);
|
|
||||||
}
|
|
||||||
if (bus->parent) {
|
|
||||||
QLIST_REMOVE(bus, sibling);
|
|
||||||
bus->parent->num_child_bus--;
|
|
||||||
} else {
|
|
||||||
assert(bus != sysbus_get_default()); /* main_system_bus is never freed */
|
|
||||||
qemu_unregister_reset(qbus_reset_all_fn, bus);
|
|
||||||
}
|
|
||||||
g_free((char *)bus->name);
|
g_free((char *)bus->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -832,6 +844,7 @@ static const TypeInfo bus_info = {
|
||||||
.class_size = sizeof(BusClass),
|
.class_size = sizeof(BusClass),
|
||||||
.instance_init = qbus_initfn,
|
.instance_init = qbus_initfn,
|
||||||
.instance_finalize = qbus_finalize,
|
.instance_finalize = qbus_finalize,
|
||||||
|
.class_init = bus_class_init,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void qdev_register_types(void)
|
static void qdev_register_types(void)
|
||||||
|
|
Loading…
Reference in New Issue