| 1 | /* |
| 2 | * AioContext wait support |
| 3 | * |
| 4 | * Copyright (C) 2018 Red Hat, Inc. |
| 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 | #ifndef QEMU_AIO_WAIT_H |
| 26 | #define QEMU_AIO_WAIT_H |
| 27 | |
| 28 | #include "qemu/aio.h" |
| 29 | #include "qemu/main-loop.h" |
| 30 | |
| 31 | /** |
| 32 | * AioWait: |
| 33 | * |
| 34 | * An object that facilitates synchronous waiting on a condition. A single |
| 35 | * global AioWait object (global_aio_wait) is used internally. |
| 36 | * |
| 37 | * The main loop can wait on an operation running in an IOThread as follows: |
| 38 | * |
| 39 | * AioContext *ctx = ...; |
| 40 | * MyWork work = { .done = false }; |
| 41 | * schedule_my_work_in_iothread(ctx, &work); |
| 42 | * AIO_WAIT_WHILE(ctx, !work.done); |
| 43 | * |
| 44 | * The IOThread must call aio_wait_kick() to notify the main loop when |
| 45 | * work.done changes: |
| 46 | * |
| 47 | * static void do_work(...) |
| 48 | * { |
| 49 | * ... |
| 50 | * work.done = true; |
| 51 | * aio_wait_kick(); |
| 52 | * } |
| 53 | */ |
| 54 | typedef struct { |
| 55 | /* Number of waiting AIO_WAIT_WHILE() callers. Accessed with atomic ops. */ |
| 56 | unsigned num_waiters; |
| 57 | } AioWait; |
| 58 | |
| 59 | extern AioWait global_aio_wait; |
| 60 | |
| 61 | /** |
| 62 | * AIO_WAIT_WHILE_INTERNAL: |
| 63 | * @ctx: the aio context, or NULL if multiple aio contexts (for which the |
| 64 | * caller does not hold a lock) are involved in the polling condition. |
| 65 | * @cond: wait while this conditional expression is true |
| 66 | * |
| 67 | * Wait while a condition is true. Use this to implement synchronous |
| 68 | * operations that require event loop activity. |
| 69 | * |
| 70 | * The caller must be sure that something calls aio_wait_kick() when the value |
| 71 | * of @cond might have changed. |
| 72 | * |
| 73 | * The caller's thread must be the IOThread that owns @ctx or the main loop |
| 74 | * thread (with @ctx acquired exactly once). This function cannot be used to |
| 75 | * wait on conditions between two IOThreads since that could lead to deadlock, |
| 76 | * go via the main loop instead. |
| 77 | */ |
| 78 | #define AIO_WAIT_WHILE_INTERNAL(ctx, cond) ({ \ |
| 79 | bool waited_ = false; \ |
| 80 | AioWait *wait_ = &global_aio_wait; \ |
| 81 | AioContext *ctx_ = (ctx); \ |
| 82 | /* Increment wait_->num_waiters before evaluating cond. */ \ |
| 83 | qatomic_inc(&wait_->num_waiters); \ |
| 84 | /* Paired with smp_mb in aio_wait_kick(). */ \ |
| 85 | smp_mb__after_rmw(); \ |
| 86 | if (ctx_ && in_aio_context_home_thread(ctx_)) { \ |
| 87 | while ((cond)) { \ |
| 88 | aio_poll(ctx_, true); \ |
| 89 | waited_ = true; \ |
| 90 | } \ |
| 91 | } else { \ |
| 92 | assert(qemu_get_current_aio_context() == \ |
| 93 | qemu_get_aio_context()); \ |
| 94 | while ((cond)) { \ |
| 95 | aio_poll(qemu_get_aio_context(), true); \ |
| 96 | waited_ = true; \ |
| 97 | } \ |
| 98 | } \ |
| 99 | qatomic_dec(&wait_->num_waiters); \ |
| 100 | waited_; }) |
| 101 | |
| 102 | #define AIO_WAIT_WHILE(ctx, cond) \ |
| 103 | AIO_WAIT_WHILE_INTERNAL(ctx, cond) |
| 104 | |
| 105 | /* TODO replace this with AIO_WAIT_WHILE() in a future patch */ |
| 106 | #define AIO_WAIT_WHILE_UNLOCKED(ctx, cond) \ |
| 107 | AIO_WAIT_WHILE_INTERNAL(ctx, cond) |
| 108 | |
| 109 | /** |
| 110 | * aio_wait_kick: |
| 111 | * Wake up the main thread if it is waiting on AIO_WAIT_WHILE(). During |
| 112 | * synchronous operations performed in an IOThread, the main thread lets the |
| 113 | * IOThread's event loop run, waiting for the operation to complete. A |
| 114 | * aio_wait_kick() call will wake up the main thread. |
| 115 | */ |
| 116 | void aio_wait_kick(void); |
| 117 | |
| 118 | /** |
| 119 | * aio_wait_bh_oneshot: |
| 120 | * @ctx: the aio context |
| 121 | * @cb: the BH callback function |
| 122 | * @opaque: user data for the BH callback function |
| 123 | * |
| 124 | * Run a BH in @ctx and wait for it to complete. |
| 125 | * |
| 126 | * Must be called from the main loop thread without @ctx acquired. |
| 127 | * Note that main loop event processing may occur. |
| 128 | */ |
| 129 | void aio_wait_bh_oneshot(AioContext *ctx, QEMUBHFunc *cb, void *opaque); |
| 130 | |
| 131 | /** |
| 132 | * in_aio_context_home_thread: |
| 133 | * @ctx: the aio context |
| 134 | * |
| 135 | * Return whether we are running in the thread that normally runs @ctx. Note |
| 136 | * that acquiring/releasing ctx does not affect the outcome, each AioContext |
| 137 | * still only has one home thread that is responsible for running it. |
| 138 | */ |
| 139 | static inline bool in_aio_context_home_thread(AioContext *ctx) |
| 140 | { |
| 141 | if (ctx == qemu_get_current_aio_context()) { |
| 142 | return true; |
| 143 | } |
| 144 | |
| 145 | if (ctx == qemu_get_aio_context()) { |
| 146 | return bql_locked(); |
| 147 | } else { |
| 148 | return false; |
| 149 | } |
| 150 | } |
| 151 | |
| 152 | #endif /* QEMU_AIO_WAIT_H */ |