diff options
author | Anthony Liguori <aliguori@us.ibm.com> | 2011-12-12 14:29:40 -0600 |
---|---|---|
committer | Anthony Liguori <aliguori@us.ibm.com> | 2011-12-15 09:20:49 -0600 |
commit | b2b6c39a7915e82cade4ab8689344c91c5e45653 (patch) | |
tree | 54aaf0ea1a1e21f9f0b516081a2cd9b8db071c36 | |
parent | 182970509bd79635a5b16a06d2e918d3f5187486 (diff) | |
download | qemu-b2b6c39a7915e82cade4ab8689344c91c5e45653.zip qemu-b2b6c39a7915e82cade4ab8689344c91c5e45653.tar.gz qemu-b2b6c39a7915e82cade4ab8689344c91c5e45653.tar.bz2 |
qom: optimize qdev_get_canonical_path using a parent link
The full tree search was a bit unreasonable.
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
-rw-r--r-- | hw/qdev.c | 56 | ||||
-rw-r--r-- | hw/qdev.h | 4 |
2 files changed, 28 insertions, 32 deletions
@@ -1229,6 +1229,8 @@ void qdev_property_add_child(DeviceState *dev, const char *name, NULL, NULL, child, errp); qdev_ref(child); + g_assert(child->parent == NULL); + child->parent = dev; g_free(type); } @@ -1307,48 +1309,38 @@ void qdev_property_add_link(DeviceState *dev, const char *name, g_free(full_type); } -static gchar *qdev_get_path_in(DeviceState *parent, DeviceState *dev) +gchar *qdev_get_canonical_path(DeviceState *dev) { - DeviceProperty *prop; + DeviceState *root = qdev_get_root(); + char *newpath = NULL, *path = NULL; - if (parent == dev) { - return g_strdup(""); - } + while (dev != root) { + DeviceProperty *prop = NULL; - QTAILQ_FOREACH(prop, &parent->properties, node) { - gchar *subpath; + g_assert(dev->parent != NULL); - if (!strstart(prop->type, "child<", NULL)) { - continue; - } + QTAILQ_FOREACH(prop, &dev->parent->properties, node) { + if (!strstart(prop->type, "child<", NULL)) { + continue; + } - /* Check to see if the device is one of parent's children */ - if (prop->opaque == dev) { - return g_strdup(prop->name); + if (prop->opaque == dev) { + if (path) { + newpath = g_strdup_printf("%s/%s", prop->name, path); + g_free(path); + path = newpath; + } else { + path = g_strdup(prop->name); + } + break; + } } - /* Check to see if the device is a child of our child */ - subpath = qdev_get_path_in(prop->opaque, dev); - if (subpath) { - gchar *path; + g_assert(prop != NULL); - path = g_strdup_printf("%s/%s", prop->name, subpath); - g_free(subpath); - - return path; - } + dev = dev->parent; } - return NULL; -} - -gchar *qdev_get_canonical_path(DeviceState *dev) -{ - gchar *path, *newpath; - - path = qdev_get_path_in(qdev_get_root(), dev); - g_assert(path != NULL); - newpath = g_strdup_printf("/%s", path); g_free(path); @@ -92,6 +92,10 @@ struct DeviceState { uint32_t ref; QTAILQ_HEAD(, DeviceProperty) properties; + + /* Do not, under any circumstance, use this parent link below anywhere + * outside of qdev.c. You have been warned. */ + DeviceState *parent; }; typedef void (*bus_dev_printfn)(Monitor *mon, DeviceState *dev, int indent); |