iohandler: Use aio API
iohandler.c shares the same interface with aio, but with duplicated code. It's better to rebase iohandler, also because that aio is a more friendly interface to multi-threads. Create a global AioContext instance and let its GSource handle the iohandler events. Signed-off-by: Fam Zheng <famz@redhat.com> Message-Id: <1441596538-4412-1-git-send-email-famz@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
46036b2462
commit
f3926945c8
@ -203,6 +203,7 @@ void qemu_set_fd_handler(int fd,
|
|||||||
IOHandler *fd_write,
|
IOHandler *fd_write,
|
||||||
void *opaque);
|
void *opaque);
|
||||||
|
|
||||||
|
GSource *iohandler_get_g_source(void);
|
||||||
#ifdef CONFIG_POSIX
|
#ifdef CONFIG_POSIX
|
||||||
/**
|
/**
|
||||||
* qemu_add_child_watch: Register a child process for reaping.
|
* qemu_add_child_watch: Register a child process for reaping.
|
||||||
@ -265,8 +266,6 @@ void qemu_mutex_unlock_iothread(void);
|
|||||||
/* internal interfaces */
|
/* internal interfaces */
|
||||||
|
|
||||||
void qemu_fd_register(int fd);
|
void qemu_fd_register(int fd);
|
||||||
void qemu_iohandler_fill(GArray *pollfds);
|
|
||||||
void qemu_iohandler_poll(GArray *pollfds, int rc);
|
|
||||||
|
|
||||||
QEMUBH *qemu_bh_new(QEMUBHFunc *cb, void *opaque);
|
QEMUBH *qemu_bh_new(QEMUBHFunc *cb, void *opaque);
|
||||||
void qemu_bh_schedule_idle(QEMUBH *bh);
|
void qemu_bh_schedule_idle(QEMUBH *bh);
|
||||||
|
115
iohandler.c
115
iohandler.c
@ -32,111 +32,30 @@
|
|||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct IOHandlerRecord {
|
/* This context runs on top of main loop. We can't reuse qemu_aio_context
|
||||||
IOHandler *fd_read;
|
* because iohandlers mustn't be polled by aio_poll(qemu_aio_context). */
|
||||||
IOHandler *fd_write;
|
static AioContext *iohandler_ctx;
|
||||||
void *opaque;
|
|
||||||
QLIST_ENTRY(IOHandlerRecord) next;
|
|
||||||
int fd;
|
|
||||||
int pollfds_idx;
|
|
||||||
bool deleted;
|
|
||||||
} IOHandlerRecord;
|
|
||||||
|
|
||||||
static QLIST_HEAD(, IOHandlerRecord) io_handlers =
|
static void iohandler_init(void)
|
||||||
QLIST_HEAD_INITIALIZER(io_handlers);
|
{
|
||||||
|
if (!iohandler_ctx) {
|
||||||
|
iohandler_ctx = aio_context_new(&error_abort);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GSource *iohandler_get_g_source(void)
|
||||||
|
{
|
||||||
|
iohandler_init();
|
||||||
|
return aio_get_g_source(iohandler_ctx);
|
||||||
|
}
|
||||||
|
|
||||||
void qemu_set_fd_handler(int fd,
|
void qemu_set_fd_handler(int fd,
|
||||||
IOHandler *fd_read,
|
IOHandler *fd_read,
|
||||||
IOHandler *fd_write,
|
IOHandler *fd_write,
|
||||||
void *opaque)
|
void *opaque)
|
||||||
{
|
{
|
||||||
IOHandlerRecord *ioh;
|
iohandler_init();
|
||||||
|
aio_set_fd_handler(iohandler_ctx, fd, fd_read, fd_write, opaque);
|
||||||
assert(fd >= 0);
|
|
||||||
|
|
||||||
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 = g_malloc0(sizeof(IOHandlerRecord));
|
|
||||||
QLIST_INSERT_HEAD(&io_handlers, ioh, next);
|
|
||||||
found:
|
|
||||||
ioh->fd = fd;
|
|
||||||
ioh->fd_read = fd_read;
|
|
||||||
ioh->fd_write = fd_write;
|
|
||||||
ioh->opaque = opaque;
|
|
||||||
ioh->pollfds_idx = -1;
|
|
||||||
ioh->deleted = 0;
|
|
||||||
qemu_notify_event();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void qemu_iohandler_fill(GArray *pollfds)
|
|
||||||
{
|
|
||||||
IOHandlerRecord *ioh;
|
|
||||||
|
|
||||||
QLIST_FOREACH(ioh, &io_handlers, next) {
|
|
||||||
int events = 0;
|
|
||||||
|
|
||||||
if (ioh->deleted)
|
|
||||||
continue;
|
|
||||||
if (ioh->fd_read) {
|
|
||||||
events |= G_IO_IN | G_IO_HUP | G_IO_ERR;
|
|
||||||
}
|
|
||||||
if (ioh->fd_write) {
|
|
||||||
events |= G_IO_OUT | G_IO_ERR;
|
|
||||||
}
|
|
||||||
if (events) {
|
|
||||||
GPollFD pfd = {
|
|
||||||
.fd = ioh->fd,
|
|
||||||
.events = events,
|
|
||||||
};
|
|
||||||
ioh->pollfds_idx = pollfds->len;
|
|
||||||
g_array_append_val(pollfds, pfd);
|
|
||||||
} else {
|
|
||||||
ioh->pollfds_idx = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void qemu_iohandler_poll(GArray *pollfds, int ret)
|
|
||||||
{
|
|
||||||
if (ret > 0) {
|
|
||||||
IOHandlerRecord *pioh, *ioh;
|
|
||||||
|
|
||||||
QLIST_FOREACH_SAFE(ioh, &io_handlers, next, pioh) {
|
|
||||||
int revents = 0;
|
|
||||||
|
|
||||||
if (!ioh->deleted && ioh->pollfds_idx != -1) {
|
|
||||||
GPollFD *pfd = &g_array_index(pollfds, GPollFD,
|
|
||||||
ioh->pollfds_idx);
|
|
||||||
revents = pfd->revents;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ioh->deleted && ioh->fd_read &&
|
|
||||||
(revents & (G_IO_IN | G_IO_HUP | G_IO_ERR))) {
|
|
||||||
ioh->fd_read(ioh->opaque);
|
|
||||||
}
|
|
||||||
if (!ioh->deleted && ioh->fd_write &&
|
|
||||||
(revents & (G_IO_OUT | G_IO_ERR))) {
|
|
||||||
ioh->fd_write(ioh->opaque);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Do this last in case read/write handlers marked it for deletion */
|
|
||||||
if (ioh->deleted) {
|
|
||||||
QLIST_REMOVE(ioh, next);
|
|
||||||
g_free(ioh);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* reaping of zombies. right now we're not passing the status to
|
/* reaping of zombies. right now we're not passing the status to
|
||||||
|
@ -161,6 +161,9 @@ int qemu_init_main_loop(Error **errp)
|
|||||||
src = aio_get_g_source(qemu_aio_context);
|
src = aio_get_g_source(qemu_aio_context);
|
||||||
g_source_attach(src, NULL);
|
g_source_attach(src, NULL);
|
||||||
g_source_unref(src);
|
g_source_unref(src);
|
||||||
|
src = iohandler_get_g_source();
|
||||||
|
g_source_attach(src, NULL);
|
||||||
|
g_source_unref(src);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -487,7 +490,6 @@ int main_loop_wait(int nonblocking)
|
|||||||
#ifdef CONFIG_SLIRP
|
#ifdef CONFIG_SLIRP
|
||||||
slirp_pollfds_fill(gpollfds, &timeout);
|
slirp_pollfds_fill(gpollfds, &timeout);
|
||||||
#endif
|
#endif
|
||||||
qemu_iohandler_fill(gpollfds);
|
|
||||||
|
|
||||||
if (timeout == UINT32_MAX) {
|
if (timeout == UINT32_MAX) {
|
||||||
timeout_ns = -1;
|
timeout_ns = -1;
|
||||||
@ -500,7 +502,6 @@ int main_loop_wait(int nonblocking)
|
|||||||
&main_loop_tlg));
|
&main_loop_tlg));
|
||||||
|
|
||||||
ret = os_host_main_loop_wait(timeout_ns);
|
ret = os_host_main_loop_wait(timeout_ns);
|
||||||
qemu_iohandler_poll(gpollfds, ret);
|
|
||||||
#ifdef CONFIG_SLIRP
|
#ifdef CONFIG_SLIRP
|
||||||
slirp_pollfds_poll(gpollfds, (ret < 0));
|
slirp_pollfds_poll(gpollfds, (ret < 0));
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user