From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:48408) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VrAYm-0002CE-Cw for qemu-devel@nongnu.org; Thu, 12 Dec 2013 13:00:37 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1VrAYd-0002Xt-AF for qemu-devel@nongnu.org; Thu, 12 Dec 2013 13:00:28 -0500 Received: from e39.co.us.ibm.com ([32.97.110.160]:53077) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VrAYd-0002Xb-2f for qemu-devel@nongnu.org; Thu, 12 Dec 2013 13:00:19 -0500 Received: from /spool/local by e39.co.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Thu, 12 Dec 2013 11:00:17 -0700 Received: from b01cxnp23034.gho.pok.ibm.com (b01cxnp23034.gho.pok.ibm.com [9.57.198.29]) by d01dlp03.pok.ibm.com (Postfix) with ESMTP id 8A598C9003E for ; Thu, 12 Dec 2013 13:00:11 -0500 (EST) Received: from d01av05.pok.ibm.com (d01av05.pok.ibm.com [9.56.224.195]) by b01cxnp23034.gho.pok.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id rBCI0DYY9503002 for ; Thu, 12 Dec 2013 18:00:13 GMT Received: from d01av05.pok.ibm.com (localhost [127.0.0.1]) by d01av05.pok.ibm.com (8.14.4/8.14.4/NCO v10.0 AVout) with ESMTP id rBCI0CgD023552 for ; Thu, 12 Dec 2013 13:00:13 -0500 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable From: Michael Roth In-Reply-To: <1386854384-1992-4-git-send-email-stefanha@redhat.com> References: <1386854384-1992-1-git-send-email-stefanha@redhat.com> <1386854384-1992-4-git-send-email-stefanha@redhat.com> Message-ID: <20131212180012.11040.17183@loki> Date: Thu, 12 Dec 2013 12:00:12 -0600 Subject: Re: [Qemu-devel] [RFC 3/7] iothread: add I/O thread object List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Stefan Hajnoczi , qemu-devel@nongnu.org Cc: Kevin Wolf , Paolo Bonzini Quoting Stefan Hajnoczi (2013-12-12 07:19:40) > 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 > --- > Makefile.objs | 1 + > include/sysemu/iothread.h | 31 +++++++++++++ > iothread.c | 115 ++++++++++++++++++++++++++++++++++++++++= ++++++ > 3 files changed, 147 insertions(+) > create mode 100644 include/sysemu/iothread.h > create mode 100644 iothread.c > = > diff --git a/Makefile.objs b/Makefile.objs > index 2b6c1fe..a1102a5 100644 > --- a/Makefile.objs > +++ b/Makefile.objs > @@ -42,6 +42,7 @@ libcacard-y +=3D libcacard/vcardt.o > = > ifeq ($(CONFIG_SOFTMMU),y) > common-obj-y =3D $(block-obj-y) blockdev.o blockdev-nbd.o block/ > +common-obj-y +=3D iothread.o > common-obj-y +=3D net/ > common-obj-y +=3D readline.o > common-obj-y +=3D qdev-monitor.o device-hotplug.o > diff --git a/include/sysemu/iothread.h b/include/sysemu/iothread.h > new file mode 100644 > index 0000000..8c49bd6 > --- /dev/null > +++ b/include/sysemu/iothread.h > @@ -0,0 +1,31 @@ > +/* > + * Event loop thread > + * > + * Copyright Red Hat Inc., 2013 > + * > + * Authors: > + * Stefan Hajnoczi > + * > + * This work is licensed under the terms of the GNU GPL, version 2 or la= ter. > + * See the COPYING file in the top-level directory. > + * > + */ > + > +#ifndef IOTHREAD_H > +#define IOTHREAD_H > + > +#include "block/aio.h" > + > +#define TYPE_IOTHREAD "iothread" > +#define IOTHREADS_PATH "/backends/iothreads" > + > +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..dbc6047 > --- /dev/null > +++ b/iothread.c > @@ -0,0 +1,115 @@ > +/* > + * Event loop thread > + * > + * Copyright Red Hat Inc., 2013 > + * > + * Authors: > + * Stefan Hajnoczi > + * > + * This work is licensed under the terms of the GNU GPL, version 2 or la= ter. > + * See the COPYING file in the top-level directory. > + * > + */ > + > +#include "qom/object.h" > +#include "qemu/module.h" > +#include "qemu/thread.h" > +#include "block/aio.h" > +#include "sysemu/iothread.h" > + > +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 =3D opaque; > + > + for (;;) { > + /* TODO can we optimize away acquire/release to only happen when > + * aio_notify() was called? > + */ Perhaps have the AioContext's notifier callback set a flag that can be checked for afterward to determine whether we should release/re-acquire? Calls to aio_context_acquire() could reset it upon acquistion, so we could maybe do something like: while(!iothread->stopping) { aio_context_acquire(iothread->ctx); while (!iothread->ctx->notified) { aio_poll(iothread->ctx, true); } aio_context_release(iothread->ctx); } > + aio_context_acquire(iothread->ctx); > + if (iothread->stopping) { > + aio_context_release(iothread->ctx); > + break; > + } > + aio_poll(iothread->ctx, true); > + aio_context_release(iothread->ctx); > + } > + return NULL; > +} > + > +static void iothread_instance_init(Object *obj) > +{ > + IOThread *iothread =3D IOTHREAD(obj); > + > + iothread->stopping =3D false; > + iothread->ctx =3D aio_context_new(); > + > + /* This assumes .instance_init() is called from a thread with useful= CPU > + * affinity for us to inherit. > + */ Is this assumption necessary/controllable? Couldn't we just expose the thre= ad id via QOM or some other interface so users/management can set the affinity later? > + qemu_thread_create(&iothread->thread, iothread_run, > + iothread, QEMU_THREAD_JOINABLE); > +} > + > +static void iothread_instance_finalize(Object *obj) > +{ > + IOThread *iothread =3D IOTHREAD(obj); > + > + iothread->stopping =3D true; > + aio_notify(iothread->ctx); > + qemu_thread_join(&iothread->thread); > + aio_context_unref(iothread->ctx); > +} > + > +static const TypeInfo iothread_info =3D { > + .name =3D TYPE_IOTHREAD, > + .parent =3D TYPE_OBJECT, > + .instance_size =3D sizeof(IOThread), > + .instance_init =3D iothread_instance_init, > + .instance_finalize =3D iothread_instance_finalize, > +}; > + > +static void iothread_register_types(void) > +{ > + type_register_static(&iothread_info); > +} > + > +type_init(iothread_register_types) > + > +IOThread *iothread_find(const char *id) > +{ > + Object *container =3D container_get(object_get_root(), IOTHREADS_PAT= H); > + Object *child; > + > + child =3D object_property_get_link(container, id, NULL); > + if (!child) { > + return NULL; > + } > + return IOTHREAD(child); > +} > + > +char *iothread_get_id(IOThread *iothread) > +{ > + /* The last path component is the identifier */ > + char *path =3D object_get_canonical_path(OBJECT(iothread)); > + char *id =3D g_strdup(&path[sizeof(IOTHREADS_PATH)]); > + g_free(path); > + return id; > +} > + > +AioContext *iothread_get_aio_context(IOThread *iothread) > +{ > + return iothread->ctx; > +} > -- = > 1.8.4.2