1 /* 2 * Polymorphic locking functions (aka poor man templates) 3 * 4 * Copyright Red Hat, Inc. 2017, 2018 5 * 6 * Author: Paolo Bonzini <pbonzini@redhat.com> 7 * 8 * This work is licensed under the terms of the GNU LGPL, version 2 or later. 9 * See the COPYING.LIB file in the top-level directory. 10 * 11 */ 12 13 #ifndef QEMU_LOCKABLE_H 14 #define QEMU_LOCKABLE_H 15 16 #include "qemu/coroutine-core.h" 17 #include "qemu/thread.h" 18 19 typedef void QemuLockUnlockFunc(void *); 20 21 typedef struct QemuLockable { 22 void *object; 23 QemuLockUnlockFunc *lock; 24 QemuLockUnlockFunc *unlock; 25 } QemuLockable; 26 27 static inline __attribute__((__always_inline__)) QemuLockable * 28 qemu_make_lockable(void *x, QemuLockable *lockable) 29 { 30 /* 31 * We cannot test this in a macro, otherwise we get compiler 32 * warnings like "the address of 'm' will always evaluate as 'true'". 33 */ 34 return x ? lockable : NULL; 35 } 36 37 static inline __attribute__((__always_inline__)) QemuLockable * 38 qemu_null_lockable(void *x) 39 { 40 if (x != NULL) { 41 qemu_build_not_reached(); 42 } 43 return NULL; 44 } 45 46 #define QML_FUNC_(name) \ 47 static inline void qemu_lockable_ ## name ## _lock(void *x) \ 48 { \ 49 qemu_ ## name ## _lock(x); \ 50 } \ 51 static inline void qemu_lockable_ ## name ## _unlock(void *x) \ 52 { \ 53 qemu_ ## name ## _unlock(x); \ 54 } 55 56 QML_FUNC_(mutex) 57 QML_FUNC_(rec_mutex) 58 QML_FUNC_(co_mutex) 59 QML_FUNC_(spin) 60 61 /* 62 * In C, compound literals have the lifetime of an automatic variable. 63 * In C++ it would be different, but then C++ wouldn't need QemuLockable 64 * either... 65 */ 66 #define QML_OBJ_(x, name) (&(QemuLockable) { \ 67 .object = (x), \ 68 .lock = qemu_lockable_ ## name ## _lock, \ 69 .unlock = qemu_lockable_ ## name ## _unlock \ 70 }) 71 72 /** 73 * QEMU_MAKE_LOCKABLE - Make a polymorphic QemuLockable 74 * 75 * @x: a lock object (currently one of QemuMutex, QemuRecMutex, 76 * CoMutex, QemuSpin). 77 * 78 * Returns a QemuLockable object that can be passed around 79 * to a function that can operate with locks of any kind, or 80 * NULL if @x is %NULL. 81 * 82 * Note the special case for void *, so that we may pass "NULL". 83 */ 84 #define QEMU_MAKE_LOCKABLE(x) \ 85 _Generic((x), QemuLockable *: (x), \ 86 void *: qemu_null_lockable(x), \ 87 QemuMutex *: qemu_make_lockable(x, QML_OBJ_(x, mutex)), \ 88 QemuRecMutex *: qemu_make_lockable(x, QML_OBJ_(x, rec_mutex)), \ 89 CoMutex *: qemu_make_lockable(x, QML_OBJ_(x, co_mutex)), \ 90 QemuSpin *: qemu_make_lockable(x, QML_OBJ_(x, spin))) 91 92 /** 93 * QEMU_MAKE_LOCKABLE_NONNULL - Make a polymorphic QemuLockable 94 * 95 * @x: a lock object (currently one of QemuMutex, QemuRecMutex, 96 * CoMutex, QemuSpin). 97 * 98 * Returns a QemuLockable object that can be passed around 99 * to a function that can operate with locks of any kind. 100 */ 101 #define QEMU_MAKE_LOCKABLE_NONNULL(x) \ 102 _Generic((x), QemuLockable *: (x), \ 103 QemuMutex *: QML_OBJ_(x, mutex), \ 104 QemuRecMutex *: QML_OBJ_(x, rec_mutex), \ 105 CoMutex *: QML_OBJ_(x, co_mutex), \ 106 QemuSpin *: QML_OBJ_(x, spin)) 107 108 static inline void qemu_lockable_lock(QemuLockable *x) 109 { 110 x->lock(x->object); 111 } 112 113 static inline void qemu_lockable_unlock(QemuLockable *x) 114 { 115 x->unlock(x->object); 116 } 117 118 static inline QemuLockable *qemu_lockable_auto_lock(QemuLockable *x) 119 { 120 qemu_lockable_lock(x); 121 return x; 122 } 123 124 static inline void qemu_lockable_auto_unlock(QemuLockable *x) 125 { 126 if (x) { 127 qemu_lockable_unlock(x); 128 } 129 } 130 131 G_DEFINE_AUTOPTR_CLEANUP_FUNC(QemuLockable, qemu_lockable_auto_unlock) 132 133 #define WITH_QEMU_LOCK_GUARD_(x, var) \ 134 for (g_autoptr(QemuLockable) var = \ 135 qemu_lockable_auto_lock(QEMU_MAKE_LOCKABLE_NONNULL((x))); \ 136 var; \ 137 qemu_lockable_auto_unlock(var), var = NULL) 138 139 /** 140 * WITH_QEMU_LOCK_GUARD - Lock a lock object for scope 141 * 142 * @x: a lock object (currently one of QemuMutex, CoMutex, QemuSpin). 143 * 144 * This macro defines a lock scope such that entering the scope takes the lock 145 * and leaving the scope releases the lock. Return statements are allowed 146 * within the scope and release the lock. Break and continue statements leave 147 * the scope early and release the lock. 148 * 149 * WITH_QEMU_LOCK_GUARD(&mutex) { 150 * ... 151 * if (error) { 152 * return; <-- mutex is automatically unlocked 153 * } 154 * 155 * if (early_exit) { 156 * break; <-- leave this scope early 157 * } 158 * ... 159 * } 160 */ 161 #define WITH_QEMU_LOCK_GUARD(x) \ 162 WITH_QEMU_LOCK_GUARD_((x), glue(qemu_lockable_auto, __COUNTER__)) 163 164 /** 165 * QEMU_LOCK_GUARD - Lock an object until the end of the scope 166 * 167 * @x: a lock object (currently one of QemuMutex, CoMutex, QemuSpin). 168 * 169 * This macro takes a lock until the end of the scope. Return statements 170 * release the lock. 171 * 172 * ... <-- mutex not locked 173 * QEMU_LOCK_GUARD(&mutex); <-- mutex locked from here onwards 174 * ... 175 * if (error) { 176 * return; <-- mutex is automatically unlocked 177 * } 178 */ 179 #define QEMU_LOCK_GUARD(x) \ 180 g_autoptr(QemuLockable) \ 181 glue(qemu_lockable_auto, __COUNTER__) G_GNUC_UNUSED = \ 182 qemu_lockable_auto_lock(QEMU_MAKE_LOCKABLE((x))) 183 184 #endif 185