2
* QEMU aio implementation
4
* Copyright IBM, Corp. 2008
7
* Anthony Liguori <aliguori@us.ibm.com>
9
* This work is licensed under the terms of the GNU GPL, version 2. See
10
* the COPYING file in the top-level directory.
14
#include "qemu-common.h"
16
#include "sys-queue.h"
17
#include "qemu_socket.h"
19
typedef struct AioHandler AioHandler;
21
/* The list of registered AIO handlers */
22
static LIST_HEAD(, AioHandler) aio_handlers;
24
/* This is a simple lock used to protect the aio_handlers list. Specifically,
25
* it's used to ensure that no callbacks are removed while we're walking and
26
* dispatching callbacks.
28
static int walking_handlers;
35
AioFlushHandler *io_flush;
38
LIST_ENTRY(AioHandler) node;
41
static AioHandler *find_aio_handler(int fd)
45
LIST_FOREACH(node, &aio_handlers, node) {
53
int qemu_aio_set_fd_handler(int fd,
56
AioFlushHandler *io_flush,
61
node = find_aio_handler(fd);
63
/* Are we deleting the fd handler? */
64
if (!io_read && !io_write) {
66
/* If the lock is held, just mark the node as deleted */
70
/* Otherwise, delete it for real. We can't just mark it as
71
* deleted because deleted nodes are only cleaned up after
72
* releasing the walking_handlers lock.
74
LIST_REMOVE(node, node);
80
/* Alloc and insert if it's not already there */
81
node = qemu_mallocz(sizeof(AioHandler));
85
LIST_INSERT_HEAD(&aio_handlers, node, node);
87
/* Update handler with latest information */
88
node->io_read = io_read;
89
node->io_write = io_write;
90
node->io_flush = io_flush;
91
node->opaque = opaque;
94
qemu_set_fd_handler2(fd, NULL, io_read, io_write, opaque);
99
void qemu_aio_flush(void)
107
LIST_FOREACH(node, &aio_handlers, node) {
108
ret |= node->io_flush(node->opaque);
115
void qemu_aio_wait(void)
127
walking_handlers = 1;
133
LIST_FOREACH(node, &aio_handlers, node) {
134
/* If there aren't pending AIO operations, don't invoke callbacks.
135
* Otherwise, if there are no AIO requests, qemu_aio_wait() would
138
if (node->io_flush && node->io_flush(node->opaque) == 0)
141
if (!node->deleted && node->io_read) {
142
FD_SET(node->fd, &rdfds);
143
max_fd = MAX(max_fd, node->fd + 1);
145
if (!node->deleted && node->io_write) {
146
FD_SET(node->fd, &wrfds);
147
max_fd = MAX(max_fd, node->fd + 1);
151
walking_handlers = 0;
153
/* No AIO operations? Get us out of here */
157
/* wait until next event */
158
ret = select(max_fd, &rdfds, &wrfds, NULL, NULL);
159
if (ret == -1 && errno == EINTR)
162
/* if we have any readable fds, dispatch event */
164
walking_handlers = 1;
166
/* we have to walk very carefully in case
167
* qemu_aio_set_fd_handler is called while we're walking */
168
node = LIST_FIRST(&aio_handlers);
172
if (!node->deleted &&
173
FD_ISSET(node->fd, &rdfds) &&
175
node->io_read(node->opaque);
177
if (!node->deleted &&
178
FD_ISSET(node->fd, &wrfds) &&
180
node->io_write(node->opaque);
184
node = LIST_NEXT(node, node);
187
LIST_REMOVE(tmp, node);
192
walking_handlers = 0;