aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2016-01-18 17:40:50 +0000
committerPeter Maydell <peter.maydell@linaro.org>2016-01-18 17:40:50 +0000
commit3db34bf64ab4f8797565dd8750003156c32b301d (patch)
treeb4b660b22b17d76c7184e3d153f5c6c2e0681925
parent12b167226f2804063cf8d72fe4fdc01764c99e96 (diff)
parent300b115ce804cb6a20acc0003cc17687545b728d (diff)
Merge remote-tracking branch 'remotes/afaerber/tags/qom-devices-for-peter' into staging
QOM infrastructure fixes and device conversions * Dynamic class properties * Property iterator cleanup * Device hot-unplug ID race fix # gpg: Signature made Mon 18 Jan 2016 17:27:01 GMT using RSA key ID 3E7E013F # gpg: Good signature from "Andreas Färber <afaerber@suse.de>" # gpg: aka "Andreas Färber <afaerber@suse.com>" * remotes/afaerber/tags/qom-devices-for-peter: MAINTAINERS: Fix sPAPR entry heading qdev: Free QemuOpts when the QOM path goes away qom: Change object property iterator API contract qom: Allow properties to be registered against classes Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r--MAINTAINERS2
-rw-r--r--hw/core/qdev.c4
-rw-r--r--hw/ppc/spapr_drc.c7
-rw-r--r--include/qom/object.h76
-rw-r--r--net/filter.c7
-rw-r--r--qmp.c14
-rw-r--r--qom/object.c252
-rw-r--r--tests/check-qom-proplist.c38
-rw-r--r--vl.c7
9 files changed, 324 insertions, 83 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 8f44dca48a..4030e2749d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -587,7 +587,7 @@ F: hw/ppc/prep.c
F: hw/pci-host/prep.[hc]
F: hw/isa/pc87312.[hc]
-sPAPR (pseries)
+sPAPR
M: David Gibson <david@gibson.dropbear.id.au>
M: Alexander Graf <agraf@suse.de>
L: qemu-ppc@nongnu.org
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index 2c7101d91d..44bf790b01 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -1206,7 +1206,6 @@ static void device_finalize(Object *obj)
NamedGPIOList *ngl, *next;
DeviceState *dev = DEVICE(obj);
- qemu_opts_del(dev->opts);
QLIST_FOREACH_SAFE(ngl, &dev->gpios, node, next) {
QLIST_REMOVE(ngl, node);
@@ -1254,6 +1253,9 @@ static void device_unparent(Object *obj)
qapi_event_send_device_deleted(!!dev->id, dev->id, path, &error_abort);
g_free(path);
}
+
+ qemu_opts_del(dev->opts);
+ dev->opts = NULL;
}
static void device_class_init(ObjectClass *class, void *data)
diff --git a/hw/ppc/spapr_drc.c b/hw/ppc/spapr_drc.c
index 4fb86a68c4..dccb908c31 100644
--- a/hw/ppc/spapr_drc.c
+++ b/hw/ppc/spapr_drc.c
@@ -684,7 +684,7 @@ int spapr_drc_populate_dt(void *fdt, int fdt_offset, Object *owner,
{
Object *root_container;
ObjectProperty *prop;
- ObjectPropertyIterator *iter;
+ ObjectPropertyIterator iter;
uint32_t drc_count = 0;
GArray *drc_indexes, *drc_power_domains;
GString *drc_names, *drc_types;
@@ -708,8 +708,8 @@ int spapr_drc_populate_dt(void *fdt, int fdt_offset, Object *owner,
*/
root_container = container_get(object_get_root(), DRC_CONTAINER_PATH);
- iter = object_property_iter_init(root_container);
- while ((prop = object_property_iter_next(iter))) {
+ object_property_iter_init(&iter, root_container);
+ while ((prop = object_property_iter_next(&iter))) {
Object *obj;
sPAPRDRConnector *drc;
sPAPRDRConnectorClass *drck;
@@ -750,7 +750,6 @@ int spapr_drc_populate_dt(void *fdt, int fdt_offset, Object *owner,
spapr_drc_get_type_str(drc->type));
drc_types = g_string_insert_len(drc_types, -1, "\0", 1);
}
- object_property_iter_free(iter);
/* now write the drc count into the space we reserved at the
* beginning of the arrays previously
diff --git a/include/qom/object.h b/include/qom/object.h
index 4509166f6f..d0dafe986c 100644
--- a/include/qom/object.h
+++ b/include/qom/object.h
@@ -381,6 +381,8 @@ struct ObjectClass
const char *class_cast_cache[OBJECT_CLASS_CAST_CACHE];
ObjectUnparent *unparent;
+
+ GHashTable *properties;
};
/**
@@ -944,6 +946,13 @@ ObjectProperty *object_property_add(Object *obj, const char *name,
void object_property_del(Object *obj, const char *name, Error **errp);
+ObjectProperty *object_class_property_add(ObjectClass *klass, const char *name,
+ const char *type,
+ ObjectPropertyAccessor *get,
+ ObjectPropertyAccessor *set,
+ ObjectPropertyRelease *release,
+ void *opaque, Error **errp);
+
/**
* object_property_find:
* @obj: the object
@@ -954,15 +963,20 @@ void object_property_del(Object *obj, const char *name, Error **errp);
*/
ObjectProperty *object_property_find(Object *obj, const char *name,
Error **errp);
+ObjectProperty *object_class_property_find(ObjectClass *klass, const char *name,
+ Error **errp);
-typedef struct ObjectPropertyIterator ObjectPropertyIterator;
+typedef struct ObjectPropertyIterator {
+ ObjectClass *nextclass;
+ GHashTableIter iter;
+} ObjectPropertyIterator;
/**
* object_property_iter_init:
* @obj: the object
*
* Initializes an iterator for traversing all properties
- * registered against an object instance.
+ * registered against an object instance, its class and all parent classes.
*
* It is forbidden to modify the property list while iterating,
* whether removing or adding properties.
@@ -973,32 +987,27 @@ typedef struct ObjectPropertyIterator ObjectPropertyIterator;
* <title>Using object property iterators</title>
* <programlisting>
* ObjectProperty *prop;
- * ObjectPropertyIterator *iter;
+ * ObjectPropertyIterator iter;
*
- * iter = object_property_iter_init(obj);
- * while ((prop = object_property_iter_next(iter))) {
+ * object_property_iter_init(&iter, obj);
+ * while ((prop = object_property_iter_next(&iter))) {
* ... do something with prop ...
* }
- * object_property_iter_free(iter);
* </programlisting>
* </example>
- *
- * Returns: the new iterator
- */
-ObjectPropertyIterator *object_property_iter_init(Object *obj);
-
-/**
- * object_property_iter_free:
- * @iter: the iterator instance
- *
- * Releases any resources associated with the iterator.
*/
-void object_property_iter_free(ObjectPropertyIterator *iter);
+void object_property_iter_init(ObjectPropertyIterator *iter,
+ Object *obj);
/**
* object_property_iter_next:
* @iter: the iterator instance
*
+ * Return the next available property. If no further properties
+ * are available, a %NULL value will be returned and the @iter
+ * pointer should not be used again after this point without
+ * re-initializing it.
+ *
* Returns: the next property, or %NULL when all properties
* have been traversed.
*/
@@ -1371,6 +1380,12 @@ void object_property_add_str(Object *obj, const char *name,
void (*set)(Object *, const char *, Error **),
Error **errp);
+void object_class_property_add_str(ObjectClass *klass, const char *name,
+ char *(*get)(Object *, Error **),
+ void (*set)(Object *, const char *,
+ Error **),
+ Error **errp);
+
/**
* object_property_add_bool:
* @obj: the object to add a property to
@@ -1387,6 +1402,11 @@ void object_property_add_bool(Object *obj, const char *name,
void (*set)(Object *, bool, Error **),
Error **errp);
+void object_class_property_add_bool(ObjectClass *klass, const char *name,
+ bool (*get)(Object *, Error **),
+ void (*set)(Object *, bool, Error **),
+ Error **errp);
+
/**
* object_property_add_enum:
* @obj: the object to add a property to
@@ -1406,6 +1426,13 @@ void object_property_add_enum(Object *obj, const char *name,
void (*set)(Object *, int, Error **),
Error **errp);
+void object_class_property_add_enum(ObjectClass *klass, const char *name,
+ const char *typename,
+ const char * const *strings,
+ int (*get)(Object *, Error **),
+ void (*set)(Object *, int, Error **),
+ Error **errp);
+
/**
* object_property_add_tm:
* @obj: the object to add a property to
@@ -1420,6 +1447,10 @@ void object_property_add_tm(Object *obj, const char *name,
void (*get)(Object *, struct tm *, Error **),
Error **errp);
+void object_class_property_add_tm(ObjectClass *klass, const char *name,
+ void (*get)(Object *, struct tm *, Error **),
+ Error **errp);
+
/**
* object_property_add_uint8_ptr:
* @obj: the object to add a property to
@@ -1432,6 +1463,8 @@ void object_property_add_tm(Object *obj, const char *name,
*/
void object_property_add_uint8_ptr(Object *obj, const char *name,
const uint8_t *v, Error **errp);
+void object_class_property_add_uint8_ptr(ObjectClass *klass, const char *name,
+ const uint8_t *v, Error **errp);
/**
* object_property_add_uint16_ptr:
@@ -1445,6 +1478,8 @@ void object_property_add_uint8_ptr(Object *obj, const char *name,
*/
void object_property_add_uint16_ptr(Object *obj, const char *name,
const uint16_t *v, Error **errp);
+void object_class_property_add_uint16_ptr(ObjectClass *klass, const char *name,
+ const uint16_t *v, Error **errp);
/**
* object_property_add_uint32_ptr:
@@ -1458,6 +1493,8 @@ void object_property_add_uint16_ptr(Object *obj, const char *name,
*/
void object_property_add_uint32_ptr(Object *obj, const char *name,
const uint32_t *v, Error **errp);
+void object_class_property_add_uint32_ptr(ObjectClass *klass, const char *name,
+ const uint32_t *v, Error **errp);
/**
* object_property_add_uint64_ptr:
@@ -1471,6 +1508,8 @@ void object_property_add_uint32_ptr(Object *obj, const char *name,
*/
void object_property_add_uint64_ptr(Object *obj, const char *name,
const uint64_t *v, Error **Errp);
+void object_class_property_add_uint64_ptr(ObjectClass *klass, const char *name,
+ const uint64_t *v, Error **Errp);
/**
* object_property_add_alias:
@@ -1522,6 +1561,9 @@ void object_property_add_const_link(Object *obj, const char *name,
*/
void object_property_set_description(Object *obj, const char *name,
const char *description, Error **errp);
+void object_class_property_set_description(ObjectClass *klass, const char *name,
+ const char *description,
+ Error **errp);
/**
* object_child_foreach:
diff --git a/net/filter.c b/net/filter.c
index f777ba2899..5d90f83429 100644
--- a/net/filter.c
+++ b/net/filter.c
@@ -137,7 +137,7 @@ static void netfilter_complete(UserCreatable *uc, Error **errp)
Error *local_err = NULL;
char *str, *info;
ObjectProperty *prop;
- ObjectPropertyIterator *iter;
+ ObjectPropertyIterator iter;
StringOutputVisitor *ov;
if (!nf->netdev_id) {
@@ -174,8 +174,8 @@ static void netfilter_complete(UserCreatable *uc, Error **errp)
QTAILQ_INSERT_TAIL(&nf->netdev->filters, nf, next);
/* generate info str */
- iter = object_property_iter_init(OBJECT(nf));
- while ((prop = object_property_iter_next(iter))) {
+ object_property_iter_init(&iter, OBJECT(nf));
+ while ((prop = object_property_iter_next(&iter))) {
if (!strcmp(prop->name, "type")) {
continue;
}
@@ -189,7 +189,6 @@ static void netfilter_complete(UserCreatable *uc, Error **errp)
g_free(str);
g_free(info);
}
- object_property_iter_free(iter);
}
static void netfilter_finalize(Object *obj)
diff --git a/qmp.c b/qmp.c
index 0a1fa19925..3ff6db79b9 100644
--- a/qmp.c
+++ b/qmp.c
@@ -210,7 +210,7 @@ ObjectPropertyInfoList *qmp_qom_list(const char *path, Error **errp)
bool ambiguous = false;
ObjectPropertyInfoList *props = NULL;
ObjectProperty *prop;
- ObjectPropertyIterator *iter;
+ ObjectPropertyIterator iter;
obj = object_resolve_path(path, &ambiguous);
if (obj == NULL) {
@@ -223,8 +223,8 @@ ObjectPropertyInfoList *qmp_qom_list(const char *path, Error **errp)
return NULL;
}
- iter = object_property_iter_init(obj);
- while ((prop = object_property_iter_next(iter))) {
+ object_property_iter_init(&iter, obj);
+ while ((prop = object_property_iter_next(&iter))) {
ObjectPropertyInfoList *entry = g_malloc0(sizeof(*entry));
entry->value = g_malloc0(sizeof(ObjectPropertyInfo));
@@ -234,7 +234,6 @@ ObjectPropertyInfoList *qmp_qom_list(const char *path, Error **errp)
entry->value->name = g_strdup(prop->name);
entry->value->type = g_strdup(prop->type);
}
- object_property_iter_free(iter);
return props;
}
@@ -506,7 +505,7 @@ DevicePropertyInfoList *qmp_device_list_properties(const char *typename,
ObjectClass *klass;
Object *obj;
ObjectProperty *prop;
- ObjectPropertyIterator *iter;
+ ObjectPropertyIterator iter;
DevicePropertyInfoList *prop_list = NULL;
klass = object_class_by_name(typename);
@@ -535,8 +534,8 @@ DevicePropertyInfoList *qmp_device_list_properties(const char *typename,
obj = object_new(typename);
- iter = object_property_iter_init(obj);
- while ((prop = object_property_iter_next(iter))) {
+ object_property_iter_init(&iter, obj);
+ while ((prop = object_property_iter_next(&iter))) {
DevicePropertyInfo *info;
DevicePropertyInfoList *entry;
@@ -567,7 +566,6 @@ DevicePropertyInfoList *qmp_device_list_properties(const char *typename,
entry->next = prop_list;
prop_list = entry;
}
- object_property_iter_free(iter);
object_unref(obj);
diff --git a/qom/object.c b/qom/object.c
index d7515697a3..5ff97ab91e 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -67,10 +67,6 @@ struct TypeImpl
InterfaceImpl interfaces[MAX_INTERFACES];
};
-struct ObjectPropertyIterator {
- GHashTableIter iter;
-};
-
static Type type_interface;
static GHashTable *type_table_get(void)
@@ -246,6 +242,16 @@ static void type_initialize_interface(TypeImpl *ti, TypeImpl *interface_type,
iface_impl->class);
}
+static void object_property_free(gpointer data)
+{
+ ObjectProperty *prop = data;
+
+ g_free(prop->name);
+ g_free(prop->type);
+ g_free(prop->description);
+ g_free(prop);
+}
+
static void type_initialize(TypeImpl *ti)
{
TypeImpl *parent;
@@ -268,6 +274,8 @@ static void type_initialize(TypeImpl *ti)
g_assert_cmpint(parent->class_size, <=, ti->class_size);
memcpy(ti->class, parent->class, parent->class_size);
ti->class->interfaces = NULL;
+ ti->class->properties = g_hash_table_new_full(
+ g_str_hash, g_str_equal, g_free, object_property_free);
for (e = parent->class->interfaces; e; e = e->next) {
InterfaceClass *iface = e->data;
@@ -292,6 +300,9 @@ static void type_initialize(TypeImpl *ti)
type_initialize_interface(ti, t, t);
}
+ } else {
+ ti->class->properties = g_hash_table_new_full(
+ g_str_hash, g_str_equal, g_free, object_property_free);
}
ti->class->type = ti;
@@ -330,16 +341,6 @@ static void object_post_init_with_type(Object *obj, TypeImpl *ti)
}
}
-static void object_property_free(gpointer data)
-{
- ObjectProperty *prop = data;
-
- g_free(prop->name);
- g_free(prop->type);
- g_free(prop->description);
- g_free(prop);
-}
-
void object_initialize_with_type(void *data, size_t size, TypeImpl *type)
{
Object *obj = data;
@@ -918,10 +919,10 @@ object_property_add(Object *obj, const char *name, const char *type,
return ret;
}
- if (g_hash_table_lookup(obj->properties, name) != NULL) {
+ if (object_property_find(obj, name, NULL) != NULL) {
error_setg(errp, "attempt to add duplicate property '%s'"
- " to object (type '%s')", name,
- object_get_typename(obj));
+ " to object (type '%s')", name,
+ object_get_typename(obj));
return NULL;
}
@@ -939,10 +940,50 @@ object_property_add(Object *obj, const char *name, const char *type,
return prop;
}
+ObjectProperty *
+object_class_property_add(ObjectClass *klass,
+ const char *name,
+ const char *type,
+ ObjectPropertyAccessor *get,
+ ObjectPropertyAccessor *set,
+ ObjectPropertyRelease *release,
+ void *opaque,
+ Error **errp)
+{
+ ObjectProperty *prop;
+
+ if (object_class_property_find(klass, name, NULL) != NULL) {
+ error_setg(errp, "attempt to add duplicate property '%s'"
+ " to object (type '%s')", name,
+ object_class_get_name(klass));
+ return NULL;
+ }
+
+ prop = g_malloc0(sizeof(*prop));
+
+ prop->name = g_strdup(name);
+ prop->type = g_strdup(type);
+
+ prop->get = get;
+ prop->set = set;
+ prop->release = release;
+ prop->opaque = opaque;
+
+ g_hash_table_insert(klass->properties, g_strdup(name), prop);
+
+ return prop;
+}
+
ObjectProperty *object_property_find(Object *obj, const char *name,
Error **errp)
{
ObjectProperty *prop;
+ ObjectClass *klass = object_get_class(obj);
+
+ prop = object_class_property_find(klass, name, NULL);
+ if (prop) {
+ return prop;
+ }
prop = g_hash_table_lookup(obj->properties, name);
if (prop) {
@@ -953,28 +994,45 @@ ObjectProperty *object_property_find(Object *obj, const char *name,
return NULL;
}
-ObjectPropertyIterator *object_property_iter_init(Object *obj)
+void object_property_iter_init(ObjectPropertyIterator *iter,
+ Object *obj)
{
- ObjectPropertyIterator *ret = g_new0(ObjectPropertyIterator, 1);
- g_hash_table_iter_init(&ret->iter, obj->properties);
- return ret;
+ g_hash_table_iter_init(&iter->iter, obj->properties);
+ iter->nextclass = object_get_class(obj);
}
-void object_property_iter_free(ObjectPropertyIterator *iter)
+ObjectProperty *object_property_iter_next(ObjectPropertyIterator *iter)
{
- if (!iter) {
- return;
+ gpointer key, val;
+ while (!g_hash_table_iter_next(&iter->iter, &key, &val)) {
+ if (!iter->nextclass) {
+ return NULL;
+ }
+ g_hash_table_iter_init(&iter->iter, iter->nextclass->properties);
+ iter->nextclass = object_class_get_parent(iter->nextclass);
}
- g_free(iter);
+ return val;
}
-ObjectProperty *object_property_iter_next(ObjectPropertyIterator *iter)
+ObjectProperty *object_class_property_find(ObjectClass *klass, const char *name,
+ Error **errp)
{
- gpointer key, val;
- if (!g_hash_table_iter_next(&iter->iter, &key, &val)) {
- return NULL;
+ ObjectProperty *prop;
+ ObjectClass *parent_klass;
+
+ parent_klass = object_class_get_parent(klass);
+ if (parent_klass) {
+ prop = object_class_property_find(parent_klass, name, NULL);
+ if (prop) {
+ return prop;
+ }
}
- return val;
+
+ prop = g_hash_table_lookup(klass->properties, name);
+ if (!prop) {
+ error_setg(errp, "Property '.%s' not found", name);
+ }
+ return prop;
}
void object_property_del(Object *obj, const char *name, Error **errp)
@@ -1730,6 +1788,29 @@ void object_property_add_str(Object *obj, const char *name,
}
}
+void object_class_property_add_str(ObjectClass *klass, const char *name,
+ char *(*get)(Object *, Error **),
+ void (*set)(Object *, const char *,
+ Error **),
+ Error **errp)
+{
+ Error *local_err = NULL;
+ StringProperty *prop = g_malloc0(sizeof(*prop));
+
+ prop->get = get;
+ prop->set = set;
+
+ object_class_property_add(klass, name, "string",
+ get ? property_get_str : NULL,
+ set ? property_set_str : NULL,
+ property_release_str,
+ prop, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ g_free(prop);
+ }
+}
+
typedef struct BoolProperty
{
bool (*get)(Object *, Error **);
@@ -1797,6 +1878,28 @@ void object_property_add_bool(Object *obj, const char *name,
}
}
+void object_class_property_add_bool(ObjectClass *klass, const char *name,
+ bool (*get)(Object *, Error **),
+ void (*set)(Object *, bool, Error **),
+ Error **errp)
+{
+ Error *local_err = NULL;
+ BoolProperty *prop = g_malloc0(sizeof(*prop));
+
+ prop->get = get;
+ prop->set = set;
+
+ object_class_property_add(klass, name, "bool",
+ get ? property_get_bool : NULL,
+ set ? property_set_bool : NULL,
+ property_release_bool,
+ prop, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ g_free(prop);
+ }
+}
+
static void property_get_enum(Object *obj, Visitor *v, void *opaque,
const char *name, Error **errp)
{
@@ -1860,6 +1963,31 @@ void object_property_add_enum(Object *obj, const char *name,
}
}
+void object_class_property_add_enum(ObjectClass *klass, const char *name,
+ const char *typename,
+ const char * const *strings,
+ int (*get)(Object *, Error **),
+ void (*set)(Object *, int, Error **),
+ Error **errp)
+{
+ Error *local_err = NULL;
+ EnumProperty *prop = g_malloc(sizeof(*prop));
+
+ prop->strings = strings;
+ prop->get = get;
+ prop->set = set;
+
+ object_class_property_add(klass, name, typename,
+ get ? property_get_enum : NULL,
+ set ? property_set_enum : NULL,
+ property_release_enum,
+ prop, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ g_free(prop);
+ }
+}
+
typedef struct TMProperty {
void (*get)(Object *, struct tm *, Error **);
} TMProperty;
@@ -1939,6 +2067,25 @@ void object_property_add_tm(Object *obj, const char *name,
}
}
+void object_class_property_add_tm(ObjectClass *klass, const char *name,
+ void (*get)(Object *, struct tm *, Error **),
+ Error **errp)
+{
+ Error *local_err = NULL;
+ TMProperty *prop = g_malloc0(sizeof(*prop));
+
+ prop->get = get;
+
+ object_class_property_add(klass, name, "struct tm",
+ get ? property_get_tm : NULL, NULL,
+ property_release_tm,
+ prop, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ g_free(prop);
+ }
+}
+
static char *qdev_get_type(Object *obj, Error **errp)
{
return g_strdup(object_get_typename(obj));
@@ -1983,6 +2130,13 @@ void object_property_add_uint8_ptr(Object *obj, const char *name,
NULL, NULL, (void *)v, errp);
}
+void object_class_property_add_uint8_ptr(ObjectClass *klass, const char *name,
+ const uint8_t *v, Error **errp)
+{
+ object_class_property_add(klass, name, "uint8", property_get_uint8_ptr,
+ NULL, NULL, (void *)v, errp);
+}
+
void object_property_add_uint16_ptr(Object *obj, const char *name,
const uint16_t *v, Error **errp)
{
@@ -1990,6 +2144,13 @@ void object_property_add_uint16_ptr(Object *obj, const char *name,
NULL, NULL, (void *)v, errp);
}
+void object_class_property_add_uint16_ptr(ObjectClass *klass, const char *name,
+ const uint16_t *v, Error **errp)
+{
+ object_class_property_add(klass, name, "uint16", property_get_uint16_ptr,
+ NULL, NULL, (void *)v, errp);
+}
+
void object_property_add_uint32_ptr(Object *obj, const char *name,
const uint32_t *v, Error **errp)
{
@@ -1997,6 +2158,13 @@ void object_property_add_uint32_ptr(Object *obj, const char *name,
NULL, NULL, (void *)v, errp);
}
+void object_class_property_add_uint32_ptr(ObjectClass *klass, const char *name,
+ const uint32_t *v, Error **errp)
+{
+ object_class_property_add(klass, name, "uint32", property_get_uint32_ptr,
+ NULL, NULL, (void *)v, errp);
+}
+
void object_property_add_uint64_ptr(Object *obj, const char *name,
const uint64_t *v, Error **errp)
{
@@ -2004,6 +2172,13 @@ void object_property_add_uint64_ptr(Object *obj, const char *name,
NULL, NULL, (void *)v, errp);
}
+void object_class_property_add_uint64_ptr(ObjectClass *klass, const char *name,
+ const uint64_t *v, Error **errp)
+{
+ object_class_property_add(klass, name, "uint64", property_get_uint64_ptr,
+ NULL, NULL, (void *)v, errp);
+}
+
typedef struct {
Object *target_obj;
char *target_name;
@@ -2101,6 +2276,23 @@ void object_property_set_description(Object *obj, const char *name,
op->description = g_strdup(description);
}
+void object_class_property_set_description(ObjectClass *klass,
+ const char *name,
+ const char *description,
+ Error **errp)
+{
+ ObjectProperty *op;
+
+ op = g_hash_table_lookup(klass->properties, name);
+ if (!op) {
+ error_setg(errp, "Property '.%s' not found", name);
+ return;
+ }
+
+ g_free(op->description);
+ op->description = g_strdup(description);
+}
+
static void object_instance_init(Object *obj)
{
object_property_add_str(obj, "type", qdev_get_type, NULL, NULL);
diff --git a/tests/check-qom-proplist.c b/tests/check-qom-proplist.c
index e674c0fa89..448d270b68 100644
--- a/tests/check-qom-proplist.c
+++ b/tests/check-qom-proplist.c
@@ -123,18 +123,28 @@ static void dummy_init(Object *obj)
dummy_get_bv,
dummy_set_bv,
NULL);
- object_property_add_str(obj, "sv",
- dummy_get_sv,
- dummy_set_sv,
- NULL);
- object_property_add_enum(obj, "av",
- "DummyAnimal",
- dummy_animal_map,
- dummy_get_av,
- dummy_set_av,
- NULL);
}
+
+static void dummy_class_init(ObjectClass *cls, void *data)
+{
+ object_class_property_add_bool(cls, "bv",
+ dummy_get_bv,
+ dummy_set_bv,
+ NULL);
+ object_class_property_add_str(cls, "sv",
+ dummy_get_sv,
+ dummy_set_sv,
+ NULL);
+ object_class_property_add_enum(cls, "av",
+ "DummyAnimal",
+ dummy_animal_map,
+ dummy_get_av,
+ dummy_set_av,
+ NULL);
+}
+
+
static void dummy_finalize(Object *obj)
{
DummyObject *dobj = DUMMY_OBJECT(obj);
@@ -150,6 +160,7 @@ static const TypeInfo dummy_info = {
.instance_init = dummy_init,
.instance_finalize = dummy_finalize,
.class_size = sizeof(DummyObjectClass),
+ .class_init = dummy_class_init,
};
@@ -444,11 +455,11 @@ static void test_dummy_iterator(void)
NULL));
ObjectProperty *prop;
- ObjectPropertyIterator *iter;
+ ObjectPropertyIterator iter;
bool seenbv = false, seensv = false, seenav = false, seentype;
- iter = object_property_iter_init(OBJECT(dobj));
- while ((prop = object_property_iter_next(iter))) {
+ object_property_iter_init(&iter, OBJECT(dobj));
+ while ((prop = object_property_iter_next(&iter))) {
if (g_str_equal(prop->name, "bv")) {
seenbv = true;
} else if (g_str_equal(prop->name, "sv")) {
@@ -463,7 +474,6 @@ static void test_dummy_iterator(void)
g_assert_not_reached();
}
}
- object_property_iter_free(iter);
g_assert(seenbv);
g_assert(seenav);
g_assert(seensv);
diff --git a/vl.c b/vl.c
index b7a083eb56..f043009f67 100644
--- a/vl.c
+++ b/vl.c
@@ -1535,14 +1535,14 @@ MachineInfoList *qmp_query_machines(Error **errp)
static int machine_help_func(QemuOpts *opts, MachineState *machine)
{
ObjectProperty *prop;
- ObjectPropertyIterator *iter;
+ ObjectPropertyIterator iter;
if (!qemu_opt_has_help_opt(opts)) {
return 0;
}
- iter = object_property_iter_init(OBJECT(machine));
- while ((prop = object_property_iter_next(iter))) {
+ object_property_iter_init(&iter, OBJECT(machine));
+ while ((prop = object_property_iter_next(&iter))) {
if (!prop->set) {
continue;
}
@@ -1555,7 +1555,6 @@ static int machine_help_func(QemuOpts *opts, MachineState *machine)
error_printf("\n");
}
}
- object_property_iter_free(iter);
return 1;
}