qom: Allow properties to be registered against classes

When there are many instances of a given class, registering
properties against the instance is wasteful of resources. The
majority of objects have a statically defined list of possible
properties, so most of the properties are easily registerable
against the class. Only those properties which are conditionally
registered at runtime need be recorded against the klass.

Registering properties against classes also makes it possible
to provide static introspection of QOM - currently introspection
is only possible after creating an instance of a class, which
severely limits its usefulness.

This impl only supports simple scalar properties. It does not
attempt to allow child object / link object properties against
the class. There are ways to support those too, but it would
make this patch more complicated, so it is left as an exercise
for the future.

There is no equivalent to object_property_del() provided, since
classes must be immutable once they are defined.

Backports commit 16bf7f522a2ff68993f80631ed86254c71eaf5d4 from qemu
This commit is contained in:
Daniel P. Berrange 2018-02-21 13:58:46 -05:00 committed by Lioncash
parent 825bc2fb04
commit b97ab59f08
No known key found for this signature in database
GPG key ID: 4E3C3CC1031BA9C7
8 changed files with 350 additions and 120 deletions

View file

@ -30,7 +30,7 @@
#include "qapi/qmp/qerror.h"
static void bus_add_child(BusState *bus, DeviceState *child)
static void bus_add_child(struct uc_struct *uc, BusState *bus, DeviceState *child)
{
char name[32];
BusChild *kid = g_malloc0(sizeof(*kid));
@ -43,7 +43,7 @@ static void bus_add_child(BusState *bus, DeviceState *child)
/* This transfers ownership of kid->child to the property. */
snprintf(name, sizeof(name), "child[%d]", kid->index);
object_property_add_link(OBJECT(bus), name,
object_property_add_link(uc, OBJECT(bus), name,
object_get_typename(OBJECT(child)),
(Object **)&kid->child,
NULL, /* read-only property */
@ -51,11 +51,11 @@ static void bus_add_child(BusState *bus, DeviceState *child)
NULL);
}
void qdev_set_parent_bus(DeviceState *dev, BusState *bus)
void qdev_set_parent_bus(struct uc_struct *uc, DeviceState *dev, BusState *bus)
{
dev->parent_bus = bus;
object_ref(OBJECT(bus));
bus_add_child(bus, dev);
bus_add_child(uc, bus, dev);
}
/* Create a new device. This only initializes the device state structure

View file

@ -333,7 +333,7 @@ const char *qdev_fw_name(DeviceState *dev);
Object *qdev_get_machine(struct uc_struct *);
/* FIXME: make this a link<> */
void qdev_set_parent_bus(DeviceState *dev, BusState *bus);
void qdev_set_parent_bus(struct uc_struct *uc, DeviceState *dev, BusState *bus);
extern int qdev_hotplug;

View file

@ -381,6 +381,8 @@ struct ObjectClass
const char *class_cast_cache[OBJECT_CLASS_CAST_CACHE];
ObjectUnparent *unparent;
GHashTable *properties;
};
/**
@ -792,7 +794,8 @@ void object_unref(struct uc_struct *uc, Object *obj);
* Returns: The #ObjectProperty; this can be used to set the @resolve
* callback for child and link properties.
*/
ObjectProperty *object_property_add(Object *obj, const char *name,
ObjectProperty *object_property_add(struct uc_struct *uc, Object *obj,
const char *name,
const char *type,
ObjectPropertyAccessor *get,
ObjectPropertyAccessor *set,
@ -801,6 +804,14 @@ ObjectProperty *object_property_add(Object *obj, const char *name,
void object_property_del(struct uc_struct *uc, Object *obj, const char *name, Error **errp);
ObjectProperty *object_class_property_add(struct uc_struct *uc, ObjectClass *klass, const char *name,
const char *type,
ObjectPropertyAccessor *get,
ObjectPropertyAccessor *set,
ObjectPropertyRelease *release,
void *opaque, Error **errp);
void object_property_del_child(struct uc_struct *uc, Object *obj, Object *child, Error **errp);
/**
@ -811,8 +822,10 @@ void object_property_del_child(struct uc_struct *uc, Object *obj, Object *child,
*
* Look up a property for an object and return its #ObjectProperty if found.
*/
ObjectProperty *object_property_find(Object *obj, const char *name,
Error **errp);
ObjectProperty *object_property_find(struct uc_struct *uc, Object *obj,
const char *name, Error **errp);
ObjectProperty *object_class_property_find(struct uc_struct *uc, ObjectClass *klass,
const char *name, Error **errp);
typedef struct ObjectPropertyIterator ObjectPropertyIterator;
@ -821,7 +834,7 @@ typedef struct ObjectPropertyIterator ObjectPropertyIterator;
* @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.
@ -861,7 +874,7 @@ void object_property_iter_free(ObjectPropertyIterator *iter);
* Returns: the next property, or %NULL when all properties
* have been traversed.
*/
ObjectProperty *object_property_iter_next(ObjectPropertyIterator *iter);
ObjectProperty *object_property_iter_next(struct uc_struct *uc, ObjectPropertyIterator *iter);
void object_unparent(struct uc_struct *uc, Object *obj);
@ -875,8 +888,8 @@ void object_unparent(struct uc_struct *uc, Object *obj);
*
* Reads a property from a object.
*/
void object_property_get(struct uc_struct *uc, Object *obj, Visitor *v, const char *name,
Error **errp);
void object_property_get(struct uc_struct *uc, Object *obj, Visitor *v,
const char *name, Error **errp);
/**
* object_property_set_str:
@ -886,8 +899,9 @@ void object_property_get(struct uc_struct *uc, Object *obj, Visitor *v, const ch
*
* Writes a string value to a property.
*/
void object_property_set_str(struct uc_struct *uc, Object *obj, const char *value,
const char *name, Error **errp);
void object_property_set_str(struct uc_struct *uc, Object *obj,
const char *value, const char *name,
Error **errp);
/**
* object_property_get_str:
@ -899,8 +913,8 @@ void object_property_set_str(struct uc_struct *uc, Object *obj, const char *valu
* an error occurs (including when the property value is not a string).
* The caller should free the string.
*/
char *object_property_get_str(struct uc_struct *uc, Object *obj, const char *name,
Error **errp);
char *object_property_get_str(struct uc_struct *uc, Object *obj,
const char *name, Error **errp);
/**
* object_property_set_link:
@ -923,8 +937,8 @@ void object_property_set_link(struct uc_struct *uc, Object *obj, Object *value,
* or NULL if an error occurs (including when the property value is not a
* string or not a valid object path).
*/
Object *object_property_get_link(struct uc_struct *uc, Object *obj, const char *name,
Error **errp);
Object *object_property_get_link(struct uc_struct *uc, Object *obj,
const char *name, Error **errp);
/**
* object_property_set_bool:
@ -946,8 +960,8 @@ void object_property_set_bool(struct uc_struct *uc, Object *obj, bool value,
* Returns: the value of the property, converted to a boolean, or NULL if
* an error occurs (including when the property value is not a bool).
*/
bool object_property_get_bool(struct uc_struct *uc, Object *obj, const char *name,
Error **errp);
bool object_property_get_bool(struct uc_struct *uc, Object *obj,
const char *name, Error **errp);
/**
* object_property_set_int:
@ -969,8 +983,8 @@ void object_property_set_int(struct uc_struct *uc, Object *obj, int64_t value,
* Returns: the value of the property, converted to an integer, or negative if
* an error occurs (including when the property value is not an integer).
*/
int64_t object_property_get_int(struct uc_struct *uc, Object *obj, const char *name,
Error **errp);
int64_t object_property_get_int(struct uc_struct *uc, Object *obj,
const char *name, Error **errp);
/**
* object_property_set:
@ -983,8 +997,8 @@ int64_t object_property_get_int(struct uc_struct *uc, Object *obj, const char *n
*
* Writes a property to a object.
*/
void object_property_set(struct uc_struct *uc, Object *obj, Visitor *v, const char *name,
Error **errp);
void object_property_set(struct uc_struct *uc, Object *obj, Visitor *v,
const char *name, Error **errp);
/**
* object_property_parse:
@ -995,8 +1009,9 @@ void object_property_set(struct uc_struct *uc, Object *obj, Visitor *v, const ch
*
* Parses a string and writes the result into a property of an object.
*/
void object_property_parse(struct uc_struct *uc, Object *obj, const char *string,
const char *name, Error **errp);
void object_property_parse(struct uc_struct *uc, Object *obj,
const char *string, const char *name,
Error **errp);
/**
* object_property_get_type:
@ -1006,8 +1021,8 @@ void object_property_parse(struct uc_struct *uc, Object *obj, const char *string
*
* Returns: The type name of the property.
*/
const char *object_property_get_type(Object *obj, const char *name,
Error **errp);
const char *object_property_get_type(struct uc_struct *uc, Object *obj,
const char *name, Error **errp);
/**
* object_get_root:
@ -1055,7 +1070,8 @@ gchar *object_get_canonical_path(Object *obj);
*
* Returns: The matched object or NULL on path lookup failure.
*/
Object *object_resolve_path(struct uc_struct *uc, const char *path, bool *ambiguous);
Object *object_resolve_path(struct uc_struct *uc, const char *path,
bool *ambiguous);
/**
* object_resolve_path_type:
@ -1075,7 +1091,9 @@ Object *object_resolve_path(struct uc_struct *uc, const char *path, bool *ambigu
*
* Returns: The matched object or NULL on path lookup failure.
*/
Object *object_resolve_path_type(struct uc_struct *uc, const char *path, const char *typename,
Object *object_resolve_path_type(struct uc_struct *uc,
const char *path,
const char *typename,
bool *ambiguous);
/**
@ -1088,7 +1106,9 @@ Object *object_resolve_path_type(struct uc_struct *uc, const char *path, const c
*
* Returns: The resolved object or NULL on path lookup failure.
*/
Object *object_resolve_path_component(struct uc_struct *uc, Object *parent, const gchar *part);
Object *object_resolve_path_component(struct uc_struct *uc,
Object *parent,
const gchar *part);
/**
* object_property_add_child:
@ -1107,8 +1127,9 @@ Object *object_resolve_path_component(struct uc_struct *uc, Object *parent, cons
* canonical path. It can be retrieved using object_property_get_str().
* The child object itself can be retrieved using object_property_get_link().
*/
void object_property_add_child(Object *obj, const char *name,
Object *child, Error **errp);
void object_property_add_child(struct uc_struct *uc, Object *obj,
const char *name, Object *child,
Error **errp);
typedef enum {
/* Unref the link pointer when the property is deleted */
@ -1153,7 +1174,7 @@ void object_property_allow_set_link(Object *, const char *,
* <code>@flags</code> <code>OBJ_PROP_LINK_UNREF_ON_RELEASE</code> bit is set,
* the reference count is decremented when the property is deleted.
*/
void object_property_add_link(Object *obj, const char *name,
void object_property_add_link(struct uc_struct *uc, Object *obj, const char *name,
const char *type, Object **child,
void (*check)(Object *obj, const char *name,
Object *val, Error **errp),
@ -1172,10 +1193,16 @@ void object_property_add_link(Object *obj, const char *name,
* Add a string property using getters/setters. This function will add a
* property of type 'string'.
*/
void object_property_add_str(Object *obj, const char *name,
void object_property_add_str(struct uc_struct *uc, Object *obj, const char *name,
char *(*get)(struct uc_struct *uc, Object *, Error **),
int (*set)(struct uc_struct *uc, Object *, const char *, Error **),
Error **errp);
void object_class_property_add_str(struct uc_struct *uc, ObjectClass *klass,
const char *name,
char *(*get)(struct uc_struct *uc, Object *, Error **),
int (*set)(struct uc_struct *uc, Object *, const char *,
Error **),
Error **errp);
/**
* object_property_add_bool:
@ -1192,6 +1219,10 @@ void object_property_add_bool(struct uc_struct *uc, Object *obj, const char *nam
bool (*get)(struct uc_struct *uc, Object *, Error **),
int (*set)(struct uc_struct *uc, Object *, bool, Error **),
Error **errp);
void object_class_property_add_bool(struct uc_struct *uc, ObjectClass *klass, const char *name,
bool (*get)(struct uc_struct *, Object *, Error **),
int (*set)(struct uc_struct *, Object *, bool, Error **),
Error **errp);
/**
* object_property_add_uint8_ptr:
@ -1203,8 +1234,12 @@ void object_property_add_bool(struct uc_struct *uc, Object *obj, const char *nam
* Add an integer property in memory. This function will add a
* property of type 'uint8'.
*/
void object_property_add_uint8_ptr(Object *obj, const char *name,
const uint8_t *v, Error **errp);
void object_property_add_uint8_ptr(struct uc_struct *uc, Object *obj,
const char *name, const uint8_t *v,
Error **errp);
void object_class_property_add_uint8_ptr(struct uc_struct *uc, ObjectClass *klass,
const char *name, const uint8_t *v,
Error **errp);
/**
* object_property_add_uint16_ptr:
@ -1216,8 +1251,12 @@ void object_property_add_uint8_ptr(Object *obj, const char *name,
* Add an integer property in memory. This function will add a
* property of type 'uint16'.
*/
void object_property_add_uint16_ptr(Object *obj, const char *name,
const uint16_t *v, Error **errp);
void object_property_add_uint16_ptr(struct uc_struct *uc, Object *obj,
const char *name, const uint16_t *v,
Error **errp);
void object_class_property_add_uint16_ptr(struct uc_struct *uc, ObjectClass *klass,
const char *name, const uint16_t *v,
Error **errp);
/**
* object_property_add_uint32_ptr:
@ -1229,8 +1268,12 @@ void object_property_add_uint16_ptr(Object *obj, const char *name,
* Add an integer property in memory. This function will add a
* property of type 'uint32'.
*/
void object_property_add_uint32_ptr(Object *obj, const char *name,
const uint32_t *v, Error **errp);
void object_property_add_uint32_ptr(struct uc_struct *uc, Object *obj,
const char *name, const uint32_t *v,
Error **errp);
void object_class_property_add_uint32_ptr(struct uc_struct *uc, ObjectClass *klass,
const char *name, const uint32_t *v,
Error **errp);
/**
* object_property_add_uint64_ptr:
@ -1242,8 +1285,12 @@ void object_property_add_uint32_ptr(Object *obj, const char *name,
* Add an integer property in memory. This function will add a
* property of type 'uint64'.
*/
void object_property_add_uint64_ptr(Object *obj, const char *name,
const uint64_t *v, Error **Errp);
void object_property_add_uint64_ptr(struct uc_struct *uc, Object *obj,
const char *name, const uint64_t *v,
Error **Errp);
void object_class_property_add_uint64_ptr(struct uc_struct *uc, ObjectClass *klass,
const char *name, const uint64_t *v,
Error **Errp);
/**
* object_property_add_alias:
@ -1261,7 +1308,7 @@ void object_property_add_uint64_ptr(Object *obj, const char *name,
* object this will be the case. For aliases to other objects the caller is
* responsible for taking a reference.
*/
void object_property_add_alias(Object *obj, const char *name,
void object_property_add_alias(struct uc_struct *uc, Object *obj, const char *name,
Object *target_obj, const char *target_name,
Error **errp);
@ -1275,8 +1322,12 @@ void object_property_add_alias(Object *obj, const char *name,
* Set an object property's description.
*
*/
void object_property_set_description(Object *obj, const char *name,
const char *description, Error **errp);
void object_property_set_description(struct uc_struct *uc, Object *obj,
const char *name, const char *description,
Error **errp);
void object_class_property_set_description(struct uc_struct *uc, ObjectClass *klass,
const char *name, const char *description,
Error **errp);
/**
* object_child_foreach:

View file

@ -877,7 +877,7 @@ void memory_region_init(struct uc_struct *uc, MemoryRegion *mr,
uc->owner = owner;
}
object_property_add_child(owner, name_array, OBJECT(mr), &error_abort);
object_property_add_child(uc, owner, name_array, OBJECT(mr), &error_abort);
object_unref(uc, OBJECT(mr));
g_free(name_array);
g_free(escaped_name);
@ -961,18 +961,18 @@ static void memory_region_initfn(struct uc_struct *uc, Object *obj, void *opaque
mr->destructor = memory_region_destructor_none;
QTAILQ_INIT(&mr->subregions);
op = object_property_add(OBJECT(mr), "container",
op = object_property_add(mr->uc, OBJECT(mr), "container",
"link<" TYPE_MEMORY_REGION ">",
memory_region_get_container,
NULL, /* memory_region_set_container */
NULL, NULL, &error_abort);
op->resolve = memory_region_resolve_container;
object_property_add(OBJECT(mr), "addr", "uint64",
object_property_add(mr->uc, OBJECT(mr), "addr", "uint64",
memory_region_get_addr,
NULL, /* memory_region_set_addr */
NULL, NULL, &error_abort);
object_property_add(OBJECT(mr), "priority", "uint32",
object_property_add(mr->uc, OBJECT(mr), "priority", "uint32",
memory_region_get_priority,
NULL, /* memory_region_set_priority */
NULL, NULL, &error_abort);
@ -980,7 +980,7 @@ static void memory_region_initfn(struct uc_struct *uc, Object *obj, void *opaque
memory_region_get_may_overlap,
NULL, /* memory_region_set_may_overlap */
&error_abort);
object_property_add(OBJECT(mr), "size", "uint64",
object_property_add(mr->uc, OBJECT(mr), "size", "uint64",
memory_region_get_size,
NULL, /* memory_region_set_size, */
NULL, NULL, &error_abort);

View file

@ -40,7 +40,7 @@ Object *container_get(struct uc_struct *uc, Object *root, const char *path)
child = object_resolve_path_component(uc, obj, parts[i]);
if (!child) {
child = object_new(uc, "container");
object_property_add_child(obj, parts[i], child, NULL);
object_property_add_child(uc, obj, parts[i], child, NULL);
}
}

View file

@ -67,6 +67,7 @@ struct TypeImpl
};
struct ObjectPropertyIterator {
ObjectClass *nextclass;
GHashTableIter iter;
};
@ -241,6 +242,16 @@ static void type_initialize_interface(struct uc_struct *uc, TypeImpl *ti, TypeIm
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(struct uc_struct *uc, TypeImpl *ti)
{
TypeImpl *parent;
@ -263,6 +274,8 @@ static void type_initialize(struct uc_struct *uc, TypeImpl *ti)
g_assert(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;
@ -287,6 +300,9 @@ static void type_initialize(struct uc_struct *uc, TypeImpl *ti)
type_initialize_interface(uc, 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;
@ -325,16 +341,6 @@ static void object_post_init_with_type(struct uc_struct *uc, Object *obj, TypeIm
}
}
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 object_initialize_with_type(struct uc_struct *uc, void *data, size_t size, TypeImpl *type)
{
Object *obj = data;
@ -771,7 +777,8 @@ void object_unref(struct uc_struct *uc, Object *obj)
}
ObjectProperty *
object_property_add(Object *obj, const char *name, const char *type,
object_property_add(struct uc_struct *uc, Object *obj,
const char *name, const char *type,
ObjectPropertyAccessor *get,
ObjectPropertyAccessor *set,
ObjectPropertyRelease *release,
@ -789,7 +796,7 @@ object_property_add(Object *obj, const char *name, const char *type,
for (i = 0; ; ++i) {
char *full_name = g_strdup_printf("%s[%d]", name_no_array, i);
ret = object_property_add(obj, full_name, type, get, set,
ret = object_property_add(uc, obj, full_name, type, get, set,
release, opaque, NULL);
g_free(full_name);
if (ret) {
@ -800,7 +807,7 @@ 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(uc, obj, name, NULL) != NULL) {
error_setg(errp, "attempt to add duplicate property '%s'"
" to object (type '%s')", name,
object_get_typename(obj));
@ -821,11 +828,52 @@ object_property_add(Object *obj, const char *name, const char *type,
return prop;
}
ObjectProperty *object_property_find(Object *obj, const char *name,
ObjectProperty *
object_class_property_add(struct uc_struct *uc,
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(uc, 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(struct uc_struct *uc, Object *obj,
const char *name, Error **errp)
{
ObjectProperty *prop;
ObjectClass *klass = object_get_class(obj);
prop = object_class_property_find(uc, klass, name, NULL);
if (prop) {
return prop;
}
prop = g_hash_table_lookup(obj->properties, name);
if (prop) {
return prop;
@ -839,6 +887,7 @@ ObjectPropertyIterator *object_property_iter_init(Object *obj)
{
ObjectPropertyIterator *ret = g_new0(ObjectPropertyIterator, 1);
g_hash_table_iter_init(&ret->iter, obj->properties);
ret->nextclass = object_get_class(obj);
return ret;
}
@ -850,15 +899,40 @@ void object_property_iter_free(ObjectPropertyIterator *iter)
g_free(iter);
}
ObjectProperty *object_property_iter_next(ObjectPropertyIterator *iter)
ObjectProperty *object_property_iter_next(struct uc_struct *uc, ObjectPropertyIterator *iter)
{
gpointer key, val;
if (!g_hash_table_iter_next(&iter->iter, &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(uc, iter->nextclass);
}
return val;
}
ObjectProperty *object_class_property_find(struct uc_struct *uc, ObjectClass *klass,
const char *name, Error **errp)
{
ObjectProperty *prop;
ObjectClass *parent_klass;
parent_klass = object_class_get_parent(uc, klass);
if (parent_klass) {
prop = object_class_property_find(uc, parent_klass, name, NULL);
if (prop) {
return prop;
}
}
prop = g_hash_table_lookup(klass->properties, name);
if (!prop) {
error_setg(errp, "Property '.%s' not found", name);
}
return prop;
}
void object_property_del(struct uc_struct *uc, Object *obj, const char *name, Error **errp)
{
ObjectProperty *prop = g_hash_table_lookup(obj->properties, name);
@ -875,10 +949,10 @@ void object_property_del(struct uc_struct *uc, Object *obj, const char *name, Er
g_hash_table_remove(obj->properties, name);
}
void object_property_get(struct uc_struct *uc, Object *obj, Visitor *v, const char *name,
Error **errp)
void object_property_get(struct uc_struct *uc, Object *obj, Visitor *v,
const char *name, Error **errp)
{
ObjectProperty *prop = object_property_find(obj, name, errp);
ObjectProperty *prop = object_property_find(uc, obj, name, errp);
if (prop == NULL) {
return;
}
@ -890,10 +964,10 @@ void object_property_get(struct uc_struct *uc, Object *obj, Visitor *v, const ch
}
}
void object_property_set(struct uc_struct *uc, Object *obj, Visitor *v, const char *name,
Error **errp)
void object_property_set(struct uc_struct *uc, Object *obj, Visitor *v,
const char *name, Error **errp)
{
ObjectProperty *prop = object_property_find(obj, name, errp);
ObjectProperty *prop = object_property_find(uc, obj, name, errp);
if (prop == NULL) {
return;
}
@ -1038,9 +1112,10 @@ void object_property_parse(struct uc_struct *uc, Object *obj, const char *string
string_input_visitor_cleanup(siv);
}
const char *object_property_get_type(Object *obj, const char *name, Error **errp)
const char *object_property_get_type(struct uc_struct *uc, Object *obj,
const char *name, Error **errp)
{
ObjectProperty *prop = object_property_find(obj, name, errp);
ObjectProperty *prop = object_property_find(uc, obj, name, errp);
if (prop == NULL) {
return NULL;
}
@ -1085,8 +1160,9 @@ static void object_finalize_child_property(struct uc_struct *uc, Object *obj, co
object_unref(uc, child);
}
void object_property_add_child(Object *obj, const char *name,
Object *child, Error **errp)
void object_property_add_child(struct uc_struct *uc, Object *obj,
const char *name, Object *child,
Error **errp)
{
Error *local_err = NULL;
gchar *type;
@ -1099,7 +1175,7 @@ void object_property_add_child(Object *obj, const char *name,
type = g_strdup_printf("child<%s>", object_get_typename(OBJECT(child)));
op = object_property_add(obj, name, type, object_get_child_property, NULL,
op = object_property_add(uc, obj, name, type, object_get_child_property, NULL,
object_finalize_child_property, child, &local_err);
if (local_err) {
error_propagate(errp, local_err);
@ -1163,7 +1239,7 @@ static Object *object_resolve_link(struct uc_struct *uc, Object *obj, const char
Object *target;
/* Go from link<FOO> to FOO. */
type = object_property_get_type(obj, name, NULL);
type = object_property_get_type(uc, obj, name, NULL);
target_type = g_strndup(&type[5], strlen(type) - 6);
target = object_resolve_path_type(uc, path, target_type, &ambiguous);
@ -1238,7 +1314,7 @@ static void object_release_link_property(struct uc_struct *uc, Object *obj, cons
g_free(prop);
}
void object_property_add_link(Object *obj, const char *name,
void object_property_add_link(struct uc_struct *uc, Object *obj, const char *name,
const char *type, Object **child,
void (*check)(Object *, const char *,
Object *, Error **),
@ -1256,7 +1332,7 @@ void object_property_add_link(Object *obj, const char *name,
full_type = g_strdup_printf("link<%s>", type);
op = object_property_add(obj, name, full_type,
op = object_property_add(uc, obj, name, full_type,
object_get_link_property,
check ? object_set_link_property : NULL,
object_release_link_property,
@ -1326,7 +1402,7 @@ gchar *object_get_canonical_path(Object *obj)
Object *object_resolve_path_component(struct uc_struct *uc, Object *parent, const gchar *part)
{
ObjectProperty *prop = object_property_find(parent, part, NULL);
ObjectProperty *prop = object_property_find(uc, parent, part, NULL);
if (prop == NULL) {
return NULL;
}
@ -1480,7 +1556,7 @@ static void property_release_str(struct uc_struct *uc, Object *obj, const char *
g_free(prop);
}
void object_property_add_str(Object *obj, const char *name,
void object_property_add_str(struct uc_struct *uc, Object *obj, const char *name,
char *(*get)(struct uc_struct *uc, Object *, Error **),
int (*set)(struct uc_struct *uc, Object *, const char *, Error **),
Error **errp)
@ -1491,7 +1567,30 @@ void object_property_add_str(Object *obj, const char *name,
prop->get = get;
prop->set = set;
object_property_add(obj, name, "string",
object_property_add(uc, obj, 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);
}
}
void object_class_property_add_str(struct uc_struct *uc, ObjectClass *klass, const char *name,
char *(*get)(struct uc_struct *, Object *, Error **),
int (*set)(struct uc_struct *, 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(uc, klass, name, "string",
get ? property_get_str : NULL,
set ? property_set_str : NULL,
property_release_str,
@ -1556,7 +1655,30 @@ void object_property_add_bool(struct uc_struct *uc, Object *obj, const char *nam
prop->get = get;
prop->set = set;
object_property_add(obj, name, "bool",
object_property_add(uc, obj, 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);
}
}
void object_class_property_add_bool(struct uc_struct *uc, ObjectClass *klass,
const char *name,
bool (*get)(struct uc_struct *, Object *, Error **),
int (*set)(struct uc_struct *, 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(uc, klass, name, "bool",
get ? property_get_bool : NULL,
set ? property_set_bool : NULL,
property_release_bool,
@ -1604,31 +1726,67 @@ static void property_get_uint64_ptr(struct uc_struct *uc, Object *obj, Visitor *
visit_type_uint64(v, name, &value, errp);
}
void object_property_add_uint8_ptr(Object *obj, const char *name,
const uint8_t *v, Error **errp)
void object_class_property_add_uint8_ptr(struct uc_struct *uc, ObjectClass *klass,
const char *name, const uint8_t *v,
Error **errp)
{
object_property_add(obj, name, "uint8", property_get_uint8_ptr,
object_class_property_add(uc, 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)
void object_property_add_uint8_ptr(struct uc_struct *uc, Object *obj,
const char *name, const uint8_t *v,
Error **errp)
{
object_property_add(obj, name, "uint16", property_get_uint16_ptr,
object_property_add(uc, obj, name, "uint8", property_get_uint8_ptr,
NULL, NULL, (void *)v, errp);
}
void object_property_add_uint32_ptr(Object *obj, const char *name,
const uint32_t *v, Error **errp)
void object_class_property_add_uint16_ptr(struct uc_struct *uc, ObjectClass *klass,
const char *name, const uint16_t *v,
Error **errp)
{
object_property_add(obj, name, "uint32", property_get_uint32_ptr,
object_class_property_add(uc, klass, name, "uint16", property_get_uint16_ptr,
NULL, NULL, (void *)v, errp);
}
void object_property_add_uint64_ptr(Object *obj, const char *name,
const uint64_t *v, Error **errp)
void object_property_add_uint16_ptr(struct uc_struct *uc, Object *obj,
const char *name, const uint16_t *v,
Error **errp)
{
object_property_add(obj, name, "uint64", property_get_uint64_ptr,
object_property_add(uc, obj, name, "uint16", property_get_uint16_ptr,
NULL, NULL, (void *)v, errp);
}
void object_class_property_add_uint32_ptr(struct uc_struct *uc, ObjectClass *klass,
const char *name, const uint32_t *v,
Error **errp)
{
object_class_property_add(uc, klass, name, "uint32", property_get_uint32_ptr,
NULL, NULL, (void *)v, errp);
}
void object_property_add_uint32_ptr(struct uc_struct *uc, Object *obj,
const char *name, const uint32_t *v,
Error **errp)
{
object_property_add(uc, obj, name, "uint32", property_get_uint32_ptr,
NULL, NULL, (void *)v, errp);
}
void object_class_property_add_uint64_ptr(struct uc_struct *uc, ObjectClass *klass,
const char *name, const uint64_t *v,
Error **errp)
{
object_class_property_add(uc, klass, name, "uint64", property_get_uint64_ptr,
NULL, NULL, (void *)v, errp);
}
void object_property_add_uint64_ptr(struct uc_struct *uc, Object *obj,
const char *name, const uint64_t *v,
Error **errp)
{
object_property_add(uc, obj, name, "uint64", property_get_uint64_ptr,
NULL, NULL, (void *)v, errp);
}
@ -1673,8 +1831,9 @@ static void property_release_alias(struct uc_struct *uc, Object *obj, const char
g_free(prop);
}
void object_property_add_alias(Object *obj, const char *name,
Object *target_obj, const char *target_name,
void object_property_add_alias(struct uc_struct *uc, Object *obj,
const char *name, Object *target_obj,
const char *target_name,
Error **errp)
{
AliasProperty *prop;
@ -1683,7 +1842,7 @@ void object_property_add_alias(Object *obj, const char *name,
gchar *prop_type;
Error *local_err = NULL;
target_prop = object_property_find(target_obj, target_name, errp);
target_prop = object_property_find(uc, target_obj, target_name, errp);
if (!target_prop) {
return;
}
@ -1699,7 +1858,7 @@ void object_property_add_alias(Object *obj, const char *name,
prop->target_obj = target_obj;
prop->target_name = g_strdup(target_name);
op = object_property_add(obj, name, prop_type,
op = object_property_add(uc, obj, name, prop_type,
property_get_alias,
property_set_alias,
property_release_alias,
@ -1711,7 +1870,7 @@ void object_property_add_alias(Object *obj, const char *name,
}
op->resolve = property_resolve_alias;
object_property_set_description(obj, op->name,
object_property_set_description(uc, obj, op->name,
target_prop->description,
&error_abort);
@ -1719,12 +1878,13 @@ out:
g_free(prop_type);
}
void object_property_set_description(Object *obj, const char *name,
const char *description, Error **errp)
void object_property_set_description(struct uc_struct *uc, Object *obj,
const char *name, const char *description,
Error **errp)
{
ObjectProperty *op;
op = object_property_find(obj, name, errp);
op = object_property_find(uc, obj, name, errp);
if (!op) {
return;
}
@ -1733,9 +1893,27 @@ void object_property_set_description(Object *obj, const char *name,
op->description = g_strdup(description);
}
void object_class_property_set_description(struct uc_struct *uc,
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(struct uc_struct *uc, Object *obj, void *opaque)
{
object_property_add_str(obj, "type", qdev_get_type, NULL, NULL);
object_property_add_str(uc, obj, "type", qdev_get_type, NULL, NULL);
}
void register_types_object(struct uc_struct *uc)

View file

@ -2851,31 +2851,31 @@ static void x86_cpu_initfn(struct uc_struct *uc, Object *obj, void *opaque)
cs->env_ptr = env;
cpu_exec_init(cs, opaque);
object_property_add(obj, "family", "int",
object_property_add(uc, obj, "family", "int",
x86_cpuid_version_get_family,
x86_cpuid_version_set_family, NULL, NULL, NULL);
object_property_add(obj, "model", "int",
object_property_add(uc, obj, "model", "int",
x86_cpuid_version_get_model,
x86_cpuid_version_set_model, NULL, NULL, NULL);
object_property_add(obj, "stepping", "int",
object_property_add(uc, obj, "stepping", "int",
x86_cpuid_version_get_stepping,
x86_cpuid_version_set_stepping, NULL, NULL, NULL);
object_property_add_str(obj, "vendor",
object_property_add_str(uc, obj, "vendor",
x86_cpuid_get_vendor,
x86_cpuid_set_vendor, NULL);
object_property_add_str(obj, "model-id",
object_property_add_str(uc, obj, "model-id",
x86_cpuid_get_model_id,
x86_cpuid_set_model_id, NULL);
object_property_add(obj, "tsc-frequency", "int",
object_property_add(uc, obj, "tsc-frequency", "int",
x86_cpuid_get_tsc_freq,
x86_cpuid_set_tsc_freq, NULL, NULL, NULL);
object_property_add(obj, "apic-id", "int",
object_property_add(uc, obj, "apic-id", "int",
x86_cpuid_get_apic_id,
x86_cpuid_set_apic_id, NULL, NULL, NULL);
object_property_add(obj, "feature-words", "X86CPUFeatureWordInfo",
object_property_add(uc, obj, "feature-words", "X86CPUFeatureWordInfo",
x86_cpu_get_feature_words,
NULL, NULL, (void *)env->features, NULL);
object_property_add(obj, "filtered-features", "X86CPUFeatureWordInfo",
object_property_add(uc, obj, "filtered-features", "X86CPUFeatureWordInfo",
x86_cpu_get_feature_words,
NULL, NULL, (void *)cpu->filtered_features, NULL);

1
uc.c
View file

@ -28,6 +28,7 @@
static void free_table(gpointer key, gpointer value, gpointer data)
{
TypeInfo *ti = (TypeInfo*) value;
g_hash_table_destroy(ti->class->properties);
g_free((void *) ti->class);
g_free((void *) ti->name);
g_free((void *) ti->parent);