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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user