qemu: factor out event notification / rearm alarm timer on main_loop_wait (Marcelo Tosatti)

Special events that have no particular event descriptor (either fd for UNIX
or HANDLE for Windows) associated with make use of an artificial one.

Factor the alarm timer notification so that it can be used for other events,
and move dyntick timer rearm to main_loop_wait.

aliguori: made sure to return a value in qemu_event_init() on win32

Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@7240 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
aliguori 2009-04-24 18:03:29 +00:00
parent 3fcf7b6bed
commit 50317c7fa7

156
vl.c
View file

@ -928,15 +928,11 @@ static void qemu_rearm_alarm_timer(struct qemu_alarm_timer *t)
#define MIN_TIMER_REARM_US 250
static struct qemu_alarm_timer *alarm_timer;
#ifndef _WIN32
static int alarm_timer_rfd, alarm_timer_wfd;
#endif
#ifdef _WIN32
struct qemu_alarm_win32 {
MMRESULT timerId;
HANDLE host_alarm;
unsigned int period;
} alarm_win32_data = {0, NULL, -1};
@ -1305,6 +1301,8 @@ static int timer_load(QEMUFile *f, void *opaque, int version_id)
return 0;
}
static void qemu_event_increment(void);
#ifdef _WIN32
static void CALLBACK host_alarm_handler(UINT uTimerID, UINT uMsg,
DWORD_PTR dwUser, DWORD_PTR dw1,
@ -1350,13 +1348,7 @@ static void host_alarm_handler(int host_signum)
qemu_get_clock(rt_clock))) {
CPUState *env = next_cpu;
#ifdef _WIN32
struct qemu_alarm_win32 *data = ((struct qemu_alarm_timer*)dwUser)->priv;
SetEvent(data->host_alarm);
#else
static const char byte = 0;
write(alarm_timer_wfd, &byte, sizeof(byte));
#endif
qemu_event_increment();
alarm_timer->flags |= ALARM_FLAG_EXPIRED;
if (env) {
@ -1645,24 +1637,6 @@ static void unix_stop_timer(struct qemu_alarm_timer *t)
#endif /* !defined(_WIN32) */
static void try_to_rearm_timer(void *opaque)
{
struct qemu_alarm_timer *t = opaque;
#ifndef _WIN32
ssize_t len;
/* Drain the notify pipe */
do {
char buffer[512];
len = read(alarm_timer_rfd, buffer, sizeof(buffer));
} while ((len == -1 && errno == EINTR) || len > 0);
#endif
if (t->flags & ALARM_FLAG_EXPIRED) {
alarm_timer->flags &= ~ALARM_FLAG_EXPIRED;
qemu_rearm_alarm_timer(alarm_timer);
}
}
#ifdef _WIN32
@ -1672,12 +1646,6 @@ static int win32_start_timer(struct qemu_alarm_timer *t)
struct qemu_alarm_win32 *data = t->priv;
UINT flags;
data->host_alarm = CreateEvent(NULL, FALSE, FALSE, NULL);
if (!data->host_alarm) {
perror("Failed CreateEvent");
return -1;
}
memset(&tc, 0, sizeof(tc));
timeGetDevCaps(&tc, sizeof(tc));
@ -1700,14 +1668,10 @@ static int win32_start_timer(struct qemu_alarm_timer *t)
if (!data->timerId) {
perror("Failed to initialize win32 alarm timer");
timeEndPeriod(data->period);
CloseHandle(data->host_alarm);
return -1;
}
qemu_add_wait_object(data->host_alarm, try_to_rearm_timer, t);
return 0;
}
@ -1717,8 +1681,6 @@ static void win32_stop_timer(struct qemu_alarm_timer *t)
timeKillEvent(data->timerId);
timeEndPeriod(data->period);
CloseHandle(data->host_alarm);
}
static void win32_rearm_timer(struct qemu_alarm_timer *t)
@ -1745,7 +1707,6 @@ static void win32_rearm_timer(struct qemu_alarm_timer *t)
perror("Failed to re-arm win32 alarm timer");
timeEndPeriod(data->period);
CloseHandle(data->host_alarm);
exit(1);
}
}
@ -1757,25 +1718,6 @@ static int init_timer_alarm(void)
struct qemu_alarm_timer *t = NULL;
int i, err = -1;
#ifndef _WIN32
int fds[2];
err = pipe(fds);
if (err == -1)
return -errno;
err = fcntl_setfl(fds[0], O_NONBLOCK);
if (err < 0)
goto fail;
err = fcntl_setfl(fds[1], O_NONBLOCK);
if (err < 0)
goto fail;
alarm_timer_rfd = fds[0];
alarm_timer_wfd = fds[1];
#endif
for (i = 0; alarm_timers[i].name; i++) {
t = &alarm_timers[i];
@ -1789,20 +1731,11 @@ static int init_timer_alarm(void)
goto fail;
}
#ifndef _WIN32
qemu_set_fd_handler2(alarm_timer_rfd, NULL,
try_to_rearm_timer, NULL, t);
#endif
alarm_timer = t;
return 0;
fail:
#ifndef _WIN32
close(fds[0]);
close(fds[1]);
#endif
return err;
}
@ -3718,9 +3651,84 @@ void qemu_notify_event(void)
}
}
#ifndef _WIN32
static int io_thread_fd = -1;
static void qemu_event_increment(void)
{
static const char byte = 0;
if (io_thread_fd == -1)
return;
write(io_thread_fd, &byte, sizeof(byte));
}
static void qemu_event_read(void *opaque)
{
int fd = (unsigned long)opaque;
ssize_t len;
/* Drain the notify pipe */
do {
char buffer[512];
len = read(fd, buffer, sizeof(buffer));
} while ((len == -1 && errno == EINTR) || len > 0);
}
static int qemu_event_init(void)
{
int err;
int fds[2];
err = pipe(fds);
if (err == -1)
return -errno;
err = fcntl_setfl(fds[0], O_NONBLOCK);
if (err < 0)
goto fail;
err = fcntl_setfl(fds[1], O_NONBLOCK);
if (err < 0)
goto fail;
qemu_set_fd_handler2(fds[0], NULL, qemu_event_read, NULL,
(void *)(unsigned long)fds[0]);
io_thread_fd = fds[1];
fail:
close(fds[0]);
close(fds[1]);
return err;
}
#else
HANDLE qemu_event_handle;
static void dummy_event_handler(void *opaque)
{
}
static int qemu_event_init(void)
{
qemu_event_handle = CreateEvent(NULL, FALSE, FALSE, NULL);
if (!qemu_event_handle) {
perror("Failed CreateEvent");
return -1;
}
qemu_add_wait_object(qemu_event_handle, dummy_event_handler, NULL);
return 0;
}
static void qemu_event_increment(void)
{
SetEvent(qemu_event_handle);
}
#endif
static int qemu_init_main_loop(void)
{
return 0;
return qemu_event_init();
}
#ifdef _WIN32
@ -3850,6 +3858,12 @@ void main_loop_wait(int timeout)
}
#endif
/* rearm timer, if not periodic */
if (alarm_timer->flags & ALARM_FLAG_EXPIRED) {
alarm_timer->flags &= ~ALARM_FLAG_EXPIRED;
qemu_rearm_alarm_timer(alarm_timer);
}
/* vm time timers */
if (vm_running && likely(!(cur_cpu->singlestep_enabled & SSTEP_NOTIMER)))
qemu_run_timers(&active_timers[QEMU_TIMER_VIRTUAL],