提交 037b7add 编写于 作者: P Peter Maydell

Merge remote-tracking branch 'remotes/afaerber/tags/qom-devices-for-2.0' into staging

QOM/QTest infrastructure fixes

* QOM machine memory and build fixes
* QOM link<> and child<> property reference counting fixes

# gpg: Signature made Wed 19 Mar 2014 21:44:04 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-2.0:
  virtio-rng: Avoid default_backend refcount leak
  qom: Add check() argument to object_property_add_link()
  qom: Make QOM link property unref optional
  qom: Don't make link NULL on object_property_set_link() failure
  qom: Split object_property_set_link()
  vl.c: Fix OpenBSD compilation issue due to namespace collisions
  vl.c: Fix memory leak in qemu_register_machine()
Signed-off-by: NPeter Maydell <peter.maydell@linaro.org>
...@@ -21,6 +21,18 @@ void qdev_prop_set_after_realize(DeviceState *dev, const char *name, ...@@ -21,6 +21,18 @@ void qdev_prop_set_after_realize(DeviceState *dev, const char *name,
} }
} }
void qdev_prop_allow_set_link_before_realize(Object *obj, const char *name,
Object *val, Error **errp)
{
DeviceState *dev = DEVICE(obj);
if (dev->realized) {
error_setg(errp, "Attempt to set link property '%s' on device '%s' "
"(type '%s') after it was realized",
name, dev->id, object_get_typename(obj));
}
}
void *qdev_get_prop_ptr(DeviceState *dev, Property *prop) void *qdev_get_prop_ptr(DeviceState *dev, Property *prop)
{ {
void *ptr = dev; void *ptr = dev;
......
...@@ -98,6 +98,8 @@ static void bus_add_child(BusState *bus, DeviceState *child) ...@@ -98,6 +98,8 @@ static void bus_add_child(BusState *bus, DeviceState *child)
object_property_add_link(OBJECT(bus), name, object_property_add_link(OBJECT(bus), name,
object_get_typename(OBJECT(child)), object_get_typename(OBJECT(child)),
(Object **)&kid->child, (Object **)&kid->child,
NULL, /* read-only property */
0, /* return ownership on prop deletion */
NULL); NULL);
} }
...@@ -824,7 +826,8 @@ static void device_initfn(Object *obj) ...@@ -824,7 +826,8 @@ static void device_initfn(Object *obj)
} while (class != object_class_by_name(TYPE_DEVICE)); } while (class != object_class_by_name(TYPE_DEVICE));
object_property_add_link(OBJECT(dev), "parent_bus", TYPE_BUS, object_property_add_link(OBJECT(dev), "parent_bus", TYPE_BUS,
(Object **)&dev->parent_bus, &error_abort); (Object **)&dev->parent_bus, NULL, 0,
&error_abort);
} }
static void device_post_init(Object *obj) static void device_post_init(Object *obj)
...@@ -944,7 +947,10 @@ static void qbus_initfn(Object *obj) ...@@ -944,7 +947,10 @@ static void qbus_initfn(Object *obj)
QTAILQ_INIT(&bus->children); QTAILQ_INIT(&bus->children);
object_property_add_link(obj, QDEV_HOTPLUG_HANDLER_PROPERTY, object_property_add_link(obj, QDEV_HOTPLUG_HANDLER_PROPERTY,
TYPE_HOTPLUG_HANDLER, TYPE_HOTPLUG_HANDLER,
(Object **)&bus->hotplug_handler, NULL); (Object **)&bus->hotplug_handler,
object_property_allow_set_link,
OBJ_PROP_LINK_UNREF_ON_RELEASE,
NULL);
object_property_add_bool(obj, "realized", object_property_add_bool(obj, "realized",
bus_get_realized, bus_set_realized, NULL); bus_get_realized, bus_set_realized, NULL);
} }
......
...@@ -537,9 +537,15 @@ static void xilinx_axidma_realize(DeviceState *dev, Error **errp) ...@@ -537,9 +537,15 @@ static void xilinx_axidma_realize(DeviceState *dev, Error **errp)
Error *local_errp = NULL; Error *local_errp = NULL;
object_property_add_link(OBJECT(ds), "dma", TYPE_XILINX_AXI_DMA, object_property_add_link(OBJECT(ds), "dma", TYPE_XILINX_AXI_DMA,
(Object **)&ds->dma, &local_errp); (Object **)&ds->dma,
object_property_allow_set_link,
OBJ_PROP_LINK_UNREF_ON_RELEASE,
&local_errp);
object_property_add_link(OBJECT(cs), "dma", TYPE_XILINX_AXI_DMA, object_property_add_link(OBJECT(cs), "dma", TYPE_XILINX_AXI_DMA,
(Object **)&cs->dma, &local_errp); (Object **)&cs->dma,
object_property_allow_set_link,
OBJ_PROP_LINK_UNREF_ON_RELEASE,
&local_errp);
if (local_errp) { if (local_errp) {
goto xilinx_axidma_realize_fail; goto xilinx_axidma_realize_fail;
} }
...@@ -571,10 +577,16 @@ static void xilinx_axidma_init(Object *obj) ...@@ -571,10 +577,16 @@ static void xilinx_axidma_init(Object *obj)
SysBusDevice *sbd = SYS_BUS_DEVICE(obj); SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
object_property_add_link(obj, "axistream-connected", TYPE_STREAM_SLAVE, object_property_add_link(obj, "axistream-connected", TYPE_STREAM_SLAVE,
(Object **)&s->tx_data_dev, &error_abort); (Object **)&s->tx_data_dev,
qdev_prop_allow_set_link_before_realize,
OBJ_PROP_LINK_UNREF_ON_RELEASE,
&error_abort);
object_property_add_link(obj, "axistream-control-connected", object_property_add_link(obj, "axistream-control-connected",
TYPE_STREAM_SLAVE, TYPE_STREAM_SLAVE,
(Object **)&s->tx_control_dev, &error_abort); (Object **)&s->tx_control_dev,
qdev_prop_allow_set_link_before_realize,
OBJ_PROP_LINK_UNREF_ON_RELEASE,
&error_abort);
object_initialize(&s->rx_data_dev, sizeof(s->rx_data_dev), object_initialize(&s->rx_data_dev, sizeof(s->rx_data_dev),
TYPE_XILINX_AXI_DMA_DATA_STREAM); TYPE_XILINX_AXI_DMA_DATA_STREAM);
......
...@@ -945,9 +945,15 @@ static void xilinx_enet_realize(DeviceState *dev, Error **errp) ...@@ -945,9 +945,15 @@ static void xilinx_enet_realize(DeviceState *dev, Error **errp)
Error *local_errp = NULL; Error *local_errp = NULL;
object_property_add_link(OBJECT(ds), "enet", "xlnx.axi-ethernet", object_property_add_link(OBJECT(ds), "enet", "xlnx.axi-ethernet",
(Object **) &ds->enet, &local_errp); (Object **) &ds->enet,
object_property_allow_set_link,
OBJ_PROP_LINK_UNREF_ON_RELEASE,
&local_errp);
object_property_add_link(OBJECT(cs), "enet", "xlnx.axi-ethernet", object_property_add_link(OBJECT(cs), "enet", "xlnx.axi-ethernet",
(Object **) &cs->enet, &local_errp); (Object **) &cs->enet,
object_property_allow_set_link,
OBJ_PROP_LINK_UNREF_ON_RELEASE,
&local_errp);
if (local_errp) { if (local_errp) {
goto xilinx_enet_realize_fail; goto xilinx_enet_realize_fail;
} }
...@@ -982,10 +988,16 @@ static void xilinx_enet_init(Object *obj) ...@@ -982,10 +988,16 @@ static void xilinx_enet_init(Object *obj)
SysBusDevice *sbd = SYS_BUS_DEVICE(obj); SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
object_property_add_link(obj, "axistream-connected", TYPE_STREAM_SLAVE, object_property_add_link(obj, "axistream-connected", TYPE_STREAM_SLAVE,
(Object **) &s->tx_data_dev, &error_abort); (Object **) &s->tx_data_dev,
qdev_prop_allow_set_link_before_realize,
OBJ_PROP_LINK_UNREF_ON_RELEASE,
&error_abort);
object_property_add_link(obj, "axistream-control-connected", object_property_add_link(obj, "axistream-control-connected",
TYPE_STREAM_SLAVE, TYPE_STREAM_SLAVE,
(Object **) &s->tx_control_dev, &error_abort); (Object **) &s->tx_control_dev,
qdev_prop_allow_set_link_before_realize,
OBJ_PROP_LINK_UNREF_ON_RELEASE,
&error_abort);
object_initialize(&s->rx_data_dev, sizeof(s->rx_data_dev), object_initialize(&s->rx_data_dev, sizeof(s->rx_data_dev),
TYPE_XILINX_AXI_ENET_DATA_STREAM); TYPE_XILINX_AXI_ENET_DATA_STREAM);
......
...@@ -198,7 +198,9 @@ static void pxa2xx_pcmcia_initfn(Object *obj) ...@@ -198,7 +198,9 @@ static void pxa2xx_pcmcia_initfn(Object *obj)
s->slot.irq = qemu_allocate_irqs(pxa2xx_pcmcia_set_irq, s, 1)[0]; s->slot.irq = qemu_allocate_irqs(pxa2xx_pcmcia_set_irq, s, 1)[0];
object_property_add_link(obj, "card", TYPE_PCMCIA_CARD, object_property_add_link(obj, "card", TYPE_PCMCIA_CARD,
(Object **)&s->card, NULL); (Object **)&s->card,
NULL, /* read-only property */
0, NULL);
} }
/* Insert a new card into a slot */ /* Insert a new card into a slot */
......
...@@ -313,7 +313,9 @@ static void s390_virtio_rng_instance_init(Object *obj) ...@@ -313,7 +313,9 @@ static void s390_virtio_rng_instance_init(Object *obj)
object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_RNG); object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_RNG);
object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL); object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
object_property_add_link(obj, "rng", TYPE_RNG_BACKEND, object_property_add_link(obj, "rng", TYPE_RNG_BACKEND,
(Object **)&dev->vdev.conf.rng, NULL); (Object **)&dev->vdev.conf.rng,
qdev_prop_allow_set_link_before_realize,
OBJ_PROP_LINK_UNREF_ON_RELEASE, NULL);
} }
static uint64_t s390_virtio_device_vq_token(VirtIOS390Device *dev, int vq) static uint64_t s390_virtio_device_vq_token(VirtIOS390Device *dev, int vq)
......
...@@ -1272,7 +1272,9 @@ static void virtio_ccw_rng_instance_init(Object *obj) ...@@ -1272,7 +1272,9 @@ static void virtio_ccw_rng_instance_init(Object *obj)
object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_RNG); object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_RNG);
object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL); object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
object_property_add_link(obj, "rng", TYPE_RNG_BACKEND, object_property_add_link(obj, "rng", TYPE_RNG_BACKEND,
(Object **)&dev->vdev.conf.rng, NULL); (Object **)&dev->vdev.conf.rng,
qdev_prop_allow_set_link_before_realize,
OBJ_PROP_LINK_UNREF_ON_RELEASE, NULL);
} }
static Property virtio_ccw_rng_properties[] = { static Property virtio_ccw_rng_properties[] = {
......
...@@ -1517,7 +1517,9 @@ static void virtio_rng_initfn(Object *obj) ...@@ -1517,7 +1517,9 @@ static void virtio_rng_initfn(Object *obj)
object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_RNG); object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_RNG);
object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL); object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
object_property_add_link(obj, "rng", TYPE_RNG_BACKEND, object_property_add_link(obj, "rng", TYPE_RNG_BACKEND,
(Object **)&dev->vdev.conf.rng, NULL); (Object **)&dev->vdev.conf.rng,
qdev_prop_allow_set_link_before_realize,
OBJ_PROP_LINK_UNREF_ON_RELEASE, NULL);
} }
......
...@@ -162,6 +162,9 @@ static void virtio_rng_device_realize(DeviceState *dev, Error **errp) ...@@ -162,6 +162,9 @@ static void virtio_rng_device_realize(DeviceState *dev, Error **errp)
OBJECT(vrng->conf.default_backend), OBJECT(vrng->conf.default_backend),
NULL); NULL);
/* The child property took a reference, we can safely drop ours now */
object_unref(OBJECT(vrng->conf.default_backend));
object_property_set_link(OBJECT(dev), object_property_set_link(OBJECT(dev),
OBJECT(vrng->conf.default_backend), OBJECT(vrng->conf.default_backend),
"rng", NULL); "rng", NULL);
...@@ -223,7 +226,9 @@ static void virtio_rng_initfn(Object *obj) ...@@ -223,7 +226,9 @@ static void virtio_rng_initfn(Object *obj)
VirtIORNG *vrng = VIRTIO_RNG(obj); VirtIORNG *vrng = VIRTIO_RNG(obj);
object_property_add_link(obj, "rng", TYPE_RNG_BACKEND, object_property_add_link(obj, "rng", TYPE_RNG_BACKEND,
(Object **)&vrng->conf.rng, NULL); (Object **)&vrng->conf.rng,
qdev_prop_allow_set_link_before_realize,
OBJ_PROP_LINK_UNREF_ON_RELEASE, NULL);
} }
static const TypeInfo virtio_rng_info = { static const TypeInfo virtio_rng_info = {
......
...@@ -54,6 +54,7 @@ struct QEMUMachine { ...@@ -54,6 +54,7 @@ struct QEMUMachine {
int qemu_register_machine(QEMUMachine *m); int qemu_register_machine(QEMUMachine *m);
#define TYPE_MACHINE "machine" #define TYPE_MACHINE "machine"
#undef MACHINE /* BSD defines it and QEMU does not use it */
#define MACHINE(obj) \ #define MACHINE(obj) \
OBJECT_CHECK(MachineState, (obj), TYPE_MACHINE) OBJECT_CHECK(MachineState, (obj), TYPE_MACHINE)
#define MACHINE_GET_CLASS(obj) \ #define MACHINE_GET_CLASS(obj) \
......
...@@ -204,4 +204,15 @@ void qdev_property_add_static(DeviceState *dev, Property *prop, Error **errp); ...@@ -204,4 +204,15 @@ void qdev_property_add_static(DeviceState *dev, Property *prop, Error **errp);
*/ */
void qdev_prop_set_after_realize(DeviceState *dev, const char *name, void qdev_prop_set_after_realize(DeviceState *dev, const char *name,
Error **errp); Error **errp);
/**
* qdev_prop_allow_set_link_before_realize:
*
* Set the #Error object if an attempt is made to set the link after realize.
* This function should be used as the check() argument to
* object_property_add_link().
*/
void qdev_prop_allow_set_link_before_realize(Object *obj, const char *name,
Object *val, Error **errp);
#endif #endif
...@@ -1067,12 +1067,29 @@ Object *object_resolve_path_component(Object *parent, const gchar *part); ...@@ -1067,12 +1067,29 @@ Object *object_resolve_path_component(Object *parent, const gchar *part);
void object_property_add_child(Object *obj, const char *name, void object_property_add_child(Object *obj, const char *name,
Object *child, Error **errp); Object *child, Error **errp);
typedef enum {
/* Unref the link pointer when the property is deleted */
OBJ_PROP_LINK_UNREF_ON_RELEASE = 0x1,
} ObjectPropertyLinkFlags;
/**
* object_property_allow_set_link:
*
* The default implementation of the object_property_add_link() check()
* callback function. It allows the link property to be set and never returns
* an error.
*/
void object_property_allow_set_link(Object *, const char *,
Object *, Error **);
/** /**
* object_property_add_link: * object_property_add_link:
* @obj: the object to add a property to * @obj: the object to add a property to
* @name: the name of the property * @name: the name of the property
* @type: the qobj type of the link * @type: the qobj type of the link
* @child: a pointer to where the link object reference is stored * @child: a pointer to where the link object reference is stored
* @check: callback to veto setting or NULL if the property is read-only
* @flags: additional options for the link
* @errp: if an error occurs, a pointer to an area to store the area * @errp: if an error occurs, a pointer to an area to store the area
* *
* Links establish relationships between objects. Links are unidirectional * Links establish relationships between objects. Links are unidirectional
...@@ -1081,13 +1098,23 @@ void object_property_add_child(Object *obj, const char *name, ...@@ -1081,13 +1098,23 @@ void object_property_add_child(Object *obj, const char *name,
* *
* Links form the graph in the object model. * Links form the graph in the object model.
* *
* The <code>@check()</code> callback is invoked when
* object_property_set_link() is called and can raise an error to prevent the
* link being set. If <code>@check</code> is NULL, the property is read-only
* and cannot be set.
*
* Ownership of the pointer that @child points to is transferred to the * Ownership of the pointer that @child points to is transferred to the
* link property. The reference count for <code>*@child</code> is * link property. The reference count for <code>*@child</code> is
* managed by the property from after the function returns till the * managed by the property from after the function returns till the
* property is deleted with object_property_del(). * property is deleted with object_property_del(). If the
* <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(Object *obj, const char *name,
const char *type, Object **child, const char *type, Object **child,
void (*check)(Object *obj, const char *name,
Object *val, Error **errp),
ObjectPropertyLinkFlags flags,
Error **errp); Error **errp);
/** /**
......
...@@ -1023,10 +1023,23 @@ out: ...@@ -1023,10 +1023,23 @@ out:
g_free(type); g_free(type);
} }
void object_property_allow_set_link(Object *obj, const char *name,
Object *val, Error **errp)
{
/* Allow the link to be set, always */
}
typedef struct {
Object **child;
void (*check)(Object *, const char *, Object *, Error **);
ObjectPropertyLinkFlags flags;
} LinkProperty;
static void object_get_link_property(Object *obj, Visitor *v, void *opaque, static void object_get_link_property(Object *obj, Visitor *v, void *opaque,
const char *name, Error **errp) const char *name, Error **errp)
{ {
Object **child = opaque; LinkProperty *lprop = opaque;
Object **child = lprop->child;
gchar *path; gchar *path;
if (*child) { if (*child) {
...@@ -1039,65 +1052,119 @@ static void object_get_link_property(Object *obj, Visitor *v, void *opaque, ...@@ -1039,65 +1052,119 @@ static void object_get_link_property(Object *obj, Visitor *v, void *opaque,
} }
} }
static void object_set_link_property(Object *obj, Visitor *v, void *opaque, /*
const char *name, Error **errp) * object_resolve_link:
*
* Lookup an object and ensure its type matches the link property type. This
* is similar to object_resolve_path() except type verification against the
* link property is performed.
*
* Returns: The matched object or NULL on path lookup failures.
*/
static Object *object_resolve_link(Object *obj, const char *name,
const char *path, Error **errp)
{ {
Object **child = opaque;
Object *old_target;
bool ambiguous = false;
const char *type; const char *type;
char *path;
gchar *target_type; gchar *target_type;
bool ambiguous = false;
Object *target;
/* Go from link<FOO> to FOO. */
type = object_property_get_type(obj, name, NULL); type = object_property_get_type(obj, name, NULL);
target_type = g_strndup(&type[5], strlen(type) - 6);
target = object_resolve_path_type(path, target_type, &ambiguous);
if (ambiguous) {
error_set(errp, QERR_AMBIGUOUS_PATH, path);
} else if (!target) {
target = object_resolve_path(path, &ambiguous);
if (target || ambiguous) {
error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, target_type);
} else {
error_set(errp, QERR_DEVICE_NOT_FOUND, path);
}
target = NULL;
}
g_free(target_type);
visit_type_str(v, &path, name, errp); return target;
}
old_target = *child;
*child = NULL;
if (strcmp(path, "") != 0) { static void object_set_link_property(Object *obj, Visitor *v, void *opaque,
Object *target; const char *name, Error **errp)
{
Error *local_err = NULL;
LinkProperty *prop = opaque;
Object **child = prop->child;
Object *old_target = *child;
Object *new_target = NULL;
char *path = NULL;
/* Go from link<FOO> to FOO. */ visit_type_str(v, &path, name, &local_err);
target_type = g_strndup(&type[5], strlen(type) - 6);
target = object_resolve_path_type(path, target_type, &ambiguous);
if (ambiguous) { if (!local_err && strcmp(path, "") != 0) {
error_set(errp, QERR_AMBIGUOUS_PATH, path); new_target = object_resolve_link(obj, name, path, &local_err);
} else if (target) {
object_ref(target);
*child = target;
} else {
target = object_resolve_path(path, &ambiguous);
if (target || ambiguous) {
error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, target_type);
} else {
error_set(errp, QERR_DEVICE_NOT_FOUND, path);
}
}
g_free(target_type);
} }
g_free(path); g_free(path);
if (local_err) {
error_propagate(errp, local_err);
return;
}
prop->check(obj, name, new_target, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
}
if (new_target) {
object_ref(new_target);
}
*child = new_target;
if (old_target != NULL) { if (old_target != NULL) {
object_unref(old_target); object_unref(old_target);
} }
} }
static void object_release_link_property(Object *obj, const char *name,
void *opaque)
{
LinkProperty *prop = opaque;
if ((prop->flags & OBJ_PROP_LINK_UNREF_ON_RELEASE) && *prop->child) {
object_unref(*prop->child);
}
g_free(prop);
}
void object_property_add_link(Object *obj, const char *name, void object_property_add_link(Object *obj, const char *name,
const char *type, Object **child, const char *type, Object **child,
void (*check)(Object *, const char *,
Object *, Error **),
ObjectPropertyLinkFlags flags,
Error **errp) Error **errp)
{ {
Error *local_err = NULL;
LinkProperty *prop = g_malloc(sizeof(*prop));
gchar *full_type; gchar *full_type;
prop->child = child;
prop->check = check;
prop->flags = flags;
full_type = g_strdup_printf("link<%s>", type); full_type = g_strdup_printf("link<%s>", type);
object_property_add(obj, name, full_type, object_property_add(obj, name, full_type,
object_get_link_property, object_get_link_property,
object_set_link_property, check ? object_set_link_property : NULL,
NULL, child, errp); object_release_link_property,
prop,
&local_err);
if (local_err) {
error_propagate(errp, local_err);
g_free(prop);
}
g_free(full_type); g_free(full_type);
} }
......
...@@ -1180,7 +1180,10 @@ static QemuConsole *new_console(DisplayState *ds, console_type_t console_type) ...@@ -1180,7 +1180,10 @@ static QemuConsole *new_console(DisplayState *ds, console_type_t console_type)
obj = object_new(TYPE_QEMU_CONSOLE); obj = object_new(TYPE_QEMU_CONSOLE);
s = QEMU_CONSOLE(obj); s = QEMU_CONSOLE(obj);
object_property_add_link(obj, "device", TYPE_DEVICE, object_property_add_link(obj, "device", TYPE_DEVICE,
(Object **)&s->device, &local_err); (Object **)&s->device,
object_property_allow_set_link,
OBJ_PROP_LINK_UNREF_ON_RELEASE,
&local_err);
object_property_add_uint32_ptr(obj, "head", object_property_add_uint32_ptr(obj, "head",
&s->head, &local_err); &s->head, &local_err);
......
...@@ -58,6 +58,7 @@ int main(int argc, char **argv) ...@@ -58,6 +58,7 @@ int main(int argc, char **argv)
#include <glib.h> #include <glib.h>
#include "qemu/sockets.h"
#include "hw/hw.h" #include "hw/hw.h"
#include "hw/boards.h" #include "hw/boards.h"
#include "hw/usb.h" #include "hw/usb.h"
...@@ -103,7 +104,6 @@ int main(int argc, char **argv) ...@@ -103,7 +104,6 @@ int main(int argc, char **argv)
#include "disas/disas.h" #include "disas/disas.h"
#include "qemu/sockets.h"
#include "slirp/libslirp.h" #include "slirp/libslirp.h"
...@@ -1587,14 +1587,16 @@ static void machine_class_init(ObjectClass *oc, void *data) ...@@ -1587,14 +1587,16 @@ static void machine_class_init(ObjectClass *oc, void *data)
int qemu_register_machine(QEMUMachine *m) int qemu_register_machine(QEMUMachine *m)
{ {
char *name = g_strconcat(m->name, TYPE_MACHINE_SUFFIX, NULL);
TypeInfo ti = { TypeInfo ti = {
.name = g_strconcat(m->name, TYPE_MACHINE_SUFFIX, NULL), .name = name,
.parent = TYPE_MACHINE, .parent = TYPE_MACHINE,
.class_init = machine_class_init, .class_init = machine_class_init,
.class_data = (void *)m, .class_data = (void *)m,
}; };
type_register(&ti); type_register(&ti);
g_free(name);
return 0; return 0;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册