Statistics
| Branch: | Revision:

root / aio-win32.c @ 5a37532d

History | View | Annotate | Download (5.8 kB)

1 a76bab49 aliguori
/*
2 a76bab49 aliguori
 * QEMU aio implementation
3 a76bab49 aliguori
 *
4 f42b2207 Paolo Bonzini
 * Copyright IBM Corp., 2008
5 f42b2207 Paolo Bonzini
 * Copyright Red Hat Inc., 2012
6 a76bab49 aliguori
 *
7 a76bab49 aliguori
 * Authors:
8 a76bab49 aliguori
 *  Anthony Liguori   <aliguori@us.ibm.com>
9 f42b2207 Paolo Bonzini
 *  Paolo Bonzini     <pbonzini@redhat.com>
10 a76bab49 aliguori
 *
11 a76bab49 aliguori
 * This work is licensed under the terms of the GNU GPL, version 2.  See
12 a76bab49 aliguori
 * the COPYING file in the top-level directory.
13 a76bab49 aliguori
 *
14 6b620ca3 Paolo Bonzini
 * Contributions after 2012-01-13 are licensed under the terms of the
15 6b620ca3 Paolo Bonzini
 * GNU GPL, version 2 or (at your option) any later version.
16 a76bab49 aliguori
 */
17 a76bab49 aliguori
18 a76bab49 aliguori
#include "qemu-common.h"
19 737e150e Paolo Bonzini
#include "block/block.h"
20 1de7afc9 Paolo Bonzini
#include "qemu/queue.h"
21 1de7afc9 Paolo Bonzini
#include "qemu/sockets.h"
22 a76bab49 aliguori
23 f42b2207 Paolo Bonzini
struct AioHandler {
24 f42b2207 Paolo Bonzini
    EventNotifier *e;
25 f42b2207 Paolo Bonzini
    EventNotifierHandler *io_notify;
26 f42b2207 Paolo Bonzini
    AioFlushEventNotifierHandler *io_flush;
27 cd9ba1eb Paolo Bonzini
    GPollFD pfd;
28 a76bab49 aliguori
    int deleted;
29 72cf2d4f Blue Swirl
    QLIST_ENTRY(AioHandler) node;
30 a76bab49 aliguori
};
31 a76bab49 aliguori
32 f42b2207 Paolo Bonzini
void aio_set_event_notifier(AioContext *ctx,
33 f42b2207 Paolo Bonzini
                            EventNotifier *e,
34 f42b2207 Paolo Bonzini
                            EventNotifierHandler *io_notify,
35 f42b2207 Paolo Bonzini
                            AioFlushEventNotifierHandler *io_flush)
36 a76bab49 aliguori
{
37 a76bab49 aliguori
    AioHandler *node;
38 a76bab49 aliguori
39 a915f4bc Paolo Bonzini
    QLIST_FOREACH(node, &ctx->aio_handlers, node) {
40 f42b2207 Paolo Bonzini
        if (node->e == e && !node->deleted) {
41 f42b2207 Paolo Bonzini
            break;
42 f42b2207 Paolo Bonzini
        }
43 a76bab49 aliguori
    }
44 a76bab49 aliguori
45 a76bab49 aliguori
    /* Are we deleting the fd handler? */
46 f42b2207 Paolo Bonzini
    if (!io_notify) {
47 a76bab49 aliguori
        if (node) {
48 e3713e00 Paolo Bonzini
            g_source_remove_poll(&ctx->source, &node->pfd);
49 e3713e00 Paolo Bonzini
50 a76bab49 aliguori
            /* If the lock is held, just mark the node as deleted */
51 cd9ba1eb Paolo Bonzini
            if (ctx->walking_handlers) {
52 a76bab49 aliguori
                node->deleted = 1;
53 cd9ba1eb Paolo Bonzini
                node->pfd.revents = 0;
54 cd9ba1eb Paolo Bonzini
            } else {
55 a76bab49 aliguori
                /* Otherwise, delete it for real.  We can't just mark it as
56 a76bab49 aliguori
                 * deleted because deleted nodes are only cleaned up after
57 a76bab49 aliguori
                 * releasing the walking_handlers lock.
58 a76bab49 aliguori
                 */
59 72cf2d4f Blue Swirl
                QLIST_REMOVE(node, node);
60 7267c094 Anthony Liguori
                g_free(node);
61 a76bab49 aliguori
            }
62 a76bab49 aliguori
        }
63 a76bab49 aliguori
    } else {
64 a76bab49 aliguori
        if (node == NULL) {
65 a76bab49 aliguori
            /* Alloc and insert if it's not already there */
66 7267c094 Anthony Liguori
            node = g_malloc0(sizeof(AioHandler));
67 f42b2207 Paolo Bonzini
            node->e = e;
68 f42b2207 Paolo Bonzini
            node->pfd.fd = (uintptr_t)event_notifier_get_handle(e);
69 f42b2207 Paolo Bonzini
            node->pfd.events = G_IO_IN;
70 a915f4bc Paolo Bonzini
            QLIST_INSERT_HEAD(&ctx->aio_handlers, node, node);
71 e3713e00 Paolo Bonzini
72 e3713e00 Paolo Bonzini
            g_source_add_poll(&ctx->source, &node->pfd);
73 a76bab49 aliguori
        }
74 a76bab49 aliguori
        /* Update handler with latest information */
75 f42b2207 Paolo Bonzini
        node->io_notify = io_notify;
76 a76bab49 aliguori
        node->io_flush = io_flush;
77 a76bab49 aliguori
    }
78 7ed2b24c Paolo Bonzini
79 7ed2b24c Paolo Bonzini
    aio_notify(ctx);
80 9958c351 Paolo Bonzini
}
81 9958c351 Paolo Bonzini
82 cd9ba1eb Paolo Bonzini
bool aio_pending(AioContext *ctx)
83 cd9ba1eb Paolo Bonzini
{
84 cd9ba1eb Paolo Bonzini
    AioHandler *node;
85 cd9ba1eb Paolo Bonzini
86 cd9ba1eb Paolo Bonzini
    QLIST_FOREACH(node, &ctx->aio_handlers, node) {
87 f42b2207 Paolo Bonzini
        if (node->pfd.revents && node->io_notify) {
88 cd9ba1eb Paolo Bonzini
            return true;
89 cd9ba1eb Paolo Bonzini
        }
90 cd9ba1eb Paolo Bonzini
    }
91 cd9ba1eb Paolo Bonzini
92 cd9ba1eb Paolo Bonzini
    return false;
93 cd9ba1eb Paolo Bonzini
}
94 cd9ba1eb Paolo Bonzini
95 7c0628b2 Paolo Bonzini
bool aio_poll(AioContext *ctx, bool blocking)
96 a76bab49 aliguori
{
97 9eb0bfca Paolo Bonzini
    AioHandler *node;
98 f42b2207 Paolo Bonzini
    HANDLE events[MAXIMUM_WAIT_OBJECTS + 1];
99 7c0628b2 Paolo Bonzini
    bool busy, progress;
100 f42b2207 Paolo Bonzini
    int count;
101 7c0628b2 Paolo Bonzini
102 7c0628b2 Paolo Bonzini
    progress = false;
103 a76bab49 aliguori
104 8febfa26 Kevin Wolf
    /*
105 8febfa26 Kevin Wolf
     * If there are callbacks left that have been queued, we need to call then.
106 bcdc1857 Paolo Bonzini
     * Do not call select in this case, because it is possible that the caller
107 bcdc1857 Paolo Bonzini
     * does not need a complete flush (as is the case for qemu_aio_wait loops).
108 8febfa26 Kevin Wolf
     */
109 a915f4bc Paolo Bonzini
    if (aio_bh_poll(ctx)) {
110 7c0628b2 Paolo Bonzini
        blocking = false;
111 7c0628b2 Paolo Bonzini
        progress = true;
112 7c0628b2 Paolo Bonzini
    }
113 7c0628b2 Paolo Bonzini
114 cd9ba1eb Paolo Bonzini
    /*
115 cd9ba1eb Paolo Bonzini
     * Then dispatch any pending callbacks from the GSource.
116 cd9ba1eb Paolo Bonzini
     *
117 cd9ba1eb Paolo Bonzini
     * We have to walk very carefully in case qemu_aio_set_fd_handler is
118 cd9ba1eb Paolo Bonzini
     * called while we're walking.
119 cd9ba1eb Paolo Bonzini
     */
120 cd9ba1eb Paolo Bonzini
    node = QLIST_FIRST(&ctx->aio_handlers);
121 cd9ba1eb Paolo Bonzini
    while (node) {
122 cd9ba1eb Paolo Bonzini
        AioHandler *tmp;
123 cd9ba1eb Paolo Bonzini
124 cd9ba1eb Paolo Bonzini
        ctx->walking_handlers++;
125 cd9ba1eb Paolo Bonzini
126 f42b2207 Paolo Bonzini
        if (node->pfd.revents && node->io_notify) {
127 f42b2207 Paolo Bonzini
            node->pfd.revents = 0;
128 f42b2207 Paolo Bonzini
            node->io_notify(node->e);
129 cd9ba1eb Paolo Bonzini
            progress = true;
130 cd9ba1eb Paolo Bonzini
        }
131 cd9ba1eb Paolo Bonzini
132 cd9ba1eb Paolo Bonzini
        tmp = node;
133 cd9ba1eb Paolo Bonzini
        node = QLIST_NEXT(node, node);
134 cd9ba1eb Paolo Bonzini
135 cd9ba1eb Paolo Bonzini
        ctx->walking_handlers--;
136 cd9ba1eb Paolo Bonzini
137 cd9ba1eb Paolo Bonzini
        if (!ctx->walking_handlers && tmp->deleted) {
138 cd9ba1eb Paolo Bonzini
            QLIST_REMOVE(tmp, node);
139 cd9ba1eb Paolo Bonzini
            g_free(tmp);
140 cd9ba1eb Paolo Bonzini
        }
141 cd9ba1eb Paolo Bonzini
    }
142 cd9ba1eb Paolo Bonzini
143 7c0628b2 Paolo Bonzini
    if (progress && !blocking) {
144 bcdc1857 Paolo Bonzini
        return true;
145 bafbd6a1 Paolo Bonzini
    }
146 8febfa26 Kevin Wolf
147 a915f4bc Paolo Bonzini
    ctx->walking_handlers++;
148 a76bab49 aliguori
149 9eb0bfca Paolo Bonzini
    /* fill fd sets */
150 9eb0bfca Paolo Bonzini
    busy = false;
151 f42b2207 Paolo Bonzini
    count = 0;
152 a915f4bc Paolo Bonzini
    QLIST_FOREACH(node, &ctx->aio_handlers, node) {
153 9eb0bfca Paolo Bonzini
        /* If there aren't pending AIO operations, don't invoke callbacks.
154 9eb0bfca Paolo Bonzini
         * Otherwise, if there are no AIO requests, qemu_aio_wait() would
155 9eb0bfca Paolo Bonzini
         * wait indefinitely.
156 9eb0bfca Paolo Bonzini
         */
157 4231c88d Paolo Bonzini
        if (!node->deleted && node->io_flush) {
158 f42b2207 Paolo Bonzini
            if (node->io_flush(node->e) == 0) {
159 9eb0bfca Paolo Bonzini
                continue;
160 a76bab49 aliguori
            }
161 9eb0bfca Paolo Bonzini
            busy = true;
162 9eb0bfca Paolo Bonzini
        }
163 f42b2207 Paolo Bonzini
        if (!node->deleted && node->io_notify) {
164 f42b2207 Paolo Bonzini
            events[count++] = event_notifier_get_handle(node->e);
165 9eb0bfca Paolo Bonzini
        }
166 9eb0bfca Paolo Bonzini
    }
167 a76bab49 aliguori
168 a915f4bc Paolo Bonzini
    ctx->walking_handlers--;
169 a76bab49 aliguori
170 9eb0bfca Paolo Bonzini
    /* No AIO operations?  Get us out of here */
171 9eb0bfca Paolo Bonzini
    if (!busy) {
172 7c0628b2 Paolo Bonzini
        return progress;
173 9eb0bfca Paolo Bonzini
    }
174 a76bab49 aliguori
175 9eb0bfca Paolo Bonzini
    /* wait until next event */
176 b022b4a4 Paolo Bonzini
    while (count > 0) {
177 f42b2207 Paolo Bonzini
        int timeout = blocking ? INFINITE : 0;
178 f42b2207 Paolo Bonzini
        int ret = WaitForMultipleObjects(count, events, FALSE, timeout);
179 f42b2207 Paolo Bonzini
180 f42b2207 Paolo Bonzini
        /* if we have any signaled events, dispatch event */
181 f42b2207 Paolo Bonzini
        if ((DWORD) (ret - WAIT_OBJECT_0) >= count) {
182 f42b2207 Paolo Bonzini
            break;
183 f42b2207 Paolo Bonzini
        }
184 f42b2207 Paolo Bonzini
185 f42b2207 Paolo Bonzini
        blocking = false;
186 9eb0bfca Paolo Bonzini
187 9eb0bfca Paolo Bonzini
        /* we have to walk very carefully in case
188 9eb0bfca Paolo Bonzini
         * qemu_aio_set_fd_handler is called while we're walking */
189 a915f4bc Paolo Bonzini
        node = QLIST_FIRST(&ctx->aio_handlers);
190 9eb0bfca Paolo Bonzini
        while (node) {
191 9eb0bfca Paolo Bonzini
            AioHandler *tmp;
192 9eb0bfca Paolo Bonzini
193 a915f4bc Paolo Bonzini
            ctx->walking_handlers++;
194 2db2bfc0 Paolo Bonzini
195 9eb0bfca Paolo Bonzini
            if (!node->deleted &&
196 f42b2207 Paolo Bonzini
                event_notifier_get_handle(node->e) == events[ret - WAIT_OBJECT_0] &&
197 f42b2207 Paolo Bonzini
                node->io_notify) {
198 f42b2207 Paolo Bonzini
                node->io_notify(node->e);
199 cd9ba1eb Paolo Bonzini
                progress = true;
200 a76bab49 aliguori
            }
201 a76bab49 aliguori
202 9eb0bfca Paolo Bonzini
            tmp = node;
203 9eb0bfca Paolo Bonzini
            node = QLIST_NEXT(node, node);
204 9eb0bfca Paolo Bonzini
205 a915f4bc Paolo Bonzini
            ctx->walking_handlers--;
206 2db2bfc0 Paolo Bonzini
207 a915f4bc Paolo Bonzini
            if (!ctx->walking_handlers && tmp->deleted) {
208 9eb0bfca Paolo Bonzini
                QLIST_REMOVE(tmp, node);
209 9eb0bfca Paolo Bonzini
                g_free(tmp);
210 9eb0bfca Paolo Bonzini
            }
211 a76bab49 aliguori
        }
212 b022b4a4 Paolo Bonzini
213 b022b4a4 Paolo Bonzini
        /* Try again, but only call each handler once.  */
214 b022b4a4 Paolo Bonzini
        events[ret - WAIT_OBJECT_0] = events[--count];
215 9eb0bfca Paolo Bonzini
    }
216 bcdc1857 Paolo Bonzini
217 2ea9b58f Kevin Wolf
    assert(progress || busy);
218 2ea9b58f Kevin Wolf
    return true;
219 a76bab49 aliguori
}