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" #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]; char name[32];
BusChild *kid = g_malloc0(sizeof(*kid)); 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. */ /* This transfers ownership of kid->child to the property. */
snprintf(name, sizeof(name), "child[%d]", kid->index); 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_get_typename(OBJECT(child)),
(Object **)&kid->child, (Object **)&kid->child,
NULL, /* read-only property */ NULL, /* read-only property */
@ -51,11 +51,11 @@ static void bus_add_child(BusState *bus, DeviceState *child)
NULL); 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; dev->parent_bus = bus;
object_ref(OBJECT(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 /* 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 *); Object *qdev_get_machine(struct uc_struct *);
/* FIXME: make this a link<> */ /* 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; extern int qdev_hotplug;

View file

@ -381,6 +381,8 @@ struct ObjectClass
const char *class_cast_cache[OBJECT_CLASS_CAST_CACHE]; const char *class_cast_cache[OBJECT_CLASS_CAST_CACHE];
ObjectUnparent *unparent; 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 * Returns: The #ObjectProperty; this can be used to set the @resolve
* callback for child and link properties. * 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, const char *type,
ObjectPropertyAccessor *get, ObjectPropertyAccessor *get,
ObjectPropertyAccessor *set, 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); 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); 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. * Look up a property for an object and return its #ObjectProperty if found.
*/ */
ObjectProperty *object_property_find(Object *obj, const char *name, ObjectProperty *object_property_find(struct uc_struct *uc, Object *obj,
Error **errp); 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; typedef struct ObjectPropertyIterator ObjectPropertyIterator;
@ -821,7 +834,7 @@ typedef struct ObjectPropertyIterator ObjectPropertyIterator;
* @obj: the object * @obj: the object
* *
* Initializes an iterator for traversing all properties * 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, * It is forbidden to modify the property list while iterating,
* whether removing or adding properties. * 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 * Returns: the next property, or %NULL when all properties
* have been traversed. * 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); 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. * Reads a property from a object.
*/ */
void object_property_get(struct uc_struct *uc, Object *obj, Visitor *v, const char *name, void object_property_get(struct uc_struct *uc, Object *obj, Visitor *v,
Error **errp); const char *name, Error **errp);
/** /**
* object_property_set_str: * 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. * Writes a string value to a property.
*/ */
void object_property_set_str(struct uc_struct *uc, Object *obj, const char *value, void object_property_set_str(struct uc_struct *uc, Object *obj,
const char *name, Error **errp); const char *value, const char *name,
Error **errp);
/** /**
* object_property_get_str: * 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). * an error occurs (including when the property value is not a string).
* The caller should free the string. * The caller should free the string.
*/ */
char *object_property_get_str(struct uc_struct *uc, Object *obj, const char *name, char *object_property_get_str(struct uc_struct *uc, Object *obj,
Error **errp); const char *name, Error **errp);
/** /**
* object_property_set_link: * 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 * or NULL if an error occurs (including when the property value is not a
* string or not a valid object path). * string or not a valid object path).
*/ */
Object *object_property_get_link(struct uc_struct *uc, Object *obj, const char *name, Object *object_property_get_link(struct uc_struct *uc, Object *obj,
Error **errp); const char *name, Error **errp);
/** /**
* object_property_set_bool: * 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 * 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). * 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, bool object_property_get_bool(struct uc_struct *uc, Object *obj,
Error **errp); const char *name, Error **errp);
/** /**
* object_property_set_int: * 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 * 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). * 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, int64_t object_property_get_int(struct uc_struct *uc, Object *obj,
Error **errp); const char *name, Error **errp);
/** /**
* object_property_set: * 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. * Writes a property to a object.
*/ */
void object_property_set(struct uc_struct *uc, Object *obj, Visitor *v, const char *name, void object_property_set(struct uc_struct *uc, Object *obj, Visitor *v,
Error **errp); const char *name, Error **errp);
/** /**
* object_property_parse: * 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. * 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, void object_property_parse(struct uc_struct *uc, Object *obj,
const char *name, Error **errp); const char *string, const char *name,
Error **errp);
/** /**
* object_property_get_type: * 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. * Returns: The type name of the property.
*/ */
const char *object_property_get_type(Object *obj, const char *name, const char *object_property_get_type(struct uc_struct *uc, Object *obj,
Error **errp); const char *name, Error **errp);
/** /**
* object_get_root: * object_get_root:
@ -1055,7 +1070,8 @@ gchar *object_get_canonical_path(Object *obj);
* *
* Returns: The matched object or NULL on path lookup failure. * 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: * 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. * 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); 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. * 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: * 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(). * canonical path. It can be retrieved using object_property_get_str().
* The child object itself can be retrieved using object_property_get_link(). * The child object itself can be retrieved using object_property_get_link().
*/ */
void object_property_add_child(Object *obj, const char *name, void object_property_add_child(struct uc_struct *uc, Object *obj,
Object *child, Error **errp); const char *name, Object *child,
Error **errp);
typedef enum { typedef enum {
/* Unref the link pointer when the property is deleted */ /* 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, * <code>@flags</code> <code>OBJ_PROP_LINK_UNREF_ON_RELEASE</code> bit is set,
* the reference count is decremented when the property is deleted. * 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, const char *type, Object **child,
void (*check)(Object *obj, const char *name, void (*check)(Object *obj, const char *name,
Object *val, Error **errp), 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 * Add a string property using getters/setters. This function will add a
* property of type 'string'. * 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 **), char *(*get)(struct uc_struct *uc, Object *, Error **),
int (*set)(struct uc_struct *uc, Object *, const char *, Error **), int (*set)(struct uc_struct *uc, Object *, const char *, Error **),
Error **errp); 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: * 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 **), bool (*get)(struct uc_struct *uc, Object *, Error **),
int (*set)(struct uc_struct *uc, Object *, bool, Error **), int (*set)(struct uc_struct *uc, Object *, bool, Error **),
Error **errp); 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: * 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 * Add an integer property in memory. This function will add a
* property of type 'uint8'. * property of type 'uint8'.
*/ */
void object_property_add_uint8_ptr(Object *obj, const char *name, void object_property_add_uint8_ptr(struct uc_struct *uc, Object *obj,
const uint8_t *v, Error **errp); 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: * 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 * Add an integer property in memory. This function will add a
* property of type 'uint16'. * property of type 'uint16'.
*/ */
void object_property_add_uint16_ptr(Object *obj, const char *name, void object_property_add_uint16_ptr(struct uc_struct *uc, Object *obj,
const uint16_t *v, Error **errp); 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: * 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 * Add an integer property in memory. This function will add a
* property of type 'uint32'. * property of type 'uint32'.
*/ */
void object_property_add_uint32_ptr(Object *obj, const char *name, void object_property_add_uint32_ptr(struct uc_struct *uc, Object *obj,
const uint32_t *v, Error **errp); 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: * 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 * Add an integer property in memory. This function will add a
* property of type 'uint64'. * property of type 'uint64'.
*/ */
void object_property_add_uint64_ptr(Object *obj, const char *name, void object_property_add_uint64_ptr(struct uc_struct *uc, Object *obj,
const uint64_t *v, Error **Errp); 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: * 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 * object this will be the case. For aliases to other objects the caller is
* responsible for taking a reference. * 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, Object *target_obj, const char *target_name,
Error **errp); Error **errp);
@ -1275,8 +1322,12 @@ void object_property_add_alias(Object *obj, const char *name,
* Set an object property's description. * Set an object property's description.
* *
*/ */
void object_property_set_description(Object *obj, const char *name, void object_property_set_description(struct uc_struct *uc, Object *obj,
const char *description, Error **errp); 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: * object_child_foreach:

View file

@ -877,7 +877,7 @@ void memory_region_init(struct uc_struct *uc, MemoryRegion *mr,
uc->owner = owner; 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)); object_unref(uc, OBJECT(mr));
g_free(name_array); g_free(name_array);
g_free(escaped_name); 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; mr->destructor = memory_region_destructor_none;
QTAILQ_INIT(&mr->subregions); QTAILQ_INIT(&mr->subregions);
op = object_property_add(OBJECT(mr), "container", op = object_property_add(mr->uc, OBJECT(mr), "container",
"link<" TYPE_MEMORY_REGION ">", "link<" TYPE_MEMORY_REGION ">",
memory_region_get_container, memory_region_get_container,
NULL, /* memory_region_set_container */ NULL, /* memory_region_set_container */
NULL, NULL, &error_abort); NULL, NULL, &error_abort);
op->resolve = memory_region_resolve_container; 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, memory_region_get_addr,
NULL, /* memory_region_set_addr */ NULL, /* memory_region_set_addr */
NULL, NULL, &error_abort); NULL, NULL, &error_abort);
object_property_add(OBJECT(mr), "priority", "uint32", object_property_add(mr->uc, OBJECT(mr), "priority", "uint32",
memory_region_get_priority, memory_region_get_priority,
NULL, /* memory_region_set_priority */ NULL, /* memory_region_set_priority */
NULL, NULL, &error_abort); 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, memory_region_get_may_overlap,
NULL, /* memory_region_set_may_overlap */ NULL, /* memory_region_set_may_overlap */
&error_abort); &error_abort);
object_property_add(OBJECT(mr), "size", "uint64", object_property_add(mr->uc, OBJECT(mr), "size", "uint64",
memory_region_get_size, memory_region_get_size,
NULL, /* memory_region_set_size, */ NULL, /* memory_region_set_size, */
NULL, NULL, &error_abort); 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]); child = object_resolve_path_component(uc, obj, parts[i]);
if (!child) { if (!child) {
child = object_new(uc, "container"); 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 { struct ObjectPropertyIterator {
ObjectClass *nextclass;
GHashTableIter iter; GHashTableIter iter;
}; };
@ -241,6 +242,16 @@ static void type_initialize_interface(struct uc_struct *uc, TypeImpl *ti, TypeIm
iface_impl->class); 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) static void type_initialize(struct uc_struct *uc, TypeImpl *ti)
{ {
TypeImpl *parent; TypeImpl *parent;
@ -263,6 +274,8 @@ static void type_initialize(struct uc_struct *uc, TypeImpl *ti)
g_assert(parent->class_size <= ti->class_size); g_assert(parent->class_size <= ti->class_size);
memcpy(ti->class, parent->class, parent->class_size); memcpy(ti->class, parent->class, parent->class_size);
ti->class->interfaces = NULL; 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) { for (e = parent->class->interfaces; e; e = e->next) {
InterfaceClass *iface = e->data; 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); 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; 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) static void object_initialize_with_type(struct uc_struct *uc, void *data, size_t size, TypeImpl *type)
{ {
Object *obj = data; Object *obj = data;
@ -771,7 +777,8 @@ void object_unref(struct uc_struct *uc, Object *obj)
} }
ObjectProperty * 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 *get,
ObjectPropertyAccessor *set, ObjectPropertyAccessor *set,
ObjectPropertyRelease *release, ObjectPropertyRelease *release,
@ -789,7 +796,7 @@ object_property_add(Object *obj, const char *name, const char *type,
for (i = 0; ; ++i) { for (i = 0; ; ++i) {
char *full_name = g_strdup_printf("%s[%d]", name_no_array, 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); release, opaque, NULL);
g_free(full_name); g_free(full_name);
if (ret) { if (ret) {
@ -800,10 +807,10 @@ object_property_add(Object *obj, const char *name, const char *type,
return ret; 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'" error_setg(errp, "attempt to add duplicate property '%s'"
" to object (type '%s')", name, " to object (type '%s')", name,
object_get_typename(obj)); object_get_typename(obj));
return NULL; return NULL;
} }
@ -821,11 +828,52 @@ object_property_add(Object *obj, const char *name, const char *type,
return prop; return prop;
} }
ObjectProperty *object_property_find(Object *obj, const char *name, ObjectProperty *
Error **errp) 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; 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); prop = g_hash_table_lookup(obj->properties, name);
if (prop) { if (prop) {
return prop; return prop;
@ -839,6 +887,7 @@ ObjectPropertyIterator *object_property_iter_init(Object *obj)
{ {
ObjectPropertyIterator *ret = g_new0(ObjectPropertyIterator, 1); ObjectPropertyIterator *ret = g_new0(ObjectPropertyIterator, 1);
g_hash_table_iter_init(&ret->iter, obj->properties); g_hash_table_iter_init(&ret->iter, obj->properties);
ret->nextclass = object_get_class(obj);
return ret; return ret;
} }
@ -850,15 +899,40 @@ void object_property_iter_free(ObjectPropertyIterator *iter)
g_free(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; gpointer key, val;
if (!g_hash_table_iter_next(&iter->iter, &key, &val)) { while (!g_hash_table_iter_next(&iter->iter, &key, &val)) {
return NULL; 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; 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) void object_property_del(struct uc_struct *uc, Object *obj, const char *name, Error **errp)
{ {
ObjectProperty *prop = g_hash_table_lookup(obj->properties, name); 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); g_hash_table_remove(obj->properties, name);
} }
void object_property_get(struct uc_struct *uc, Object *obj, Visitor *v, const char *name, void object_property_get(struct uc_struct *uc, Object *obj, Visitor *v,
Error **errp) 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) { if (prop == NULL) {
return; 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, void object_property_set(struct uc_struct *uc, Object *obj, Visitor *v,
Error **errp) 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) { if (prop == NULL) {
return; return;
} }
@ -1038,9 +1112,10 @@ void object_property_parse(struct uc_struct *uc, Object *obj, const char *string
string_input_visitor_cleanup(siv); 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) { if (prop == NULL) {
return NULL; return NULL;
} }
@ -1085,8 +1160,9 @@ static void object_finalize_child_property(struct uc_struct *uc, Object *obj, co
object_unref(uc, child); object_unref(uc, child);
} }
void object_property_add_child(Object *obj, const char *name, void object_property_add_child(struct uc_struct *uc, Object *obj,
Object *child, Error **errp) const char *name, Object *child,
Error **errp)
{ {
Error *local_err = NULL; Error *local_err = NULL;
gchar *type; 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))); 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); object_finalize_child_property, child, &local_err);
if (local_err) { if (local_err) {
error_propagate(errp, 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; Object *target;
/* Go from link<FOO> to FOO. */ /* 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_type = g_strndup(&type[5], strlen(type) - 6);
target = object_resolve_path_type(uc, path, target_type, &ambiguous); 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); 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, const char *type, Object **child,
void (*check)(Object *, const char *, void (*check)(Object *, const char *,
Object *, Error **), Object *, Error **),
@ -1256,7 +1332,7 @@ void object_property_add_link(Object *obj, const char *name,
full_type = g_strdup_printf("link<%s>", type); 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, object_get_link_property,
check ? object_set_link_property : NULL, check ? object_set_link_property : NULL,
object_release_link_property, 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) 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) { if (prop == NULL) {
return NULL; return NULL;
} }
@ -1480,7 +1556,7 @@ static void property_release_str(struct uc_struct *uc, Object *obj, const char *
g_free(prop); 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 **), char *(*get)(struct uc_struct *uc, Object *, Error **),
int (*set)(struct uc_struct *uc, Object *, const char *, Error **), int (*set)(struct uc_struct *uc, Object *, const char *, Error **),
Error **errp) Error **errp)
@ -1491,7 +1567,7 @@ void object_property_add_str(Object *obj, const char *name,
prop->get = get; prop->get = get;
prop->set = set; prop->set = set;
object_property_add(obj, name, "string", object_property_add(uc, obj, name, "string",
get ? property_get_str : NULL, get ? property_get_str : NULL,
set ? property_set_str : NULL, set ? property_set_str : NULL,
property_release_str, property_release_str,
@ -1502,6 +1578,29 @@ void object_property_add_str(Object *obj, const char *name,
} }
} }
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,
prop, &local_err);
if (local_err) {
error_propagate(errp, local_err);
g_free(prop);
}
}
typedef struct BoolProperty typedef struct BoolProperty
{ {
bool (*get)(struct uc_struct *uc, Object *, Error **); bool (*get)(struct uc_struct *uc, Object *, Error **);
@ -1556,7 +1655,7 @@ void object_property_add_bool(struct uc_struct *uc, Object *obj, const char *nam
prop->get = get; prop->get = get;
prop->set = set; prop->set = set;
object_property_add(obj, name, "bool", object_property_add(uc, obj, name, "bool",
get ? property_get_bool : NULL, get ? property_get_bool : NULL,
set ? property_set_bool : NULL, set ? property_set_bool : NULL,
property_release_bool, property_release_bool,
@ -1567,6 +1666,29 @@ void object_property_add_bool(struct uc_struct *uc, Object *obj, const char *nam
} }
} }
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,
prop, &local_err);
if (local_err) {
error_propagate(errp, local_err);
g_free(prop);
}
}
static char *qdev_get_type(struct uc_struct *uc, Object *obj, Error **errp) static char *qdev_get_type(struct uc_struct *uc, Object *obj, Error **errp)
{ {
return g_strdup(object_get_typename(obj)); return g_strdup(object_get_typename(obj));
@ -1604,31 +1726,67 @@ static void property_get_uint64_ptr(struct uc_struct *uc, Object *obj, Visitor *
visit_type_uint64(v, name, &value, errp); visit_type_uint64(v, name, &value, errp);
} }
void object_property_add_uint8_ptr(Object *obj, const char *name, void object_class_property_add_uint8_ptr(struct uc_struct *uc, ObjectClass *klass,
const uint8_t *v, Error **errp) 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_uint8_ptr(struct uc_struct *uc, Object *obj,
const char *name, const uint8_t *v,
Error **errp)
{
object_property_add(uc, obj, name, "uint8", property_get_uint8_ptr,
NULL, NULL, (void *)v, errp); NULL, NULL, (void *)v, errp);
} }
void object_property_add_uint16_ptr(Object *obj, const char *name, void object_class_property_add_uint16_ptr(struct uc_struct *uc, ObjectClass *klass,
const uint16_t *v, Error **errp) const char *name, const uint16_t *v,
Error **errp)
{ {
object_property_add(obj, name, "uint16", property_get_uint16_ptr, object_class_property_add(uc, klass, name, "uint16", property_get_uint16_ptr,
NULL, NULL, (void *)v, 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(uc, obj, name, "uint16", property_get_uint16_ptr,
NULL, NULL, (void *)v, errp); NULL, NULL, (void *)v, errp);
} }
void object_property_add_uint32_ptr(Object *obj, const char *name, void object_class_property_add_uint32_ptr(struct uc_struct *uc, ObjectClass *klass,
const uint32_t *v, Error **errp) const char *name, const uint32_t *v,
Error **errp)
{ {
object_property_add(obj, name, "uint32", property_get_uint32_ptr, 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); NULL, NULL, (void *)v, errp);
} }
void object_property_add_uint64_ptr(Object *obj, const char *name, void object_class_property_add_uint64_ptr(struct uc_struct *uc, ObjectClass *klass,
const uint64_t *v, Error **errp) const char *name, const uint64_t *v,
Error **errp)
{ {
object_property_add(obj, name, "uint64", property_get_uint64_ptr, 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); 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); g_free(prop);
} }
void object_property_add_alias(Object *obj, const char *name, void object_property_add_alias(struct uc_struct *uc, Object *obj,
Object *target_obj, const char *target_name, const char *name, Object *target_obj,
const char *target_name,
Error **errp) Error **errp)
{ {
AliasProperty *prop; AliasProperty *prop;
@ -1683,7 +1842,7 @@ void object_property_add_alias(Object *obj, const char *name,
gchar *prop_type; gchar *prop_type;
Error *local_err = NULL; 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) { if (!target_prop) {
return; return;
} }
@ -1699,7 +1858,7 @@ void object_property_add_alias(Object *obj, const char *name,
prop->target_obj = target_obj; prop->target_obj = target_obj;
prop->target_name = g_strdup(target_name); 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_get_alias,
property_set_alias, property_set_alias,
property_release_alias, property_release_alias,
@ -1711,7 +1870,7 @@ void object_property_add_alias(Object *obj, const char *name,
} }
op->resolve = property_resolve_alias; op->resolve = property_resolve_alias;
object_property_set_description(obj, op->name, object_property_set_description(uc, obj, op->name,
target_prop->description, target_prop->description,
&error_abort); &error_abort);
@ -1719,12 +1878,13 @@ out:
g_free(prop_type); g_free(prop_type);
} }
void object_property_set_description(Object *obj, const char *name, void object_property_set_description(struct uc_struct *uc, Object *obj,
const char *description, Error **errp) const char *name, const char *description,
Error **errp)
{ {
ObjectProperty *op; ObjectProperty *op;
op = object_property_find(obj, name, errp); op = object_property_find(uc, obj, name, errp);
if (!op) { if (!op) {
return; return;
} }
@ -1733,9 +1893,27 @@ void object_property_set_description(Object *obj, const char *name,
op->description = g_strdup(description); 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) 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) 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; cs->env_ptr = env;
cpu_exec_init(cs, opaque); 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_get_family,
x86_cpuid_version_set_family, NULL, NULL, NULL); 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_get_model,
x86_cpuid_version_set_model, NULL, NULL, NULL); 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_get_stepping,
x86_cpuid_version_set_stepping, NULL, NULL, NULL); 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_get_vendor,
x86_cpuid_set_vendor, NULL); 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_get_model_id,
x86_cpuid_set_model_id, NULL); 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_get_tsc_freq,
x86_cpuid_set_tsc_freq, NULL, NULL, NULL); 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_get_apic_id,
x86_cpuid_set_apic_id, NULL, NULL, NULL); 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, x86_cpu_get_feature_words,
NULL, NULL, (void *)env->features, NULL); 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, x86_cpu_get_feature_words,
NULL, NULL, (void *)cpu->filtered_features, NULL); 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) static void free_table(gpointer key, gpointer value, gpointer data)
{ {
TypeInfo *ti = (TypeInfo*) value; TypeInfo *ti = (TypeInfo*) value;
g_hash_table_destroy(ti->class->properties);
g_free((void *) ti->class); g_free((void *) ti->class);
g_free((void *) ti->name); g_free((void *) ti->name);
g_free((void *) ti->parent); g_free((void *) ti->parent);