1/* 2 * QEMU System Emulator 3 * 4 * Copyright (c) 2003-2008 Fabrice Bellard 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and associated documentation files (the "Software"), to deal 8 * in the Software without restriction, including without limitation the rights 9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 * copies of the Software, and to permit persons to whom the Software is 11 * furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 * THE SOFTWARE. 23 */ 24 25#include "qemu-common.h" 26#include "qemu-aio.h" 27 28/* 29 * An AsyncContext protects the callbacks of AIO requests and Bottom Halves 30 * against interfering with each other. A typical example is qcow2 that accepts 31 * asynchronous requests, but relies for manipulation of its metadata on 32 * synchronous bdrv_read/write that doesn't trigger any callbacks. 33 * 34 * However, these functions are often emulated using AIO which means that AIO 35 * callbacks must be run - but at the same time we must not run callbacks of 36 * other requests as they might start to modify metadata and corrupt the 37 * internal state of the caller of bdrv_read/write. 38 * 39 * To achieve the desired semantics we switch into a new AsyncContext. 40 * Callbacks must only be run if they belong to the current AsyncContext. 41 * Otherwise they need to be queued until their own context is active again. 42 * This is how you can make qemu_aio_wait() wait only for your own callbacks. 43 * 44 * The AsyncContexts form a stack. When you leave a AsyncContexts, you always 45 * return to the old ("parent") context. 46 */ 47struct AsyncContext { 48 /* Consecutive number of the AsyncContext (position in the stack) */ 49 int id; 50 51 /* Anchor of the list of Bottom Halves belonging to the context */ 52 struct QEMUBH *first_bh; 53 54 /* Link to parent context */ 55 struct AsyncContext *parent; 56}; 57 58/* The currently active AsyncContext */ 59static struct AsyncContext *async_context = &(struct AsyncContext) { 0 }; 60 61/* 62 * Enter a new AsyncContext. Already scheduled Bottom Halves and AIO callbacks 63 * won't be called until this context is left again. 64 */ 65void async_context_push(void) 66{ 67 struct AsyncContext *new = qemu_mallocz(sizeof(*new)); 68 new->parent = async_context; 69 new->id = async_context->id + 1; 70 async_context = new; 71} 72 73/* Run queued AIO completions and destroy Bottom Half */ 74static void bh_run_aio_completions(void *opaque) 75{ 76 QEMUBH **bh = opaque; 77 qemu_bh_delete(*bh); 78 qemu_free(bh); 79 qemu_aio_process_queue(); 80} 81/* 82 * Leave the currently active AsyncContext. All Bottom Halves belonging to the 83 * old context are executed before changing the context. 84 */ 85void async_context_pop(void) 86{ 87 struct AsyncContext *old = async_context; 88 QEMUBH **bh; 89 90 /* Flush the bottom halves, we don't want to lose them */ 91 while (qemu_bh_poll()); 92 93 /* Switch back to the parent context */ 94 async_context = async_context->parent; 95 qemu_free(old); 96 97 if (async_context == NULL) { 98 abort(); 99 } 100 101 /* Schedule BH to run any queued AIO completions as soon as possible */ 102 bh = qemu_malloc(sizeof(*bh)); 103 *bh = qemu_bh_new(bh_run_aio_completions, bh); 104 qemu_bh_schedule(*bh); 105} 106 107/* 108 * Returns the ID of the currently active AsyncContext 109 */ 110int get_async_context_id(void) 111{ 112 return async_context->id; 113} 114 115/***********************************************************/ 116/* bottom halves (can be seen as timers which expire ASAP) */ 117 118struct QEMUBH { 119 QEMUBHFunc *cb; 120 void *opaque; 121 int scheduled; 122 int idle; 123 int deleted; 124 QEMUBH *next; 125}; 126 127QEMUBH *qemu_bh_new(QEMUBHFunc *cb, void *opaque) 128{ 129 QEMUBH *bh; 130 bh = qemu_mallocz(sizeof(QEMUBH)); 131 bh->cb = cb; 132 bh->opaque = opaque; 133 bh->next = async_context->first_bh; 134 async_context->first_bh = bh; 135 return bh; 136} 137 138int qemu_bh_poll(void) 139{ 140 QEMUBH *bh, **bhp; 141 int ret; 142 143 ret = 0; 144 for (bh = async_context->first_bh; bh; bh = bh->next) { 145 if (!bh->deleted && bh->scheduled) { 146 bh->scheduled = 0; 147 if (!bh->idle) 148 ret = 1; 149 bh->idle = 0; 150 bh->cb(bh->opaque); 151 } 152 } 153 154 /* remove deleted bhs */ 155 bhp = &async_context->first_bh; 156 while (*bhp) { 157 bh = *bhp; 158 if (bh->deleted) { 159 *bhp = bh->next; 160 qemu_free(bh); 161 } else 162 bhp = &bh->next; 163 } 164 165 return ret; 166} 167 168void qemu_bh_schedule_idle(QEMUBH *bh) 169{ 170 if (bh->scheduled) 171 return; 172 bh->scheduled = 1; 173 bh->idle = 1; 174} 175 176void qemu_bh_schedule(QEMUBH *bh) 177{ 178 if (bh->scheduled) 179 return; 180 bh->scheduled = 1; 181 bh->idle = 0; 182 /* stop the currently executing CPU to execute the BH ASAP */ 183 qemu_notify_event(); 184} 185 186void qemu_bh_cancel(QEMUBH *bh) 187{ 188 bh->scheduled = 0; 189} 190 191void qemu_bh_delete(QEMUBH *bh) 192{ 193 bh->scheduled = 0; 194 bh->deleted = 1; 195} 196 197void qemu_bh_update_timeout(int *timeout) 198{ 199 QEMUBH *bh; 200 201 for (bh = async_context->first_bh; bh; bh = bh->next) { 202 if (!bh->deleted && bh->scheduled) { 203 if (bh->idle) { 204 /* idle bottom halves will be polled at least 205 * every 10ms */ 206 *timeout = MIN(10, *timeout); 207 } else { 208 /* non-idle bottom halves will be executed 209 * immediately */ 210 *timeout = 0; 211 break; 212 } 213 } 214 } 215} 216 217