From patchwork Thu Apr 5 10:59:12 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Kiszka X-Patchwork-Id: 151179 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 67401B7060 for ; Fri, 6 Apr 2012 22:33:11 +1000 (EST) Received: from localhost ([::1]:45426 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SFkUa-0003es-VA for incoming@patchwork.ozlabs.org; Thu, 05 Apr 2012 07:04:40 -0400 Received: from eggs.gnu.org ([208.118.235.92]:45196) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SFkQj-0007jS-Ii for qemu-devel@nongnu.org; Thu, 05 Apr 2012 07:03:08 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1SFkPR-00074t-HS for qemu-devel@nongnu.org; Thu, 05 Apr 2012 07:00:41 -0400 Received: from thoth.sbs.de ([192.35.17.2]:20037) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SFkPR-00073t-76 for qemu-devel@nongnu.org; Thu, 05 Apr 2012 06:59:21 -0400 Received: from mail1.siemens.de (localhost [127.0.0.1]) by thoth.sbs.de (8.13.6/8.13.6) with ESMTP id q35AxI3D014824; Thu, 5 Apr 2012 12:59:18 +0200 Received: from mchn199C.mchp.siemens.de ([139.25.109.49]) by mail1.siemens.de (8.13.6/8.13.6) with ESMTP id q35AxIcB027596; Thu, 5 Apr 2012 12:59:18 +0200 From: Jan Kiszka To: Anthony Liguori , qemu-devel@nongnu.org Date: Thu, 5 Apr 2012 12:59:12 +0200 Message-Id: <14c3f383cbeedf4bf67a920a8fb6f6ced85d5be2.1333623555.git.jan.kiszka@siemens.com> X-Mailer: git-send-email 1.7.3.4 In-Reply-To: References: In-Reply-To: References: X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6, seldom 2.4 (older, 4) X-Received-From: 192.35.17.2 Cc: Kevin Wolf , Paolo Bonzini Subject: [Qemu-devel] [PATCH v3 05/10] Introduce QemuEvent abstraction X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Provide generic services for binary events. Blocking wait would be feasible but is not included yet as there are no users. Signed-off-by: Jan Kiszka --- Makefile | 2 +- Makefile.objs | 5 ++- qemu-event-posix.c | 110 +++++++++++++++++++++++++++++++++++++++++++++++++++ qemu-event-win32.c | 65 ++++++++++++++++++++++++++++++ qemu-thread-posix.h | 5 ++ qemu-thread-win32.h | 4 ++ qemu-thread.h | 12 ++++++ 7 files changed, 201 insertions(+), 2 deletions(-) create mode 100644 qemu-event-posix.c create mode 100644 qemu-event-win32.c diff --git a/Makefile b/Makefile index 35c7a2a..ea127f9 100644 --- a/Makefile +++ b/Makefile @@ -153,7 +153,7 @@ endif qemu-img.o: qemu-img-cmds.h qemu-img.o qemu-tool.o qemu-nbd.o qemu-io.o cmd.o qemu-ga.o: $(GENERATED_HEADERS) -tools-obj-y = $(oslib-obj-y) $(trace-obj-y) qemu-tool.o qemu-timer.o \ +tools-obj-y = $(oslib-obj-y) $(event-obj-y) $(trace-obj-y) qemu-tool.o qemu-timer.o \ qemu-timer-common.o main-loop.o notify.o iohandler.o cutils.o async.o tools-obj-$(CONFIG_POSIX) += compatfd.o diff --git a/Makefile.objs b/Makefile.objs index f308b57..377bfe2 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -24,6 +24,9 @@ oslib-obj-y = osdep.o oslib-obj-$(CONFIG_WIN32) += oslib-win32.o qemu-thread-win32.o oslib-obj-$(CONFIG_POSIX) += oslib-posix.o qemu-thread-posix.o +event-obj-$(CONFIG_POSIX) = qemu-event-posix.o +event-obj-$(CONFIG_WIN32) = qemu-event-win32.o + ####################################################################### # coroutines coroutine-obj-y = qemu-coroutine.o qemu-coroutine-lock.o qemu-coroutine-io.o @@ -97,7 +100,7 @@ common-obj-y += $(net-obj-y) common-obj-y += $(qom-obj-twice-y) common-obj-$(CONFIG_LINUX) += $(fsdev-obj-$(CONFIG_LINUX)) common-obj-y += readline.o console.o cursor.o -common-obj-y += $(oslib-obj-y) +common-obj-y += $(oslib-obj-y) $(event-obj-y) common-obj-$(CONFIG_WIN32) += os-win32.o common-obj-$(CONFIG_POSIX) += os-posix.o diff --git a/qemu-event-posix.c b/qemu-event-posix.c new file mode 100644 index 0000000..6138168 --- /dev/null +++ b/qemu-event-posix.c @@ -0,0 +1,110 @@ +/* + * Posix implementations of event signaling service + * + * Copyright Red Hat, Inc. 2012 + * Copyright Siemens AG 2012 + * + * Author: + * Paolo Bonzini + * Jan Kiszka + * + * 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 "qemu-thread.h" +#include "qemu-common.h" +#include "main-loop.h" + +#ifdef CONFIG_EVENTFD +#include +#endif + +void qemu_event_init(QemuEvent *event, bool signaled) +{ + int fds[2]; + int ret; + +#ifdef CONFIG_EVENTFD + ret = eventfd(signaled, EFD_NONBLOCK | EFD_CLOEXEC); + if (ret >= 0) { + event->rfd = ret; + event->wfd = dup(ret); + if (event->wfd < 0) { + qemu_error_exit(errno, __func__); + } + qemu_set_cloexec(event->wfd); + return; + } + if (errno != ENOSYS) { + qemu_error_exit(errno, __func__); + } + /* fall back to pipe-based support */ +#endif + + ret = qemu_pipe(fds); + if (ret < 0) { + qemu_error_exit(errno, __func__); + } + event->rfd = fds[0]; + event->wfd = fds[1]; + if (signaled) { + qemu_event_signal(event); + } +} + +void qemu_event_destroy(QemuEvent *event) +{ + close(event->rfd); + close(event->wfd); +} + +int qemu_event_get_signal_fd(QemuEvent *event) +{ + return event->wfd; +} + +int qemu_event_get_poll_fd(QemuEvent *event) +{ + return event->rfd; +} + +void qemu_event_set_handler(QemuEvent *event, QemuEventHandler *handler, + void *opaque) +{ + qemu_set_fd_handler2(event->rfd, NULL, (IOHandler *)handler, NULL, opaque); +} + +void qemu_event_signal(QemuEvent *event) +{ + /* Write 8 bytes to be compatible with eventfd. */ + static const uint64_t val = 1; + ssize_t ret; + + do { + ret = write(event->wfd, &val, sizeof(val)); + } while (ret < 0 && errno == EINTR); + + if (ret < 0 && errno != EAGAIN) { + qemu_error_exit(errno, __func__); + } +} + +bool qemu_event_consume(QemuEvent *event) +{ + bool was_set = false; + uint64_t val; + int ret; + + while (1) { + ret = read(event->rfd, &val, sizeof(val)); + if (ret == sizeof(val)) { + was_set = true; + continue; + } + if (ret < 0 && errno == EAGAIN) { + return was_set; + } + qemu_error_exit(errno, __func__); + } +} diff --git a/qemu-event-win32.c b/qemu-event-win32.c new file mode 100644 index 0000000..38fe9ae --- /dev/null +++ b/qemu-event-win32.c @@ -0,0 +1,65 @@ +/* + * Win32 implementations of event signaling service + * + * Copyright Red Hat, Inc. 2012 + * Copyright Siemens AG 2012 + * + * Author: + * Paolo Bonzini + * Jan Kiszka + * + * 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 "qemu-thread.h" +#include "qemu-common.h" +#include "main-loop.h" + +void qemu_event_init(QemuEvent *event, bool signaled) +{ + event->event = CreateEvent(NULL, FALSE, signaled, NULL); + if (!event->event) { + qemu_error_exit(GetLastError(), __func__); + } +} + +void qemu_event_destroy(QemuEvent *event) +{ + CloseHandle(event->event); +} + +int qemu_event_get_signal_fd(QemuEvent *event) +{ + /* unsupported on Win32 */ + abort(); +} + +void qemu_event_set_handler(QemuEvent *event, QemuEventHandler *handler, + void *opaque) +{ + if (handler) { + qemu_add_wait_object(event->event, (IOHandler *)handler, opaque); + } else { + qemu_del_wait_object(event->event, (IOHandler *)handler, opaque); + } +} + +void qemu_event_signal(QemuEvent *event) +{ + if (!SetEvent(event->event)) { + qemu_error_exit(GetLastError(), __func__); + } +} + +bool qemu_event_consume(QemuEvent *event) +{ + DWORD ret; + + ret = WaitForSingleObject(event->event, 0); + if (ret == WAIT_FAILED) { + qemu_error_exit(GetLastError(), __func__); + } + return ret == WAIT_OBJECT_0; +} diff --git a/qemu-thread-posix.h b/qemu-thread-posix.h index 9f00524..95fbb45 100644 --- a/qemu-thread-posix.h +++ b/qemu-thread-posix.h @@ -11,6 +11,11 @@ struct QemuCond { pthread_cond_t cond; }; +struct QemuEvent { + int rfd; + int wfd; +}; + struct QemuThread { pthread_t thread; }; diff --git a/qemu-thread-win32.h b/qemu-thread-win32.h index b9d1be8..d1b7631 100644 --- a/qemu-thread-win32.h +++ b/qemu-thread-win32.h @@ -13,6 +13,10 @@ struct QemuCond { HANDLE continue_event; }; +struct QemuEvent { + HANDLE event; +}; + typedef struct QemuThreadData QemuThreadData; struct QemuThread { QemuThreadData *data; diff --git a/qemu-thread.h b/qemu-thread.h index 10f2c51..a53384f 100644 --- a/qemu-thread.h +++ b/qemu-thread.h @@ -5,8 +5,11 @@ typedef struct QemuMutex QemuMutex; typedef struct QemuCond QemuCond; +typedef struct QemuEvent QemuEvent; typedef struct QemuThread QemuThread; +typedef void QemuEventHandler(void *opaque); + #ifdef _WIN32 #include "qemu-thread-win32.h" #else @@ -28,6 +31,15 @@ void qemu_mutex_unlock(QemuMutex *mutex); void qemu_cond_init(QemuCond *cond); void qemu_cond_destroy(QemuCond *cond); +void qemu_event_init(QemuEvent *event, bool signaled); +void qemu_event_destroy(QemuEvent *event); +int qemu_event_get_signal_fd(QemuEvent *event); +int qemu_event_get_poll_fd(QemuEvent *event); +void qemu_event_set_handler(QemuEvent *event, QemuEventHandler *handler, + void *opaque); +void qemu_event_signal(QemuEvent *event); +bool qemu_event_consume(QemuEvent *event); + /* * IMPORTANT: The implementation does not guarantee that pthread_cond_signal * and pthread_cond_broadcast can be called except while the same mutex is