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 kvm-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/kvm-devel