2 * Polymorphic locking functions (aka poor man templates)
4 * Copyright Red Hat, Inc. 2017, 2018
6 * Author: Paolo Bonzini <pbonzini@redhat.com>
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.
13 #ifndef QEMU_LOCKABLE_H
14 #define QEMU_LOCKABLE_H
16 #include "qemu/coroutine.h"
17 #include "qemu/thread.h"
19 typedef void QemuLockUnlockFunc(void *);
23 QemuLockUnlockFunc
*lock
;
24 QemuLockUnlockFunc
*unlock
;
27 /* This function gives an error if an invalid, non-NULL pointer type is passed
28 * to QEMU_MAKE_LOCKABLE. For optimized builds, we can rely on dead-code elimination
29 * from the compiler, and give the errors already at link time.
31 #if defined(__OPTIMIZE__) && !defined(__SANITIZE_ADDRESS__)
32 void unknown_lock_type(void *);
34 static inline void unknown_lock_type(void *unused
)
40 static inline __attribute__((__always_inline__
)) QemuLockable
*
41 qemu_make_lockable(void *x
, QemuLockable
*lockable
)
43 /* We cannot test this in a macro, otherwise we get compiler
44 * warnings like "the address of 'm' will always evaluate as 'true'".
46 return x
? lockable
: NULL
;
49 /* Auxiliary macros to simplify QEMU_MAKE_LOCABLE. */
50 #define QEMU_LOCK_FUNC(x) ((QemuLockUnlockFunc *) \
52 (QemuMutex *, qemu_mutex_lock), \
53 (CoMutex *, qemu_co_mutex_lock), \
54 (QemuSpin *, qemu_spin_lock), \
57 #define QEMU_UNLOCK_FUNC(x) ((QemuLockUnlockFunc *) \
59 (QemuMutex *, qemu_mutex_unlock), \
60 (CoMutex *, qemu_co_mutex_unlock), \
61 (QemuSpin *, qemu_spin_unlock), \
64 /* In C, compound literals have the lifetime of an automatic variable.
65 * In C++ it would be different, but then C++ wouldn't need QemuLockable
68 #define QEMU_MAKE_LOCKABLE_(x) qemu_make_lockable((x), &(QemuLockable) { \
70 .lock = QEMU_LOCK_FUNC(x), \
71 .unlock = QEMU_UNLOCK_FUNC(x), \
74 /* QEMU_MAKE_LOCKABLE - Make a polymorphic QemuLockable
76 * @x: a lock object (currently one of QemuMutex, CoMutex, QemuSpin).
78 * Returns a QemuLockable object that can be passed around
79 * to a function that can operate with locks of any kind.
81 #define QEMU_MAKE_LOCKABLE(x) \
83 (QemuLockable *, (x)), \
84 QEMU_MAKE_LOCKABLE_(x))
86 static inline void qemu_lockable_lock(QemuLockable
*x
)
91 static inline void qemu_lockable_unlock(QemuLockable
*x
)