From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([208.118.235.92]:44498) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UYITw-0001OO-Fn for qemu-devel@nongnu.org; Fri, 03 May 2013 12:05:13 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1UYITu-0007dd-Cw for qemu-devel@nongnu.org; Fri, 03 May 2013 12:05:12 -0400 Received: from mail-vc0-f181.google.com ([209.85.220.181]:39500) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UYITu-0007dX-8x for qemu-devel@nongnu.org; Fri, 03 May 2013 12:05:10 -0400 Received: by mail-vc0-f181.google.com with SMTP id hr11so1572535vcb.12 for ; Fri, 03 May 2013 09:05:10 -0700 (PDT) Sender: fluxion From: Michael Roth Date: Fri, 3 May 2013 11:03:46 -0500 Message-Id: <1367597032-28934-4-git-send-email-mdroth@linux.vnet.ibm.com> In-Reply-To: <1367597032-28934-1-git-send-email-mdroth@linux.vnet.ibm.com> References: <1367597032-28934-1-git-send-email-mdroth@linux.vnet.ibm.com> Subject: [Qemu-devel] [PATCH 3/9] QSource: QEMU event source object List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: pbonzini@redhat.com, aliguori@us.ibm.com, qemulist@gmail.com, stefanha@redhat.com This references QContext, which will be introduced later (and also references this). These will likely be squashed eventually, but we leave them separate for now for easier review. This implements a QOM-based event source object which is used in much the same way as a GSource. Signed-off-by: Michael Roth --- include/qcontext/qsource.h | 63 +++++++++++++++++++ qcontext/qsource.c | 143 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 206 insertions(+) create mode 100644 include/qcontext/qsource.h create mode 100644 qcontext/qsource.c diff --git a/include/qcontext/qsource.h b/include/qcontext/qsource.h new file mode 100644 index 0000000..7c6dd75 --- /dev/null +++ b/include/qcontext/qsource.h @@ -0,0 +1,63 @@ +/* + * QSource: QEMU event source class + * + * Copyright IBM Corp. 2013 + * + * Authors: + * Michael Roth + * + * 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 QSOURCE_H +#define QSOURCE_H + +#include "qom/object.h" +#include "qcontext/qcontext.h" + +typedef struct QSource QSource; + +typedef bool (*QSourceCB)(QSource *qsource); + +typedef struct QSourceFuncs { + bool (*prepare)(QSource *qsource, int *timeout); + bool (*check)(QSource *qsource); + bool (*dispatch)(QSource *qsource); + void (*finalize)(QSource *qsource); +} QSourceFuncs; + +typedef struct QSourceClass { + ObjectClass parent_class; + + void (*add_poll)(QSource *qsource, GPollFD *pfd); + void (*remove_poll)(QSource *qsource, GPollFD *pfd); + void (*set_source_funcs)(QSource *qsource, QSourceFuncs funcs); + QSourceCB (*get_callback_func)(QSource *qsource); + void (*set_callback_func)(QSource *qsource, QSourceCB cb); + void (*set_user_data)(QSource *qsource, void *user_data); + void *(*get_user_data)(QSource *qsource); +} QSourceClass; + +struct QSource { + /* */ +}; + +#define TYPE_QSOURCE "qsource" +#define QSOURCE(obj) OBJECT_CHECK(QSource, (obj), TYPE_QSOURCE) +#define QSOURCE_CLASS(klass) OBJECT_CLASS_CHECK(QSourceClass, (klass), TYPE_QSOURCE) +#define QSOURCE_GET_CLASS(obj) OBJECT_GET_CLASS(QSourceClass, (obj), TYPE_QSOURCE) + +QSource *qsource_new(QSourceFuncs source_funcs, QSourceCB cb, const char *name, + void *opaque); + +#endif /* QSOURCE_H */ diff --git a/qcontext/qsource.c b/qcontext/qsource.c new file mode 100644 index 0000000..1f3dcb5 --- /dev/null +++ b/qcontext/qsource.c @@ -0,0 +1,143 @@ +/* + * QSource: QEMU event source class + * + * Copyright IBM Corp. 2013 + * + * Authors: + * Michael Roth + * + * 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 +#include "qom/object.h" +#include "qcontext/qcontext.h" +#include "qemu/module.h" + +/* FIXME: this basically causes us to destroy/rebuild an + * attached QSource/GSource every time we modify. What we + * should really have is an interface in the QContext for + * modifying an already attached source to avoid so much + * churn for simple action like adding poll fds to an + * source. The alternative is to require users to + * explicitly detach QSources before modifying them, but + * updating poll FDs/callbacks etc is a common operation + * for QSource/GSource callbacks so this limits functionality + * substantially + */ +static void qsource_update(QSource *qsource) +{ + QContext *ctx = qsource->ctx; + + if (ctx) { + qcontext_detach(ctx, qsource, NULL); + qcontext_attach(ctx, qsource, NULL); + } +} + +static void qsource_add_poll(QSource *qsource, GPollFD *pfd) +{ + g_array_append_val(qsource->poll_fds, pfd); + qsource_update(qsource); +} + +static void qsource_remove_poll(QSource *qsource, GPollFD *pfd) +{ + bool done = false; + + while (!done) { + done = true; + guint i; + for (i = 0; i < qsource->poll_fds->len; i++) { + if (g_array_index(qsource->poll_fds, GPollFD *, i) == pfd) { + g_array_remove_index(qsource->poll_fds, i); + /* iterate again to make sure we get them all */ + done = false; + break; + } + } + } + + qsource_update(qsource); +} + +static void qsource_set_source_funcs(QSource *qsource, QSourceFuncs funcs) +{ + qsource->source_funcs = funcs; + qsource_update(qsource); +} + +static QSourceCB qsource_get_callback_func(QSource *qsource) +{ + return qsource->callback_func; +} + +static void qsource_set_callback_func(QSource *qsource, QSourceCB callback_func) +{ + qsource->callback_func = callback_func; + qsource_update(qsource); +} + +static void qsource_set_user_data(QSource *qsource, void *user_data) +{ + qsource->user_data = user_data; + qsource_update(qsource); +} + +static void *qsource_get_user_data(QSource *qsource) +{ + return qsource->user_data; +} + +static void qsource_initfn(Object *obj) +{ + QSource *qsource = QSOURCE(obj); + qsource->poll_fds = g_array_new(FALSE, FALSE, sizeof(GPollFD)); + qsource->ctx = NULL; +} + +static void qsource_class_initfn(ObjectClass *class, void *data) +{ + QSourceClass *k = QSOURCE_CLASS(class); + + k->add_poll = qsource_add_poll; + k->remove_poll = qsource_remove_poll; + k->set_source_funcs = qsource_set_source_funcs; + k->get_callback_func = qsource_get_callback_func; + k->set_callback_func = qsource_set_callback_func; + k->get_user_data = qsource_get_user_data; + k->set_user_data = qsource_set_user_data; +} + +TypeInfo qsource_info = { + .name = TYPE_QSOURCE, + .parent = TYPE_OBJECT, + .instance_size = sizeof(QSource), + .class_size = sizeof(QSourceClass), + .instance_init = qsource_initfn, + .class_init = qsource_class_initfn, + .interfaces = (InterfaceInfo[]) { + { }, + }, +}; + +static void qsource_register_types(void) +{ + type_register_static(&qsource_info); +} + +type_init(qsource_register_types) + +QSource *qsource_new(QSourceFuncs funcs, QSourceCB cb, const char *name, void *opaque) +{ + QSource *qsource = QSOURCE(object_new(TYPE_QSOURCE)); + QSourceClass *qsourcek = QSOURCE_GET_CLASS(qsource); + + qsource->name = g_strdup(name); + + qsourcek->set_source_funcs(qsource, funcs); + qsourcek->set_callback_func(qsource, cb); + qsourcek->set_user_data(qsource, opaque); + + return qsource; +} -- 1.7.9.5