diff options
author | Andreas Färber | 2013-01-10 21:52:28 +0100 |
---|---|---|
committer | Andreas Färber | 2013-01-10 21:52:28 +0100 |
commit | 63e3555e80c31776285accbb4d0c14ae91c457dc (patch) | |
tree | 89907c82724d6519c8bbad7acc15c0198c6f902f /main-loop.c | |
parent | prep: Use pc87312 device instead of collection of random ISA devices (diff) | |
parent | Merge remote-tracking branch 'kraxel/build.1' into staging (diff) | |
download | qemu-63e3555e80c31776285accbb4d0c14ae91c457dc.tar.gz qemu-63e3555e80c31776285accbb4d0c14ae91c457dc.tar.xz qemu-63e3555e80c31776285accbb4d0c14ae91c457dc.zip |
Merge branch 'master' of git://git.qemu.org/qemu into prep-up
Conflicts:
hw/Makefile.objs
hw/ppc_prep.c
Signed-off-by: Andreas Färber <andreas.faerber@web.de>
Diffstat (limited to 'main-loop.c')
-rw-r--r-- | main-loop.c | 187 |
1 files changed, 67 insertions, 120 deletions
diff --git a/main-loop.c b/main-loop.c index eb3b6e6253..6f52ac39bc 100644 --- a/main-loop.c +++ b/main-loop.c @@ -23,77 +23,14 @@ */ #include "qemu-common.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "slirp/slirp.h" -#include "main-loop.h" +#include "qemu/main-loop.h" +#include "block/aio.h" #ifndef _WIN32 -#include "compatfd.h" - -static int io_thread_fd = -1; - -void qemu_notify_event(void) -{ - /* Write 8 bytes to be compatible with eventfd. */ - static const uint64_t val = 1; - ssize_t ret; - - if (io_thread_fd == -1) { - return; - } - do { - ret = write(io_thread_fd, &val, sizeof(val)); - } while (ret < 0 && errno == EINTR); - - /* EAGAIN is fine, a read must be pending. */ - if (ret < 0 && errno != EAGAIN) { - fprintf(stderr, "qemu_notify_event: write() failed: %s\n", - strerror(errno)); - exit(1); - } -} - -static void qemu_event_read(void *opaque) -{ - int fd = (intptr_t)opaque; - ssize_t len; - char buffer[512]; - - /* Drain the notify pipe. For eventfd, only 8 bytes will be read. */ - do { - len = read(fd, buffer, sizeof(buffer)); - } while ((len == -1 && errno == EINTR) || len == sizeof(buffer)); -} - -static int qemu_event_init(void) -{ - int err; - int fds[2]; - - err = qemu_eventfd(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 *)(intptr_t)fds[0]); - - io_thread_fd = fds[1]; - return 0; - -fail: - close(fds[0]); - close(fds[1]); - return err; -} +#include "qemu/compatfd.h" /* 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 @@ -164,57 +101,42 @@ static int qemu_signal_init(void) #else /* _WIN32 */ -static HANDLE qemu_event_handle = NULL; - -static void dummy_event_handler(void *opaque) -{ -} - -static int qemu_event_init(void) +static int qemu_signal_init(void) { - qemu_event_handle = CreateEvent(NULL, FALSE, FALSE, NULL); - if (!qemu_event_handle) { - fprintf(stderr, "Failed CreateEvent: %ld\n", GetLastError()); - return -1; - } - qemu_add_wait_object(qemu_event_handle, dummy_event_handler, NULL); return 0; } +#endif + +static AioContext *qemu_aio_context; void qemu_notify_event(void) { - if (!qemu_event_handle) { + if (!qemu_aio_context) { return; } - if (!SetEvent(qemu_event_handle)) { - fprintf(stderr, "qemu_notify_event: SetEvent failed: %ld\n", - GetLastError()); - exit(1); - } + aio_notify(qemu_aio_context); } -static int qemu_signal_init(void) -{ - return 0; -} -#endif - -int main_loop_init(void) +int qemu_init_main_loop(void) { int ret; + GSource *src; - qemu_mutex_lock_iothread(); - ret = qemu_signal_init(); - if (ret) { - return ret; + init_clocks(); + if (init_timer_alarm() < 0) { + fprintf(stderr, "could not initialize alarm timer\n"); + exit(1); } - /* Note eventfd must be drained before signalfd handlers run */ - ret = qemu_event_init(); + ret = qemu_signal_init(); if (ret) { return ret; } + qemu_aio_context = aio_context_new(); + src = aio_get_g_source(qemu_aio_context); + g_source_attach(src, NULL); + g_source_unref(src); return 0; } @@ -400,14 +322,15 @@ void qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque) void qemu_fd_register(int fd) { - WSAEventSelect(fd, qemu_event_handle, FD_READ | FD_ACCEPT | FD_CLOSE | + WSAEventSelect(fd, event_notifier_get_handle(&qemu_aio_context->notifier), + FD_READ | FD_ACCEPT | FD_CLOSE | FD_CONNECT | FD_WRITE | FD_OOB); } static int os_host_main_loop_wait(uint32_t timeout) { GMainContext *context = g_main_context_default(); - int ret, i; + int select_ret, g_poll_ret, ret, i; PollingEntry *pe; WaitObjects *w = &wait_objects; gint poll_timeout; @@ -422,13 +345,6 @@ static int os_host_main_loop_wait(uint32_t timeout) return ret; } - if (nfds >= 0) { - ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv0); - if (ret != 0) { - timeout = 0; - } - } - g_main_context_prepare(context, &max_priority); n_poll_fds = g_main_context_query(context, max_priority, &poll_timeout, poll_fds, ARRAY_SIZE(poll_fds)); @@ -444,9 +360,9 @@ static int os_host_main_loop_wait(uint32_t timeout) } qemu_mutex_unlock_iothread(); - ret = g_poll(poll_fds, n_poll_fds + w->num, poll_timeout); + g_poll_ret = g_poll(poll_fds, n_poll_fds + w->num, poll_timeout); qemu_mutex_lock_iothread(); - if (ret > 0) { + if (g_poll_ret > 0) { for (i = 0; i < w->num; i++) { w->revents[i] = poll_fds[n_poll_fds + i].revents; } @@ -461,12 +377,18 @@ static int os_host_main_loop_wait(uint32_t timeout) g_main_context_dispatch(context); } - /* If an edge-triggered socket event occurred, select will return a - * positive result on the next iteration. We do not need to do anything - * here. + /* Call select after g_poll to avoid a useless iteration and therefore + * improve socket latency. */ - return ret; + if (nfds >= 0) { + select_ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv0); + if (select_ret != 0) { + timeout = 0; + } + } + + return select_ret || g_poll_ret; } #endif @@ -477,8 +399,6 @@ int main_loop_wait(int nonblocking) if (nonblocking) { timeout = 0; - } else { - qemu_bh_update_timeout(&timeout); } /* poll any events */ @@ -501,9 +421,36 @@ int main_loop_wait(int nonblocking) qemu_run_all_timers(); - /* Check bottom-halves last in case any of the earlier events triggered - them. */ - qemu_bh_poll(); - return ret; } + +/* Functions to operate on the main QEMU AioContext. */ + +QEMUBH *qemu_bh_new(QEMUBHFunc *cb, void *opaque) +{ + return aio_bh_new(qemu_aio_context, cb, opaque); +} + +bool qemu_aio_wait(void) +{ + return aio_poll(qemu_aio_context, true); +} + +#ifdef CONFIG_POSIX +void qemu_aio_set_fd_handler(int fd, + IOHandler *io_read, + IOHandler *io_write, + AioFlushHandler *io_flush, + void *opaque) +{ + aio_set_fd_handler(qemu_aio_context, fd, io_read, io_write, io_flush, + opaque); +} +#endif + +void qemu_aio_set_event_notifier(EventNotifier *notifier, + EventNotifierHandler *io_read, + AioFlushEventNotifierHandler *io_flush) +{ + aio_set_event_notifier(qemu_aio_context, notifier, io_read, io_flush); +} |