|
@@ -24,79 +24,71 @@ struct QemuLockable {
|
|
QemuLockUnlockFunc *unlock;
|
|
QemuLockUnlockFunc *unlock;
|
|
};
|
|
};
|
|
|
|
|
|
-/* This function gives an error if an invalid, non-NULL pointer type is passed
|
|
|
|
- * to QEMU_MAKE_LOCKABLE. For optimized builds, we can rely on dead-code elimination
|
|
|
|
- * from the compiler, and give the errors already at link time.
|
|
|
|
- */
|
|
|
|
-#if defined(__OPTIMIZE__) && !defined(__SANITIZE_ADDRESS__)
|
|
|
|
-void unknown_lock_type(void *);
|
|
|
|
-#else
|
|
|
|
-static inline void unknown_lock_type(void *unused)
|
|
|
|
-{
|
|
|
|
- abort();
|
|
|
|
-}
|
|
|
|
-#endif
|
|
|
|
-
|
|
|
|
static inline __attribute__((__always_inline__)) QemuLockable *
|
|
static inline __attribute__((__always_inline__)) QemuLockable *
|
|
qemu_make_lockable(void *x, QemuLockable *lockable)
|
|
qemu_make_lockable(void *x, QemuLockable *lockable)
|
|
{
|
|
{
|
|
- /* We cannot test this in a macro, otherwise we get compiler
|
|
|
|
|
|
+ /*
|
|
|
|
+ * We cannot test this in a macro, otherwise we get compiler
|
|
* warnings like "the address of 'm' will always evaluate as 'true'".
|
|
* warnings like "the address of 'm' will always evaluate as 'true'".
|
|
*/
|
|
*/
|
|
return x ? lockable : NULL;
|
|
return x ? lockable : NULL;
|
|
}
|
|
}
|
|
|
|
|
|
-/* Auxiliary macros to simplify QEMU_MAKE_LOCABLE. */
|
|
|
|
-#define QEMU_LOCK_FUNC(x) ((QemuLockUnlockFunc *) \
|
|
|
|
- QEMU_GENERIC(x, \
|
|
|
|
- (QemuMutex *, qemu_mutex_lock), \
|
|
|
|
- (QemuRecMutex *, qemu_rec_mutex_lock), \
|
|
|
|
- (CoMutex *, qemu_co_mutex_lock), \
|
|
|
|
- (QemuSpin *, qemu_spin_lock), \
|
|
|
|
- unknown_lock_type))
|
|
|
|
-
|
|
|
|
-#define QEMU_UNLOCK_FUNC(x) ((QemuLockUnlockFunc *) \
|
|
|
|
- QEMU_GENERIC(x, \
|
|
|
|
- (QemuMutex *, qemu_mutex_unlock), \
|
|
|
|
- (QemuRecMutex *, qemu_rec_mutex_unlock), \
|
|
|
|
- (CoMutex *, qemu_co_mutex_unlock), \
|
|
|
|
- (QemuSpin *, qemu_spin_unlock), \
|
|
|
|
- unknown_lock_type))
|
|
|
|
-
|
|
|
|
-/* In C, compound literals have the lifetime of an automatic variable.
|
|
|
|
|
|
+static inline __attribute__((__always_inline__)) QemuLockable *
|
|
|
|
+qemu_null_lockable(void *x)
|
|
|
|
+{
|
|
|
|
+ if (x != NULL) {
|
|
|
|
+ qemu_build_not_reached();
|
|
|
|
+ }
|
|
|
|
+ return NULL;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * In C, compound literals have the lifetime of an automatic variable.
|
|
* In C++ it would be different, but then C++ wouldn't need QemuLockable
|
|
* In C++ it would be different, but then C++ wouldn't need QemuLockable
|
|
* either...
|
|
* either...
|
|
*/
|
|
*/
|
|
-#define QEMU_MAKE_LOCKABLE_(x) (&(QemuLockable) { \
|
|
|
|
- .object = (x), \
|
|
|
|
- .lock = QEMU_LOCK_FUNC(x), \
|
|
|
|
- .unlock = QEMU_UNLOCK_FUNC(x), \
|
|
|
|
|
|
+#define QML_OBJ_(x, name) (&(QemuLockable) { \
|
|
|
|
+ .object = (x), \
|
|
|
|
+ .lock = (QemuLockUnlockFunc *) qemu_ ## name ## _lock, \
|
|
|
|
+ .unlock = (QemuLockUnlockFunc *) qemu_ ## name ## _unlock \
|
|
})
|
|
})
|
|
|
|
|
|
-/* QEMU_MAKE_LOCKABLE - Make a polymorphic QemuLockable
|
|
|
|
|
|
+/**
|
|
|
|
+ * QEMU_MAKE_LOCKABLE - Make a polymorphic QemuLockable
|
|
*
|
|
*
|
|
- * @x: a lock object (currently one of QemuMutex, QemuRecMutex, CoMutex, QemuSpin).
|
|
|
|
|
|
+ * @x: a lock object (currently one of QemuMutex, QemuRecMutex,
|
|
|
|
+ * CoMutex, QemuSpin).
|
|
*
|
|
*
|
|
* Returns a QemuLockable object that can be passed around
|
|
* Returns a QemuLockable object that can be passed around
|
|
* to a function that can operate with locks of any kind, or
|
|
* to a function that can operate with locks of any kind, or
|
|
* NULL if @x is %NULL.
|
|
* NULL if @x is %NULL.
|
|
|
|
+ *
|
|
|
|
+ * Note the special case for void *, so that we may pass "NULL".
|
|
*/
|
|
*/
|
|
-#define QEMU_MAKE_LOCKABLE(x) \
|
|
|
|
- QEMU_GENERIC(x, \
|
|
|
|
- (QemuLockable *, (x)), \
|
|
|
|
- qemu_make_lockable((x), QEMU_MAKE_LOCKABLE_(x)))
|
|
|
|
|
|
+#define QEMU_MAKE_LOCKABLE(x) \
|
|
|
|
+ _Generic((x), QemuLockable *: (x), \
|
|
|
|
+ void *: qemu_null_lockable(x), \
|
|
|
|
+ QemuMutex *: qemu_make_lockable(x, QML_OBJ_(x, mutex)), \
|
|
|
|
+ QemuRecMutex *: qemu_make_lockable(x, QML_OBJ_(x, rec_mutex)), \
|
|
|
|
+ CoMutex *: qemu_make_lockable(x, QML_OBJ_(x, co_mutex)), \
|
|
|
|
+ QemuSpin *: qemu_make_lockable(x, QML_OBJ_(x, spin)))
|
|
|
|
|
|
-/* QEMU_MAKE_LOCKABLE_NONNULL - Make a polymorphic QemuLockable
|
|
|
|
|
|
+/**
|
|
|
|
+ * QEMU_MAKE_LOCKABLE_NONNULL - Make a polymorphic QemuLockable
|
|
*
|
|
*
|
|
- * @x: a lock object (currently one of QemuMutex, QemuRecMutex, CoMutex, QemuSpin).
|
|
|
|
|
|
+ * @x: a lock object (currently one of QemuMutex, QemuRecMutex,
|
|
|
|
+ * CoMutex, QemuSpin).
|
|
*
|
|
*
|
|
* Returns a QemuLockable object that can be passed around
|
|
* Returns a QemuLockable object that can be passed around
|
|
* to a function that can operate with locks of any kind.
|
|
* to a function that can operate with locks of any kind.
|
|
*/
|
|
*/
|
|
-#define QEMU_MAKE_LOCKABLE_NONNULL(x) \
|
|
|
|
- QEMU_GENERIC(x, \
|
|
|
|
- (QemuLockable *, (x)), \
|
|
|
|
- QEMU_MAKE_LOCKABLE_(x))
|
|
|
|
|
|
+#define QEMU_MAKE_LOCKABLE_NONNULL(x) \
|
|
|
|
+ _Generic((x), QemuLockable *: (x), \
|
|
|
|
+ QemuMutex *: QML_OBJ_(x, mutex), \
|
|
|
|
+ QemuRecMutex *: QML_OBJ_(x, rec_mutex), \
|
|
|
|
+ CoMutex *: QML_OBJ_(x, co_mutex), \
|
|
|
|
+ QemuSpin *: QML_OBJ_(x, spin))
|
|
|
|
|
|
static inline void qemu_lockable_lock(QemuLockable *x)
|
|
static inline void qemu_lockable_lock(QemuLockable *x)
|
|
{
|
|
{
|