It's a little odd to use signals to raise a notification on a file descriptor
when we can just work directly with a file descriptor instead. This patch
converts the SIGUSR1 based notification in the io-thread to instead use an
eventfd file descriptor. If eventfd isn't available, we use a pipe() instead.
The benefit of using eventfd is that multiple notifications will be batched
into a signal IO event.
Signed-off-by: Anthony Liguori <[EMAIL PROTECTED]>
diff --git a/qemu/Makefile.target b/qemu/Makefile.target
index 2316c92..db6912e 100644
--- a/qemu/Makefile.target
+++ b/qemu/Makefile.target
@@ -203,7 +203,7 @@ CPPFLAGS+=-I$(SRC_PATH)/tcg/sparc
endif
ifeq ($(USE_KVM), 1)
-LIBOBJS+=qemu-kvm.o
+LIBOBJS+=qemu-kvm.o kvm-compatfd.o
endif
ifdef CONFIG_SOFTFLOAT
LIBOBJS+=fpu/softfloat.o
diff --git a/qemu/kvm-compatfd.c b/qemu/kvm-compatfd.c
new file mode 100644
index 0000000..1b030ba
--- /dev/null
+++ b/qemu/kvm-compatfd.c
@@ -0,0 +1,33 @@
+/*
+ * signalfd/eventfd compatibility
+ *
+ * Copyright IBM, Corp. 2008
+ *
+ * Authors:
+ * Anthony Liguori <[EMAIL PROTECTED]>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#include "qemu-common.h"
+#include "qemu-kvm.h"
+
+#include <sys/syscall.h>
+
+int kvm_eventfd(int *fds)
+{
+#if defined(SYS_eventfd)
+ int ret;
+
+ ret = syscall(SYS_eventfd, 0);
+ if (ret >= 0) {
+ fds[0] = fds[1] = ret;
+ return 0;
+ } else if (!(ret == -1 && errno == ENOSYS))
+ return ret;
+#endif
+
+ return pipe(fds);
+}
diff --git a/qemu/qemu-kvm.c b/qemu/qemu-kvm.c
index 9a9bf59..7134e56 100644
--- a/qemu/qemu-kvm.c
+++ b/qemu/qemu-kvm.c
@@ -15,6 +15,8 @@ int kvm_pit = 1;
#include <string.h>
#include "hw/hw.h"
#include "sysemu.h"
+#include "qemu-common.h"
+#include "console.h"
#include "qemu-kvm.h"
#include <libkvm.h>
@@ -61,6 +63,7 @@ struct vcpu_info {
} vcpu_info[256];
pthread_t io_thread;
+static int io_thread_fd = -1;
static inline unsigned long kvm_get_thread_id(void)
{
@@ -213,7 +216,7 @@ static int kvm_eat_signal(struct qemu_kvm_signal_table
*waitset, CPUState *env,
if (env && vcpu_info[env->cpu_index].stop) {
vcpu_info[env->cpu_index].stop = 0;
vcpu_info[env->cpu_index].stopped = 1;
- pthread_kill(io_thread, SIGUSR1);
+ qemu_kvm_notify_work();
}
pthread_mutex_unlock(&qemu_mutex);
@@ -418,7 +421,6 @@ static void qemu_kvm_init_signal_tables(void)
kvm_add_signal(&io_signal_table, SIGIO);
kvm_add_signal(&io_signal_table, SIGALRM);
- kvm_add_signal(&io_signal_table, SIGUSR1);
kvm_add_signal(&io_signal_table, SIGUSR2);
kvm_add_signal(&vcpu_signal_table, SIG_IPI);
@@ -440,8 +442,51 @@ int kvm_init_ap(void)
void qemu_kvm_notify_work(void)
{
- if (io_thread)
- pthread_kill(io_thread, SIGUSR1);
+ uint64_t value = 1;
+ char buffer[8];
+ size_t offset = 0;
+
+ if (io_thread_fd == -1)
+ return;
+
+ memcpy(buffer, &value, sizeof(value));
+
+ while (offset < 8) {
+ ssize_t len;
+
+ len = write(io_thread_fd, buffer + offset, 8 - offset);
+ if (len == -1 && errno == EINTR)
+ continue;
+
+ if (len <= 0)
+ break;
+
+ offset += len;
+ }
+
+ if (offset != 8)
+ fprintf(stderr, "failed to notify io thread\n");
+}
+
+/* Used to break IO thread out of select */
+static void io_thread_wakeup(void *opaque)
+{
+ int fd = (unsigned long)opaque;
+ char buffer[8];
+ size_t offset = 0;
+
+ while (offset < 8) {
+ ssize_t len;
+
+ len = read(fd, buffer + offset, 8 - offset);
+ if (len == -1 && errno == EINTR)
+ continue;
+
+ if (len <= 0)
+ break;
+
+ offset += len;
+ }
}
/*
@@ -452,8 +497,20 @@ void qemu_kvm_notify_work(void)
int kvm_main_loop(void)
{
+ int fds[2];
+
io_thread = pthread_self();
qemu_system_ready = 1;
+
+ if (kvm_eventfd(fds) == -1) {
+ fprintf(stderr, "failed to create eventfd\n");
+ return -errno;
+ }
+
+ qemu_set_fd_handler2(fds[0], NULL, io_thread_wakeup, NULL,
+ (void *)(unsigned long)fds[0]);
+
+ io_thread_fd = fds[1];
pthread_mutex_unlock(&qemu_mutex);
pthread_cond_broadcast(&qemu_system_cond);
diff --git a/qemu/qemu-kvm.h b/qemu/qemu-kvm.h
index 024a653..8cd63e6 100644
--- a/qemu/qemu-kvm.h
+++ b/qemu/qemu-kvm.h
@@ -97,4 +97,6 @@ extern kvm_context_t kvm_context;
#define qemu_kvm_pit_in_kernel() (0)
#endif
+int kvm_eventfd(int *fds);
+
#endif
-------------------------------------------------------------------------
This SF.net email is sponsored by the 2008 JavaOne(SM) Conference
Don't miss this year's exciting event. There's still time to save $100.
Use priority code J8TL2D2.
http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone
_______________________________________________
kvm-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/kvm-devel