Browse Source
Replace signalfd with signal handler/pipe. There is no way to interrupt
the CPU execution loop when a file descriptor becomes readable. This
results in a large performance regression in sparc emulation during
bootup.
This patch switches us to signal handler/pipe which was originally
suggested by Ian Jackson. The signal handler lets us interrupt the
CPU emulation loop while the write to a pipe lets us avoid the
select/signal race condition.
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5451 c046a42c-6fe2-441c-8c8c-71466251a162
stable-0.10
9 changed files with 55 additions and 233 deletions
@ -1,127 +0,0 @@ |
|||||
/*
|
|
||||
* signalfd/eventfd compatibility |
|
||||
* |
|
||||
* Copyright IBM, Corp. 2008 |
|
||||
* |
|
||||
* Authors: |
|
||||
* Anthony Liguori <aliguori@us.ibm.com> |
|
||||
* |
|
||||
* 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 "compatfd.h" |
|
||||
|
|
||||
#include <sys/syscall.h> |
|
||||
#include <pthread.h> |
|
||||
|
|
||||
struct sigfd_compat_info |
|
||||
{ |
|
||||
sigset_t mask; |
|
||||
int fd; |
|
||||
}; |
|
||||
|
|
||||
static void *sigwait_compat(void *opaque) |
|
||||
{ |
|
||||
struct sigfd_compat_info *info = opaque; |
|
||||
int err; |
|
||||
sigset_t all; |
|
||||
|
|
||||
sigfillset(&all); |
|
||||
sigprocmask(SIG_BLOCK, &all, NULL); |
|
||||
|
|
||||
do { |
|
||||
siginfo_t siginfo; |
|
||||
|
|
||||
err = sigwaitinfo(&info->mask, &siginfo); |
|
||||
if (err == -1 && errno == EINTR) { |
|
||||
err = 0; |
|
||||
continue; |
|
||||
} |
|
||||
|
|
||||
if (err > 0) { |
|
||||
char buffer[128]; |
|
||||
size_t offset = 0; |
|
||||
|
|
||||
memcpy(buffer, &err, sizeof(err)); |
|
||||
while (offset < sizeof(buffer)) { |
|
||||
ssize_t len; |
|
||||
|
|
||||
len = write(info->fd, buffer + offset, |
|
||||
sizeof(buffer) - offset); |
|
||||
if (len == -1 && errno == EINTR) |
|
||||
continue; |
|
||||
|
|
||||
if (len <= 0) { |
|
||||
err = -1; |
|
||||
break; |
|
||||
} |
|
||||
|
|
||||
offset += len; |
|
||||
} |
|
||||
} |
|
||||
} while (err >= 0); |
|
||||
|
|
||||
return NULL; |
|
||||
} |
|
||||
|
|
||||
static int qemu_signalfd_compat(const sigset_t *mask) |
|
||||
{ |
|
||||
pthread_attr_t attr; |
|
||||
pthread_t tid; |
|
||||
struct sigfd_compat_info *info; |
|
||||
int fds[2]; |
|
||||
|
|
||||
info = malloc(sizeof(*info)); |
|
||||
if (info == NULL) { |
|
||||
errno = ENOMEM; |
|
||||
return -1; |
|
||||
} |
|
||||
|
|
||||
if (pipe(fds) == -1) { |
|
||||
free(info); |
|
||||
return -1; |
|
||||
} |
|
||||
|
|
||||
memcpy(&info->mask, mask, sizeof(*mask)); |
|
||||
info->fd = fds[1]; |
|
||||
|
|
||||
pthread_attr_init(&attr); |
|
||||
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); |
|
||||
|
|
||||
pthread_create(&tid, &attr, sigwait_compat, info); |
|
||||
|
|
||||
pthread_attr_destroy(&attr); |
|
||||
|
|
||||
return fds[0]; |
|
||||
} |
|
||||
|
|
||||
int qemu_signalfd(const sigset_t *mask) |
|
||||
{ |
|
||||
#if defined(CONFIG_signalfd) |
|
||||
int ret; |
|
||||
|
|
||||
ret = syscall(SYS_signalfd, -1, mask, _NSIG / 8); |
|
||||
if (ret != -1) |
|
||||
return ret; |
|
||||
#endif |
|
||||
|
|
||||
return qemu_signalfd_compat(mask); |
|
||||
} |
|
||||
|
|
||||
int qemu_eventfd(int *fds) |
|
||||
{ |
|
||||
#if defined(CONFIG_eventfd) |
|
||||
int ret; |
|
||||
|
|
||||
ret = syscall(SYS_eventfd, 0); |
|
||||
if (ret >= 0) { |
|
||||
fds[0] = fds[1] = ret; |
|
||||
return 0; |
|
||||
} |
|
||||
#endif |
|
||||
|
|
||||
return pipe(fds); |
|
||||
} |
|
||||
@ -1,28 +0,0 @@ |
|||||
/*
|
|
||||
* signalfd/eventfd compatibility |
|
||||
* |
|
||||
* Copyright IBM, Corp. 2008 |
|
||||
* |
|
||||
* Authors: |
|
||||
* Anthony Liguori <aliguori@us.ibm.com> |
|
||||
* |
|
||||
* This work is licensed under the terms of the GNU GPL, version 2. See |
|
||||
* the COPYING file in the top-level directory. |
|
||||
* |
|
||||
*/ |
|
||||
|
|
||||
#ifndef QEMU_COMPATFD_H |
|
||||
#define QEMU_COMPATFD_H |
|
||||
|
|
||||
#include <signal.h> |
|
||||
|
|
||||
struct qemu_signalfd_siginfo { |
|
||||
uint32_t ssi_signo; |
|
||||
uint8_t pad[124]; |
|
||||
}; |
|
||||
|
|
||||
int qemu_signalfd(const sigset_t *mask); |
|
||||
|
|
||||
int qemu_eventfd(int *fds); |
|
||||
|
|
||||
#endif |
|
||||
Loading…
Reference in new issue