From 56a391e85124382ddcbdb64dcc05aadfc965f000 Mon Sep 17 00:00:00 2001 From: Michael Roth Date: Thu, 2 Dec 2010 20:39:51 -0600 Subject: [PATCH] Move code related to fd handlers into utility functions This allows us to implement an i/o loop outside of vl.c that can interact with objects that use qemu_set_fd_handler() --- Makefile.objs | 2 +- qemu-char.h | 4 ++ qemu-ioh.c | 115 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ qemu-ioh.h | 34 +++++++++++++++++ vl.c | 86 ++++++++----------------------------------- 5 files changed, 170 insertions(+), 71 deletions(-) create mode 100644 qemu-ioh.c create mode 100644 qemu-ioh.h diff --git a/Makefile.objs b/Makefile.objs index c3e52c5674..0078921871 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -14,7 +14,7 @@ oslib-obj-$(CONFIG_POSIX) += oslib-posix.o # block-obj-y is code used by both qemu system emulation and qemu-img block-obj-y = cutils.o cache-utils.o qemu-malloc.o qemu-option.o module.o -block-obj-y += nbd.o block.o aio.o aes.o qemu-config.o +block-obj-y += nbd.o block.o aio.o aes.o qemu-config.o qemu-ioh.o block-obj-$(CONFIG_POSIX) += posix-aio-compat.o block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o diff --git a/qemu-char.h b/qemu-char.h index e6ee6c4bc9..7d0794a5e3 100644 --- a/qemu-char.h +++ b/qemu-char.h @@ -7,6 +7,7 @@ #include "qemu-config.h" #include "qobject.h" #include "qstring.h" +#include "qemu-ioh.h" /* character device */ @@ -118,4 +119,7 @@ int qemu_set_fd_handler(int fd, IOHandler *fd_read, IOHandler *fd_write, void *opaque); +void qemu_get_fdset(int *nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds); +void qemu_process_fd_handlers(const fd_set *rfds, const fd_set *wfds, + const fd_set *xfds); #endif diff --git a/qemu-ioh.c b/qemu-ioh.c new file mode 100644 index 0000000000..cc714704d7 --- /dev/null +++ b/qemu-ioh.c @@ -0,0 +1,115 @@ +/* + * QEMU System Emulator + * + * Copyright (c) 2003-2008 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "qemu-ioh.h" +#include "qlist.h" + +/* XXX: fd_read_poll should be suppressed, but an API change is + necessary in the character devices to suppress fd_can_read(). */ +int qemu_set_fd_handler3(void *ioh_record_list, + int fd, + IOCanReadHandler *fd_read_poll, + IOHandler *fd_read, + IOHandler *fd_write, + void *opaque) +{ + QLIST_HEAD(, IOHandlerRecord) *io_handlers_ptr = ioh_record_list; + IOHandlerRecord *ioh; + + if (!fd_read && !fd_write) { + QLIST_FOREACH(ioh, io_handlers_ptr, next) { + if (ioh->fd == fd) { + ioh->deleted = 1; + break; + } + } + } else { + QLIST_FOREACH(ioh, io_handlers_ptr, next) { + if (ioh->fd == fd) + goto found; + } + ioh = qemu_mallocz(sizeof(IOHandlerRecord)); + QLIST_INSERT_HEAD(io_handlers_ptr, ioh, next); + found: + ioh->fd = fd; + ioh->fd_read_poll = fd_read_poll; + ioh->fd_read = fd_read; + ioh->fd_write = fd_write; + ioh->opaque = opaque; + ioh->deleted = 0; + } + return 0; +} + +/* add entries from ioh record list to fd sets. nfds and fd sets + * should be cleared/reset by caller if desired. set a particular + * fdset to NULL to ignore fd events of that type + */ +void qemu_get_fdset2(void *ioh_record_list, int *nfds, fd_set *rfds, + fd_set *wfds, fd_set *xfds) +{ + QLIST_HEAD(, IOHandlerRecord) *io_handlers = ioh_record_list; + IOHandlerRecord *ioh; + + QLIST_FOREACH(ioh, io_handlers, next) { + if (ioh->deleted) + continue; + if ((rfds != NULL && ioh->fd_read) && + (!ioh->fd_read_poll || + ioh->fd_read_poll(ioh->opaque) != 0)) { + FD_SET(ioh->fd, rfds); + if (ioh->fd > *nfds) + *nfds = ioh->fd; + } + if (wfds != NULL && ioh->fd_write) { + FD_SET(ioh->fd, wfds); + if (ioh->fd > *nfds) + *nfds = ioh->fd; + } + } +} + +/* execute registered handlers for r/w events in the provided fdsets. unset + * handlers are cleaned up here as well + */ +void qemu_process_fd_handlers2(void *ioh_record_list, const fd_set *rfds, + const fd_set *wfds, const fd_set *xfds) +{ + QLIST_HEAD(, IOHandlerRecord) *io_handlers = ioh_record_list; + IOHandlerRecord *ioh, *pioh; + + QLIST_FOREACH_SAFE(ioh, io_handlers, next, pioh) { + if (!ioh->deleted && ioh->fd_read && FD_ISSET(ioh->fd, rfds)) { + ioh->fd_read(ioh->opaque); + } + if (!ioh->deleted && ioh->fd_write && FD_ISSET(ioh->fd, wfds)) { + ioh->fd_write(ioh->opaque); + } + + /* Do this last in case read/write handlers marked it for deletion */ + if (ioh->deleted) { + QLIST_REMOVE(ioh, next); + qemu_free(ioh); + } + } +} diff --git a/qemu-ioh.h b/qemu-ioh.h new file mode 100644 index 0000000000..7c6e833a26 --- /dev/null +++ b/qemu-ioh.h @@ -0,0 +1,34 @@ +#ifndef QEMU_IOH_H +#define QEMU_IOH_H + +#include "qemu-common.h" +#include "qlist.h" + +/* common i/o loop definitions */ + +typedef struct IOHandlerRecord { + int fd; + IOCanReadHandler *fd_read_poll; + IOHandler *fd_read; + IOHandler *fd_write; + int deleted; + void *opaque; + /* temporary data */ + struct pollfd *ufd; + QLIST_ENTRY(IOHandlerRecord) next; +} IOHandlerRecord; + +/* XXX: fd_read_poll should be suppressed, but an API change is + necessary in the character devices to suppress fd_can_read(). */ +int qemu_set_fd_handler3(void *io_handlers_ptr, + int fd, + IOCanReadHandler *fd_read_poll, + IOHandler *fd_read, + IOHandler *fd_write, + void *opaque); +void qemu_get_fdset2(void *ioh_record_list, int *nfds, fd_set *rfds, + fd_set *wfds, fd_set *xfds); +void qemu_process_fd_handlers2(void *ioh_record_list, const fd_set *rfds, + const fd_set *wfds, const fd_set *xfds); + +#endif diff --git a/vl.c b/vl.c index 0292184273..d3bdfec743 100644 --- a/vl.c +++ b/vl.c @@ -148,6 +148,7 @@ int main(int argc, char **argv) #include "qemu-config.h" #include "qemu-objects.h" #include "qemu-options.h" +#include "qemu-ioh.h" #ifdef CONFIG_VIRTFS #include "fsdev/qemu-fsdev.h" #endif @@ -1007,18 +1008,6 @@ void pcmcia_info(Monitor *mon) /***********************************************************/ /* I/O handling */ -typedef struct IOHandlerRecord { - int fd; - IOCanReadHandler *fd_read_poll; - IOHandler *fd_read; - IOHandler *fd_write; - int deleted; - void *opaque; - /* temporary data */ - struct pollfd *ufd; - QLIST_ENTRY(IOHandlerRecord) next; -} IOHandlerRecord; - static QLIST_HEAD(, IOHandlerRecord) io_handlers = QLIST_HEAD_INITIALIZER(io_handlers); @@ -1031,31 +1020,8 @@ int qemu_set_fd_handler2(int fd, IOHandler *fd_write, void *opaque) { - IOHandlerRecord *ioh; - - if (!fd_read && !fd_write) { - QLIST_FOREACH(ioh, &io_handlers, next) { - if (ioh->fd == fd) { - ioh->deleted = 1; - break; - } - } - } else { - QLIST_FOREACH(ioh, &io_handlers, next) { - if (ioh->fd == fd) - goto found; - } - ioh = qemu_mallocz(sizeof(IOHandlerRecord)); - QLIST_INSERT_HEAD(&io_handlers, ioh, next); - found: - ioh->fd = fd; - ioh->fd_read_poll = fd_read_poll; - ioh->fd_read = fd_read; - ioh->fd_write = fd_write; - ioh->opaque = opaque; - ioh->deleted = 0; - } - return 0; + return qemu_set_fd_handler3(&io_handlers, fd, fd_read_poll, fd_read, + fd_write, opaque); } int qemu_set_fd_handler(int fd, @@ -1066,6 +1032,17 @@ int qemu_set_fd_handler(int fd, return qemu_set_fd_handler2(fd, NULL, fd_read, fd_write, opaque); } +void qemu_get_fdset(int *nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds) +{ + return qemu_get_fdset2(&io_handlers, nfds, rfds, wfds, xfds); +} + +void qemu_process_fd_handlers(const fd_set *rfds, const fd_set *wfds, + const fd_set *xfds) +{ + return qemu_process_fd_handlers2(&io_handlers, rfds, wfds, xfds); +} + /***********************************************************/ /* machine registration */ @@ -1295,7 +1272,6 @@ void qemu_system_powerdown_request(void) void main_loop_wait(int nonblocking) { - IOHandlerRecord *ioh; fd_set rfds, wfds, xfds; int ret, nfds; struct timeval tv; @@ -1316,22 +1292,7 @@ void main_loop_wait(int nonblocking) FD_ZERO(&rfds); FD_ZERO(&wfds); FD_ZERO(&xfds); - QLIST_FOREACH(ioh, &io_handlers, next) { - if (ioh->deleted) - continue; - if (ioh->fd_read && - (!ioh->fd_read_poll || - ioh->fd_read_poll(ioh->opaque) != 0)) { - FD_SET(ioh->fd, &rfds); - if (ioh->fd > nfds) - nfds = ioh->fd; - } - if (ioh->fd_write) { - FD_SET(ioh->fd, &wfds); - if (ioh->fd > nfds) - nfds = ioh->fd; - } - } + qemu_get_fdset(&nfds, &rfds, &wfds, &xfds); tv.tv_sec = timeout / 1000; tv.tv_usec = (timeout % 1000) * 1000; @@ -1342,22 +1303,7 @@ void main_loop_wait(int nonblocking) ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv); qemu_mutex_lock_iothread(); if (ret > 0) { - IOHandlerRecord *pioh; - - QLIST_FOREACH_SAFE(ioh, &io_handlers, next, pioh) { - if (!ioh->deleted && ioh->fd_read && FD_ISSET(ioh->fd, &rfds)) { - ioh->fd_read(ioh->opaque); - } - if (!ioh->deleted && ioh->fd_write && FD_ISSET(ioh->fd, &wfds)) { - ioh->fd_write(ioh->opaque); - } - - /* Do this last in case read/write handlers marked it for deletion */ - if (ioh->deleted) { - QLIST_REMOVE(ioh, next); - qemu_free(ioh); - } - } + qemu_process_fd_handlers(&rfds, &wfds, &xfds); } slirp_select_poll(&rfds, &wfds, &xfds, (ret < 0)); -- 2.11.4.GIT