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

Submitted by Andreas Färber on Jan. 6, 2013, 6:48 p.m.

Details

Message ID 1357498122-1129-3-git-send-email-afaerber@suse.de
State New
Headers show

Commit Message

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(-)

Comments

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 hide | download patch | download mbox

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),