On Fri, 21 Feb 2014 15:46:55 +0100
Stefan Hajnoczi <stefa...@redhat.com> wrote:

> This is a stand-in for Michael Roth's QContext.  I expect this to be
> replaced once QContext is completed.
> 
> The IOThread object is an AioContext event loop thread.  This patch adds
> the concept of multiple event loop threads, allowing users to define
> them.
> 
> When SMP guests run on SMP hosts it makes sense to instantiate multiple
> IOThreads.  This spreads event loop processing across multiple cores.
> Note that additional patches are required to actually bind a device to
> an IOThread.
> 
> Signed-off-by: Stefan Hajnoczi <stefa...@redhat.com>
> ---
>  Makefile.objs             |   1 +
>  include/sysemu/iothread.h |  30 +++++++++++
>  iothread.c                | 123 
> ++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 154 insertions(+)
>  create mode 100644 include/sysemu/iothread.h
>  create mode 100644 iothread.c
> 
> diff --git a/Makefile.objs b/Makefile.objs
> index ac1d0e1..e24b89c 100644
> --- a/Makefile.objs
> +++ b/Makefile.objs
> @@ -42,6 +42,7 @@ libcacard-y += libcacard/vcardt.o
>  
>  ifeq ($(CONFIG_SOFTMMU),y)
>  common-obj-y = $(block-obj-y) blockdev.o blockdev-nbd.o block/
> +common-obj-y += iothread.o
>  common-obj-y += net/
>  common-obj-y += qdev-monitor.o device-hotplug.o
>  common-obj-$(CONFIG_WIN32) += os-win32.o
> diff --git a/include/sysemu/iothread.h b/include/sysemu/iothread.h
> new file mode 100644
> index 0000000..a32214a
> --- /dev/null
> +++ b/include/sysemu/iothread.h
> @@ -0,0 +1,30 @@
> +/*
> + * Event loop thread
> + *
> + * Copyright Red Hat Inc., 2013
> + *
> + * Authors:
> + *  Stefan Hajnoczi   <stefa...@redhat.com>
> + *
> + * This work is licensed under the terms of the GNU GPL, version 2 or later.
> + * See the COPYING file in the top-level directory.
> + *
> + */
> +
> +#ifndef IOTHREAD_H
> +#define IOTHREAD_H
> +
> +#include "block/aio.h"
> +
> +#define TYPE_IOTHREAD "iothread"
> +
> +typedef struct IOThread IOThread;
> +
> +#define IOTHREAD(obj) \
> +   OBJECT_CHECK(IOThread, obj, TYPE_IOTHREAD)
> +
> +IOThread *iothread_find(const char *id);
> +char *iothread_get_id(IOThread *iothread);
> +AioContext *iothread_get_aio_context(IOThread *iothread);
> +
> +#endif /* IOTHREAD_H */
> diff --git a/iothread.c b/iothread.c
> new file mode 100644
> index 0000000..033de7f
> --- /dev/null
> +++ b/iothread.c
> @@ -0,0 +1,123 @@
> +/*
> + * Event loop thread
> + *
> + * Copyright Red Hat Inc., 2013
> + *
> + * Authors:
> + *  Stefan Hajnoczi   <stefa...@redhat.com>
> + *
> + * This work is licensed under the terms of the GNU GPL, version 2 or later.
> + * See the COPYING file in the top-level directory.
> + *
> + */
> +
> +#include "qom/object.h"
> +#include "qom/object_interfaces.h"
> +#include "qemu/module.h"
> +#include "qemu/thread.h"
> +#include "block/aio.h"
> +#include "sysemu/iothread.h"
> +
> +#define IOTHREADS_PATH "/objects"
> +
> +typedef ObjectClass IOThreadClass;
> +struct IOThread {
> +    Object parent;
> +    QemuThread thread;
> +    AioContext *ctx;
> +    bool stopping;
> +};
> +
> +#define IOTHREAD_GET_CLASS(obj) \
> +   OBJECT_GET_CLASS(IOThreadClass, obj, TYPE_IOTHREAD)
> +#define IOTHREAD_CLASS(klass) \
> +   OBJECT_CLASS_CHECK(IOThreadClass, klass, TYPE_IOTHREAD)
> +
> +static void *iothread_run(void *opaque)
> +{
> +    IOThread *iothread = opaque;
> +
> +    while (!iothread->stopping) {
> +        aio_context_acquire(iothread->ctx);
> +        while (!iothread->stopping && aio_poll(iothread->ctx, true)) {
> +            /* Progress was made, keep going */
> +        }
> +        aio_context_release(iothread->ctx);
> +    }
> +    return NULL;
> +}
> +
> +static void iothread_instance_finalize(Object *obj)
> +{
> +    IOThread *iothread = IOTHREAD(obj);
> +
> +    iothread->stopping = true;
> +    aio_notify(iothread->ctx);
> +    qemu_thread_join(&iothread->thread);
> +    aio_context_unref(iothread->ctx);
> +}
> +
> +static void iothread_complete(UserCreatable *obj, Error **errp)
> +{
> +    IOThread *iothread = IOTHREAD(obj);
> +
> +    iothread->stopping = false;
> +    iothread->ctx = aio_context_new();
> +
> +    /* This assumes we are called from a thread with useful CPU affinity for 
> us
> +     * to inherit.
> +     */
> +    qemu_thread_create(&iothread->thread, iothread_run,
> +                       iothread, QEMU_THREAD_JOINABLE);
> +}
> +
> +static void iothread_class_init(ObjectClass *klass, void *class_data)
> +{
> +    UserCreatableClass *ucc = USER_CREATABLE_CLASS(klass);
> +    ucc->complete = iothread_complete;
> +}
> +
> +static const TypeInfo iothread_info = {
> +    .name = TYPE_IOTHREAD,
> +    .parent = TYPE_OBJECT,
> +    .class_init = iothread_class_init,
> +    .instance_size = sizeof(IOThread),
> +    .instance_finalize = iothread_instance_finalize,
> +    .interfaces = (InterfaceInfo[]) {
> +        {TYPE_USER_CREATABLE},
> +        {}
> +    },
> +};
> +
> +static void iothread_register_types(void)
> +{
> +    type_register_static(&iothread_info);
> +}
> +
> +type_init(iothread_register_types)
> +
> +IOThread *iothread_find(const char *id)
> +{
> +    Object *container = container_get(object_get_root(), IOTHREADS_PATH);
> +    Object *child;
> +
> +    child = object_property_get_link(container, id, NULL);
> +    if (!child) {
> +        return NULL;
> +    }
> +    return (IOThread *)object_dynamic_cast(child, TYPE_IOTHREAD);
> +}
> +
> +char *iothread_get_id(IOThread *iothread)
> +{
> +    /* The last path component is the identifier */
> +    char *path = object_get_canonical_path(OBJECT(iothread));
> +    char *id = g_strdup(&path[sizeof(IOTHREADS_PATH)]);
> +    g_free(path);
> +    return id;
> +}
it seems to be a more generic issue, i.e. QOM object wanting to know its
name. I've did something similar for memory_backend except of cutting
of parent's path.
Could we make and use a more generic accessor for object name?


> +AioContext *iothread_get_aio_context(IOThread *iothread)
> +{
> +    return iothread->ctx;
> +}


Reply via email to