@@ -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
@@ -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
new file mode 100644
@@ -0,0 +1,110 @@
+/*
+ * Posix implementations of event signaling service
+ *
+ * Copyright Red Hat, Inc. 2012
+ * Copyright Siemens AG 2012
+ *
+ * Author:
+ * Paolo Bonzini <pbonzini@redhat.com>
+ * Jan Kiszka <jan.kiszka@siemens.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 "qemu-thread.h"
+#include "qemu-common.h"
+#include "main-loop.h"
+
+#ifdef CONFIG_EVENTFD
+#include <sys/eventfd.h>
+#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__);
+ }
+}
new file mode 100644
@@ -0,0 +1,65 @@
+/*
+ * Win32 implementations of event signaling service
+ *
+ * Copyright Red Hat, Inc. 2012
+ * Copyright Siemens AG 2012
+ *
+ * Author:
+ * Paolo Bonzini <pbonzini@redhat.com>
+ * Jan Kiszka <jan.kiszka@siemens.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 <stdbool.h>
+#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;
+}
@@ -11,6 +11,11 @@ struct QemuCond {
pthread_cond_t cond;
};
+struct QemuEvent {
+ int rfd;
+ int wfd;
+};
+
struct QemuThread {
pthread_t thread;
};
@@ -13,6 +13,10 @@ struct QemuCond {
HANDLE continue_event;
};
+struct QemuEvent {
+ HANDLE event;
+};
+
typedef struct QemuThreadData QemuThreadData;
struct QemuThread {
QemuThreadData *data;
@@ -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
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 <jan.kiszka@siemens.com> --- 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