diff options
Diffstat (limited to 'qemu/aio-win32.c')
-rw-r--r-- | qemu/aio-win32.c | 376 |
1 files changed, 0 insertions, 376 deletions
diff --git a/qemu/aio-win32.c b/qemu/aio-win32.c deleted file mode 100644 index 6aaa32a14..000000000 --- a/qemu/aio-win32.c +++ /dev/null @@ -1,376 +0,0 @@ -/* - * QEMU aio implementation - * - * Copyright IBM Corp., 2008 - * Copyright Red Hat Inc., 2012 - * - * Authors: - * Anthony Liguori <aliguori@us.ibm.com> - * Paolo Bonzini <pbonzini@redhat.com> - * - * This work is licensed under the terms of the GNU GPL, version 2. See - * the COPYING file in the top-level directory. - * - * Contributions after 2012-01-13 are licensed under the terms of the - * GNU GPL, version 2 or (at your option) any later version. - */ - -#include "qemu/osdep.h" -#include "qemu-common.h" -#include "block/block.h" -#include "qemu/queue.h" -#include "qemu/sockets.h" - -struct AioHandler { - EventNotifier *e; - IOHandler *io_read; - IOHandler *io_write; - EventNotifierHandler *io_notify; - GPollFD pfd; - int deleted; - void *opaque; - bool is_external; - QLIST_ENTRY(AioHandler) node; -}; - -void aio_set_fd_handler(AioContext *ctx, - int fd, - bool is_external, - IOHandler *io_read, - IOHandler *io_write, - void *opaque) -{ - /* fd is a SOCKET in our case */ - AioHandler *node; - - QLIST_FOREACH(node, &ctx->aio_handlers, node) { - if (node->pfd.fd == fd && !node->deleted) { - break; - } - } - - /* Are we deleting the fd handler? */ - if (!io_read && !io_write) { - if (node) { - /* If the lock is held, just mark the node as deleted */ - if (ctx->walking_handlers) { - node->deleted = 1; - node->pfd.revents = 0; - } else { - /* Otherwise, delete it for real. We can't just mark it as - * deleted because deleted nodes are only cleaned up after - * releasing the walking_handlers lock. - */ - QLIST_REMOVE(node, node); - g_free(node); - } - } - } else { - HANDLE event; - - if (node == NULL) { - /* Alloc and insert if it's not already there */ - node = g_new0(AioHandler, 1); - node->pfd.fd = fd; - QLIST_INSERT_HEAD(&ctx->aio_handlers, node, node); - } - - node->pfd.events = 0; - if (node->io_read) { - node->pfd.events |= G_IO_IN; - } - if (node->io_write) { - node->pfd.events |= G_IO_OUT; - } - - node->e = &ctx->notifier; - - /* Update handler with latest information */ - node->opaque = opaque; - node->io_read = io_read; - node->io_write = io_write; - node->is_external = is_external; - - event = event_notifier_get_handle(&ctx->notifier); - WSAEventSelect(node->pfd.fd, event, - FD_READ | FD_ACCEPT | FD_CLOSE | - FD_CONNECT | FD_WRITE | FD_OOB); - } - - aio_notify(ctx); -} - -void aio_set_event_notifier(AioContext *ctx, - EventNotifier *e, - bool is_external, - EventNotifierHandler *io_notify) -{ - AioHandler *node; - - QLIST_FOREACH(node, &ctx->aio_handlers, node) { - if (node->e == e && !node->deleted) { - break; - } - } - - /* Are we deleting the fd handler? */ - if (!io_notify) { - if (node) { - g_source_remove_poll(&ctx->source, &node->pfd); - - /* If the lock is held, just mark the node as deleted */ - if (ctx->walking_handlers) { - node->deleted = 1; - node->pfd.revents = 0; - } else { - /* Otherwise, delete it for real. We can't just mark it as - * deleted because deleted nodes are only cleaned up after - * releasing the walking_handlers lock. - */ - QLIST_REMOVE(node, node); - g_free(node); - } - } - } else { - if (node == NULL) { - /* Alloc and insert if it's not already there */ - node = g_new0(AioHandler, 1); - node->e = e; - node->pfd.fd = (uintptr_t)event_notifier_get_handle(e); - node->pfd.events = G_IO_IN; - node->is_external = is_external; - QLIST_INSERT_HEAD(&ctx->aio_handlers, node, node); - - g_source_add_poll(&ctx->source, &node->pfd); - } - /* Update handler with latest information */ - node->io_notify = io_notify; - } - - aio_notify(ctx); -} - -bool aio_prepare(AioContext *ctx) -{ - static struct timeval tv0; - AioHandler *node; - bool have_select_revents = false; - fd_set rfds, wfds; - - /* fill fd sets */ - FD_ZERO(&rfds); - FD_ZERO(&wfds); - QLIST_FOREACH(node, &ctx->aio_handlers, node) { - if (node->io_read) { - FD_SET ((SOCKET)node->pfd.fd, &rfds); - } - if (node->io_write) { - FD_SET ((SOCKET)node->pfd.fd, &wfds); - } - } - - if (select(0, &rfds, &wfds, NULL, &tv0) > 0) { - QLIST_FOREACH(node, &ctx->aio_handlers, node) { - node->pfd.revents = 0; - if (FD_ISSET(node->pfd.fd, &rfds)) { - node->pfd.revents |= G_IO_IN; - have_select_revents = true; - } - - if (FD_ISSET(node->pfd.fd, &wfds)) { - node->pfd.revents |= G_IO_OUT; - have_select_revents = true; - } - } - } - - return have_select_revents; -} - -bool aio_pending(AioContext *ctx) -{ - AioHandler *node; - - QLIST_FOREACH(node, &ctx->aio_handlers, node) { - if (node->pfd.revents && node->io_notify) { - return true; - } - - if ((node->pfd.revents & G_IO_IN) && node->io_read) { - return true; - } - if ((node->pfd.revents & G_IO_OUT) && node->io_write) { - return true; - } - } - - return false; -} - -static bool aio_dispatch_handlers(AioContext *ctx, HANDLE event) -{ - AioHandler *node; - bool progress = false; - - /* - * We have to walk very carefully in case aio_set_fd_handler is - * called while we're walking. - */ - node = QLIST_FIRST(&ctx->aio_handlers); - while (node) { - AioHandler *tmp; - int revents = node->pfd.revents; - - ctx->walking_handlers++; - - if (!node->deleted && - (revents || event_notifier_get_handle(node->e) == event) && - node->io_notify) { - node->pfd.revents = 0; - node->io_notify(node->e); - - /* aio_notify() does not count as progress */ - if (node->e != &ctx->notifier) { - progress = true; - } - } - - if (!node->deleted && - (node->io_read || node->io_write)) { - node->pfd.revents = 0; - if ((revents & G_IO_IN) && node->io_read) { - node->io_read(node->opaque); - progress = true; - } - if ((revents & G_IO_OUT) && node->io_write) { - node->io_write(node->opaque); - progress = true; - } - - /* if the next select() will return an event, we have progressed */ - if (event == event_notifier_get_handle(&ctx->notifier)) { - WSANETWORKEVENTS ev; - WSAEnumNetworkEvents(node->pfd.fd, event, &ev); - if (ev.lNetworkEvents) { - progress = true; - } - } - } - - tmp = node; - node = QLIST_NEXT(node, node); - - ctx->walking_handlers--; - - if (!ctx->walking_handlers && tmp->deleted) { - QLIST_REMOVE(tmp, node); - g_free(tmp); - } - } - - return progress; -} - -bool aio_dispatch(AioContext *ctx) -{ - bool progress; - - progress = aio_bh_poll(ctx); - progress |= aio_dispatch_handlers(ctx, INVALID_HANDLE_VALUE); - progress |= timerlistgroup_run_timers(&ctx->tlg); - return progress; -} - -bool aio_poll(AioContext *ctx, bool blocking) -{ - AioHandler *node; - HANDLE events[MAXIMUM_WAIT_OBJECTS + 1]; - bool progress, have_select_revents, first; - int count; - int timeout; - - aio_context_acquire(ctx); - progress = false; - - /* aio_notify can avoid the expensive event_notifier_set if - * everything (file descriptors, bottom halves, timers) will - * be re-evaluated before the next blocking poll(). This is - * already true when aio_poll is called with blocking == false; - * if blocking == true, it is only true after poll() returns, - * so disable the optimization now. - */ - if (blocking) { - atomic_add(&ctx->notify_me, 2); - } - - have_select_revents = aio_prepare(ctx); - - ctx->walking_handlers++; - - /* fill fd sets */ - count = 0; - QLIST_FOREACH(node, &ctx->aio_handlers, node) { - if (!node->deleted && node->io_notify - && aio_node_check(ctx, node->is_external)) { - events[count++] = event_notifier_get_handle(node->e); - } - } - - ctx->walking_handlers--; - first = true; - - /* ctx->notifier is always registered. */ - assert(count > 0); - - /* Multiple iterations, all of them non-blocking except the first, - * may be necessary to process all pending events. After the first - * WaitForMultipleObjects call ctx->notify_me will be decremented. - */ - do { - HANDLE event; - int ret; - - timeout = blocking && !have_select_revents - ? qemu_timeout_ns_to_ms(aio_compute_timeout(ctx)) : 0; - if (timeout) { - aio_context_release(ctx); - } - ret = WaitForMultipleObjects(count, events, FALSE, timeout); - if (blocking) { - assert(first); - atomic_sub(&ctx->notify_me, 2); - } - if (timeout) { - aio_context_acquire(ctx); - } - - if (first) { - aio_notify_accept(ctx); - progress |= aio_bh_poll(ctx); - first = false; - } - - /* if we have any signaled events, dispatch event */ - event = NULL; - if ((DWORD) (ret - WAIT_OBJECT_0) < count) { - event = events[ret - WAIT_OBJECT_0]; - events[ret - WAIT_OBJECT_0] = events[--count]; - } else if (!have_select_revents) { - break; - } - - have_select_revents = false; - blocking = false; - - progress |= aio_dispatch_handlers(ctx, event); - } while (count > 0); - - progress |= timerlistgroup_run_timers(&ctx->tlg); - - aio_context_release(ctx); - return progress; -} - -void aio_context_setup(AioContext *ctx, Error **errp) -{ -} |