[PATCH 1/4] Replace SIGUSR1 in io-thread with eventfd() (v2)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]


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 <aliguori@xxxxxxxxxx>

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   <aliguori@xxxxxxxxxx>
+ *
+ * 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. 
_______________________________________________
kvm-devel mailing list
kvm-devel@xxxxxxxxxxxxxxxxxxxxx
https://lists.sourceforge.net/lists/listinfo/kvm-devel

[Site Home]     [Netdev]     [Ethernet Bridging]     [Linux Virtualization]     [LVS Devel]     [Linux Wireless]     [Kernel Newbies]     [Memory]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Rubini]     [100% Free Internet Dating]     [Photo]     [Yosemite]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]     [Video 4 Linux]     [Linux Resources]

Powered by Linux