Patchwork [v4,08/23] qdev: Introduce qdev_iterate_recursive

login
register
mail settings
Submitter Jan Kiszka
Date June 15, 2010, 10:38 p.m.
Message ID <8f4efb5aab7b6cd6bca60816059dd38e77c6a1ff.1276641524.git.jan.kiszka@web.de>
Download mbox | patch
Permalink /patch/55808/
State New
Headers show

Comments

Jan Kiszka - June 15, 2010, 10:38 p.m.
From: Jan Kiszka <jan.kiszka@siemens.com>

Add qdev_iterate_recursive to walk the complete qtree invoking a
callback for each device. Use this service to implement
qdev_find_id_recursive.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 hw/qdev.c |   29 +++++++++++++++++++++++++----
 hw/qdev.h |    3 +++
 2 files changed, 28 insertions(+), 4 deletions(-)
Markus Armbruster - June 23, 2010, 9:40 a.m.
Jan Kiszka <jan.kiszka@web.de> writes:

> From: Jan Kiszka <jan.kiszka@siemens.com>
>
> Add qdev_iterate_recursive to walk the complete qtree invoking a
> callback for each device. Use this service to implement
> qdev_find_id_recursive.
>
> Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
> ---
>  hw/qdev.c |   29 +++++++++++++++++++++++++----
>  hw/qdev.h |    3 +++
>  2 files changed, 28 insertions(+), 4 deletions(-)
>
> diff --git a/hw/qdev.c b/hw/qdev.c
> index 2d1d171..466d8d5 100644
> --- a/hw/qdev.c
> +++ b/hw/qdev.c
> @@ -475,16 +475,22 @@ static BusState *qbus_find_recursive(BusState *bus, const char *name,
>      return NULL;
>  }
>  
> -static DeviceState *qdev_find_id_recursive(BusState *bus, const char *id)
> +void *qdev_iterate_recursive(BusState *bus, qdev_iteratefn callback,
> +                             void *opaque)
>  {
>      DeviceState *dev, *ret;
>      BusState *child;
>  
> +    if (!bus) {
> +        bus = main_system_bus;
> +    }
>      QTAILQ_FOREACH(dev, &bus->children, sibling) {
> -        if (dev->id && strcmp(dev->id, id) == 0)
> -            return dev;
> +        ret = callback(dev, opaque);
> +        if (ret) {
> +            return ret;
> +        }
>          QTAILQ_FOREACH(child, &dev->child_bus, sibling) {
> -            ret = qdev_find_id_recursive(child, id);
> +            ret = qdev_iterate_recursive(child, callback, opaque);
>              if (ret) {
>                  return ret;
>              }

I'd call "iterate recursive" simply "walk".  It's common usage for
trees.

Except this isn't a walk or iteration, it's a search: the walk stops as
soon as the callback returns non-null.  Not obvious from the name,
therefore needs a comment.

[...]

Patch

diff --git a/hw/qdev.c b/hw/qdev.c
index 2d1d171..466d8d5 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -475,16 +475,22 @@  static BusState *qbus_find_recursive(BusState *bus, const char *name,
     return NULL;
 }
 
-static DeviceState *qdev_find_id_recursive(BusState *bus, const char *id)
+void *qdev_iterate_recursive(BusState *bus, qdev_iteratefn callback,
+                             void *opaque)
 {
     DeviceState *dev, *ret;
     BusState *child;
 
+    if (!bus) {
+        bus = main_system_bus;
+    }
     QTAILQ_FOREACH(dev, &bus->children, sibling) {
-        if (dev->id && strcmp(dev->id, id) == 0)
-            return dev;
+        ret = callback(dev, opaque);
+        if (ret) {
+            return ret;
+        }
         QTAILQ_FOREACH(child, &dev->child_bus, sibling) {
-            ret = qdev_find_id_recursive(child, id);
+            ret = qdev_iterate_recursive(child, callback, opaque);
             if (ret) {
                 return ret;
             }
@@ -493,6 +499,21 @@  static DeviceState *qdev_find_id_recursive(BusState *bus, const char *id)
     return NULL;
 }
 
+static void *find_id_callback(DeviceState *dev, void *opaque)
+{
+    const char *id = opaque;
+
+    if (dev->id && strcmp(dev->id, id) == 0) {
+        return dev;
+    }
+    return NULL;
+}
+
+static DeviceState *qdev_find_id_recursive(BusState *bus, const char *id)
+{
+    return qdev_iterate_recursive(bus, find_id_callback, (void *)id);
+}
+
 static int qdev_instance_no(DeviceState *dev)
 {
     struct DeviceState *sibling;
diff --git a/hw/qdev.h b/hw/qdev.h
index 170a63a..111c876 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -134,6 +134,7 @@  BusState *qdev_get_child_bus(DeviceState *dev, const char *name);
 typedef int (*qdev_initfn)(DeviceState *dev, DeviceInfo *info);
 typedef int (*qdev_event)(DeviceState *dev);
 typedef void (*qdev_resetfn)(DeviceState *dev);
+typedef void *(*qdev_iteratefn)(DeviceState *dev, void *opaque);
 
 struct DeviceInfo {
     const char *name;
@@ -168,6 +169,8 @@  void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n);
 CharDriverState *qdev_init_chardev(DeviceState *dev);
 
 BusState *qdev_get_parent_bus(DeviceState *dev);
+void *qdev_iterate_recursive(BusState *bus, qdev_iteratefn callback,
+                             void *opaque);
 
 /*** BUS API. ***/