Patchwork [1.3,2/5] qdev: move bus removal to object_unparent

login
register
mail settings
Submitter Paolo Bonzini
Date Nov. 23, 2012, 8:47 a.m.
Message ID <1353660436-8897-3-git-send-email-pbonzini@redhat.com>
Download mbox | patch
Permalink /patch/201260/
State New
Headers show

Comments

Paolo Bonzini - Nov. 23, 2012, 8:47 a.m.
Add an ObjectClass method that is done at object_unparent time.  It
should remove any backlinks to the object in the composition tree,
so that object_delete will be able to drop the last reference and
free the object.

Use it for qdev buses.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
        Ping Fan, with respect to your patch at
        http://permalink.gmane.org/gmane.comp.emulators.qemu/179687,
        this one removes the need for qdev_unset_parent.  You
        can simply call object_unparent.

 hw/qdev.c             | 16 +++++++++++++---
 include/qemu/object.h | 11 +++++++++++
 qom/object.c          |  3 +++
 3 files changed, 27 insertions(+), 3 deletions(-)
Andreas Färber - Nov. 23, 2012, 4:52 p.m.
Am 23.11.2012 09:47, schrieb Paolo Bonzini:
> Add an ObjectClass method that is done at object_unparent time.  It
> should remove any backlinks to the object in the composition tree,
> so that object_delete will be able to drop the last reference and
> free the object.
> 
> Use it for qdev buses.
> 
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

Reviewed-by: Andreas Färber <afaerber@suse.de>

Andreas
Andreas Färber - Nov. 27, 2012, 1:02 a.m.
Am 23.11.2012 09:47, schrieb Paolo Bonzini:
> diff --git a/hw/qdev.c b/hw/qdev.c
> index 7ddcd24..f43717b 100644
> --- a/hw/qdev.c
> +++ b/hw/qdev.c
[...]
> @@ -720,6 +717,18 @@ static void device_class_base_init(ObjectClass *class, void *data)
>      klass->props = NULL;
>  }
>  
> +static void qdev_remove_from_bus(Object *obj)
> +{
> +    DeviceState *dev = DEVICE(obj);
> +
> +    bus_remove_child(dev->parent_bus, dev);
> +}
> +
> +static void device_class_init(ObjectClass *class, void *data)
> +{
> +    class->unparent = qdev_remove_from_bus;

Ouch, patch for 1.4 coming up. :)

Andreas

> +}
> +
>  void device_reset(DeviceState *dev)
>  {
>      DeviceClass *klass = DEVICE_GET_CLASS(dev);
> @@ -747,6 +756,7 @@ static TypeInfo device_type_info = {
>      .instance_init = device_initfn,
>      .instance_finalize = device_finalize,
>      .class_base_init = device_class_base_init,
> +    .class_init = device_class_init,
>      .abstract = true,
>      .class_size = sizeof(DeviceClass),
>  };

Patch

diff --git a/hw/qdev.c b/hw/qdev.c
index 7ddcd24..f43717b 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -705,9 +705,6 @@  static void device_finalize(Object *obj)
             qemu_opts_del(dev->opts);
         }
     }
-    if (dev->parent_bus) {
-        bus_remove_child(dev->parent_bus, dev);
-    }
 }
 
 static void device_class_base_init(ObjectClass *class, void *data)
@@ -720,6 +717,18 @@  static void device_class_base_init(ObjectClass *class, void *data)
     klass->props = NULL;
 }
 
+static void qdev_remove_from_bus(Object *obj)
+{
+    DeviceState *dev = DEVICE(obj);
+
+    bus_remove_child(dev->parent_bus, dev);
+}
+
+static void device_class_init(ObjectClass *class, void *data)
+{
+    class->unparent = qdev_remove_from_bus;
+}
+
 void device_reset(DeviceState *dev)
 {
     DeviceClass *klass = DEVICE_GET_CLASS(dev);
@@ -747,6 +756,7 @@  static TypeInfo device_type_info = {
     .instance_init = device_initfn,
     .instance_finalize = device_finalize,
     .class_base_init = device_class_base_init,
+    .class_init = device_class_init,
     .abstract = true,
     .class_size = sizeof(DeviceClass),
 };
diff --git a/include/qemu/object.h b/include/qemu/object.h
index be707f1..232463b 100644
--- a/include/qemu/object.h
+++ b/include/qemu/object.h
@@ -230,6 +230,15 @@  typedef struct ObjectProperty
 } ObjectProperty;
 
 /**
+ * ObjectUnparent:
+ * @obj: the object that is being removed from the composition tree
+ *
+ * Called when an object is being removed from the QOM composition tree.
+ * The function should remove any backlinks from children objects to @obj.
+ */
+typedef void (ObjectUnparent)(Object *obj);
+
+/**
  * ObjectClass:
  *
  * The base for all classes.  The only thing that #ObjectClass contains is an
@@ -240,6 +249,8 @@  struct ObjectClass
     /*< private >*/
     Type type;
     GSList *interfaces;
+
+    ObjectUnparent *unparent;
 };
 
 /**
diff --git a/qom/object.c b/qom/object.c
index 6a8c02a..f4747d0 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -363,6 +363,9 @@  void object_unparent(Object *obj)
     if (obj->parent) {
         object_property_del_child(obj->parent, obj, NULL);
     }
+    if (obj->class->unparent) {
+        (obj->class->unparent)(obj);
+    }
 }
 
 static void object_deinit(Object *obj, TypeImpl *type)