Patchwork [v2,2/2] qdev: Prepare "realized" property

login
register
mail settings
Submitter Andreas Färber
Date Jan. 6, 2013, 6:48 p.m.
Message ID <1357498122-1129-3-git-send-email-afaerber@suse.de>
Download mbox | patch
Permalink /patch/209792/
State New
Headers show

Comments

Andreas Färber - Jan. 6, 2013, 6:48 p.m.
Based on earlier patches by Paolo and me, introduce the QOM realizefn at
device level only, as requested by Anthony.

For now this just wraps the qdev initfn, which it deprecates.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
Cc: Anthony Liguori <anthony@codemonkey.ws>
---
 hw/qdev-core.h |    4 +++
 hw/qdev.c      |   96 ++++++++++++++++++++++++++++++++++++++++++--------------
 2 Dateien geändert, 76 Zeilen hinzugefügt(+), 24 Zeilen entfernt(-)
Eduardo Habkost - Jan. 7, 2013, 1:52 p.m.
On Sun, Jan 06, 2013 at 07:48:42PM +0100, Andreas Färber wrote:
> Based on earlier patches by Paolo and me, introduce the QOM realizefn at
> device level only, as requested by Anthony.
> 
> For now this just wraps the qdev initfn, which it deprecates.
> 
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> Signed-off-by: Andreas Färber <afaerber@suse.de>
> Cc: Anthony Liguori <anthony@codemonkey.ws>
> ---
>  hw/qdev-core.h |    4 +++
>  hw/qdev.c      |   96 ++++++++++++++++++++++++++++++++++++++++++--------------
>  2 Dateien geändert, 76 Zeilen hinzugefügt(+), 24 Zeilen entfernt(-)
> 
> diff --git a/hw/qdev-core.h b/hw/qdev-core.h
> index 5836e35..e50c866 100644
> --- a/hw/qdev-core.h
> +++ b/hw/qdev-core.h
> @@ -20,6 +20,8 @@ enum {
>  typedef int (*qdev_initfn)(DeviceState *dev);
>  typedef int (*qdev_event)(DeviceState *dev);
>  typedef void (*qdev_resetfn)(DeviceState *dev);
> +typedef void (*DeviceRealize)(DeviceState *dev, Error **err);
> +typedef void (*DeviceUnrealize)(DeviceState *dev, Error **err);
>  
>  struct VMStateDescription;
>  
> @@ -38,6 +40,8 @@ typedef struct DeviceClass {
>      const struct VMStateDescription *vmsd;
>  
>      /* Private to qdev / bus.  */
> +    DeviceRealize realize;
> +    DeviceUnrealize unrealize;
>      qdev_initfn init;

Can we get the semantics of the realize/unrealize/init functions
documented here? For example, explicitly document that subclasses are
supposed to call the parent's realize function (this is the case,
right?), and the differences between DeviceState.init and
DeviceState.realize.

I took some time to understand the reason for DeviceState.realize to
exist when we already have DeviceState.init, and I am sure I already
forgot half of the explanation, and I will forget it completely in 1 or
2 months.  :-)


> [...]

Patch

diff --git a/hw/qdev-core.h b/hw/qdev-core.h
index 5836e35..e50c866 100644
--- a/hw/qdev-core.h
+++ b/hw/qdev-core.h
@@ -20,6 +20,8 @@  enum {
 typedef int (*qdev_initfn)(DeviceState *dev);
 typedef int (*qdev_event)(DeviceState *dev);
 typedef void (*qdev_resetfn)(DeviceState *dev);
+typedef void (*DeviceRealize)(DeviceState *dev, Error **err);
+typedef void (*DeviceUnrealize)(DeviceState *dev, Error **err);
 
 struct VMStateDescription;
 
@@ -38,6 +40,8 @@  typedef struct DeviceClass {
     const struct VMStateDescription *vmsd;
 
     /* Private to qdev / bus.  */
+    DeviceRealize realize;
+    DeviceUnrealize unrealize;
     qdev_initfn init;
     qdev_event unplug;
     qdev_event exit;
diff --git a/hw/qdev.c b/hw/qdev.c
index b214c8a..f45ab14 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -148,37 +148,30 @@  DeviceState *qdev_try_create(BusState *bus, const char *type)
    Return 0 on success.  */
 int qdev_init(DeviceState *dev)
 {
-    DeviceClass *dc = DEVICE_GET_CLASS(dev);
-    int rc;
+    Error *local_err = NULL;
 
     assert(!dev->realized);
 
-    rc = dc->init(dev);
-    if (rc < 0) {
+    object_property_set_bool(OBJECT(dev), true, "realized", &local_err);
+    if (local_err != NULL) {
+        error_free(local_err);
         qdev_free(dev);
-        return rc;
+        return -1;
     }
+    return 0;
+}
 
-    if (!OBJECT(dev)->parent) {
-        static int unattached_count = 0;
-        gchar *name = g_strdup_printf("device[%d]", unattached_count++);
-
-        object_property_add_child(container_get(qdev_get_machine(),
-                                                "/unattached"),
-                                  name, OBJECT(dev), NULL);
-        g_free(name);
-    }
+static void device_realize(DeviceState *dev, Error **err)
+{
+    DeviceClass *dc = DEVICE_GET_CLASS(dev);
 
-    if (qdev_get_vmsd(dev)) {
-        vmstate_register_with_alias_id(dev, -1, qdev_get_vmsd(dev), dev,
-                                       dev->instance_id_alias,
-                                       dev->alias_required_for_version);
-    }
-    dev->realized = true;
-    if (dev->hotplugged) {
-        device_reset(dev);
+    if (dc->init) {
+        int rc = dc->init(dev);
+        if (rc < 0) {
+            error_setg(err, "Device initialization failed.");
+            return;
+        }
     }
-    return 0;
 }
 
 void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
@@ -636,6 +629,55 @@  void qdev_property_add_static(DeviceState *dev, Property *prop,
     assert_no_error(local_err);
 }
 
+static bool device_get_realized(Object *obj, Error **err)
+{
+    DeviceState *dev = DEVICE(obj);
+    return dev->realized;
+}
+
+static void device_set_realized(Object *obj, bool value, Error **err)
+{
+    DeviceState *dev = DEVICE(obj);
+    DeviceClass *dc = DEVICE_GET_CLASS(dev);
+    Error *local_err = NULL;
+
+    if (value && !dev->realized) {
+        if (dc->realize) {
+            dc->realize(dev, &local_err);
+        }
+
+        if (!obj->parent && local_err == NULL) {
+            static int unattached_count;
+            gchar *name = g_strdup_printf("device[%d]", unattached_count++);
+
+            object_property_add_child(container_get(qdev_get_machine(),
+                                                    "/unattached"),
+                                      name, obj, &local_err);
+            g_free(name);
+        }
+
+        if (qdev_get_vmsd(dev) && local_err == NULL) {
+            vmstate_register_with_alias_id(dev, -1, qdev_get_vmsd(dev), dev,
+                                           dev->instance_id_alias,
+                                           dev->alias_required_for_version);
+        }
+        if (dev->hotplugged && local_err == NULL) {
+            device_reset(dev);
+        }
+    } else if (!value && dev->realized) {
+        if (dc->unrealize) {
+            dc->unrealize(dev, &local_err);
+        }
+    }
+
+    if (local_err != NULL) {
+        error_propagate(err, local_err);
+        return;
+    }
+
+    dev->realized = value;
+}
+
 static void device_initfn(Object *obj)
 {
     DeviceState *dev = DEVICE(obj);
@@ -650,6 +692,9 @@  static void device_initfn(Object *obj)
     dev->instance_id_alias = -1;
     dev->realized = false;
 
+    object_property_add_bool(obj, "realized",
+                             device_get_realized, device_set_realized, NULL);
+
     class = object_get_class(OBJECT(dev));
     do {
         for (prop = DEVICE_CLASS(class)->props; prop && prop->name; prop++) {
@@ -707,7 +752,10 @@  static void qdev_remove_from_bus(Object *obj)
 
 static void device_class_init(ObjectClass *class, void *data)
 {
+    DeviceClass *dc = DEVICE_CLASS(class);
+
     class->unparent = qdev_remove_from_bus;
+    dc->realize = device_realize;
 }
 
 void device_reset(DeviceState *dev)
@@ -730,7 +778,7 @@  Object *qdev_get_machine(void)
     return dev;
 }
 
-static TypeInfo device_type_info = {
+static const TypeInfo device_type_info = {
     .name = TYPE_DEVICE,
     .parent = TYPE_OBJECT,
     .instance_size = sizeof(DeviceState),