iothread: use signalfd

Block SIGALRM, SIGIO and consume them via signalfd.

Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
This commit is contained in:
Marcelo Tosatti 2010-10-11 15:31:16 -03:00 committed by Anthony Liguori
parent dcc38d1cce
commit a8486bc9c9

74
cpus.c
View file

@ -33,6 +33,7 @@
#include "exec-all.h"
#include "cpus.h"
#include "compatfd.h"
#ifdef SIGRTMIN
#define SIG_IPI (SIGRTMIN+4)
@ -329,14 +330,75 @@ static QemuCond qemu_work_cond;
static void tcg_init_ipi(void);
static void kvm_init_ipi(CPUState *env);
static void unblock_io_signals(void);
static sigset_t block_io_signals(void);
/* If we have signalfd, we mask out the signals we want to handle and then
* use signalfd to listen for them. We rely on whatever the current signal
* handler is to dispatch the signals when we receive them.
*/
static void sigfd_handler(void *opaque)
{
int fd = (unsigned long) opaque;
struct qemu_signalfd_siginfo info;
struct sigaction action;
ssize_t len;
while (1) {
do {
len = read(fd, &info, sizeof(info));
} while (len == -1 && errno == EINTR);
if (len == -1 && errno == EAGAIN) {
break;
}
if (len != sizeof(info)) {
printf("read from sigfd returned %zd: %m\n", len);
return;
}
sigaction(info.ssi_signo, NULL, &action);
if ((action.sa_flags & SA_SIGINFO) && action.sa_sigaction) {
action.sa_sigaction(info.ssi_signo,
(siginfo_t *)&info, NULL);
} else if (action.sa_handler) {
action.sa_handler(info.ssi_signo);
}
}
}
static int qemu_signalfd_init(sigset_t mask)
{
int sigfd;
sigfd = qemu_signalfd(&mask);
if (sigfd == -1) {
fprintf(stderr, "failed to create signalfd\n");
return -errno;
}
fcntl_setfl(sigfd, O_NONBLOCK);
qemu_set_fd_handler2(sigfd, NULL, sigfd_handler, NULL,
(void *)(unsigned long) sigfd);
return 0;
}
int qemu_init_main_loop(void)
{
int ret;
sigset_t blocked_signals;
cpu_set_debug_excp_handler(cpu_debug_handler);
blocked_signals = block_io_signals();
ret = qemu_signalfd_init(blocked_signals);
if (ret)
return ret;
/* Note eventfd must be drained before signalfd handlers run */
ret = qemu_event_init();
if (ret)
return ret;
@ -347,7 +409,6 @@ int qemu_init_main_loop(void)
qemu_mutex_init(&qemu_global_mutex);
qemu_mutex_lock(&qemu_global_mutex);
unblock_io_signals();
qemu_thread_self(&io_thread);
return 0;
@ -586,19 +647,22 @@ static void kvm_init_ipi(CPUState *env)
}
}
static void unblock_io_signals(void)
static sigset_t block_io_signals(void)
{
sigset_t set;
/* SIGUSR2 used by posix-aio-compat.c */
sigemptyset(&set);
sigaddset(&set, SIGUSR2);
sigaddset(&set, SIGIO);
sigaddset(&set, SIGALRM);
pthread_sigmask(SIG_UNBLOCK, &set, NULL);
sigemptyset(&set);
sigaddset(&set, SIGIO);
sigaddset(&set, SIGALRM);
sigaddset(&set, SIG_IPI);
pthread_sigmask(SIG_BLOCK, &set, NULL);
return set;
}
void qemu_mutex_lock_iothread(void)