diff options
| author | Peter Maydell | 2018-02-08 15:31:51 +0100 |
|---|---|---|
| committer | Peter Maydell | 2018-02-08 15:31:51 +0100 |
| commit | 008a51bbb343972dd8cf09126da8c3b87f4e1c96 (patch) | |
| tree | 6e5f7c697a796ef35198a65623e4dbdc76d3e6da /include/qemu/lockable.h | |
| parent | Merge remote-tracking branch 'remotes/jnsnow/tags/bitmaps-pull-request' into ... (diff) | |
| parent | docs: Add docs/devel/testing.rst (diff) | |
| download | qemu-008a51bbb343972dd8cf09126da8c3b87f4e1c96.tar.gz qemu-008a51bbb343972dd8cf09126da8c3b87f4e1c96.tar.xz qemu-008a51bbb343972dd8cf09126da8c3b87f4e1c96.zip | |
Merge remote-tracking branch 'remotes/famz/tags/staging-pull-request' into staging
# gpg: Signature made Thu 08 Feb 2018 01:29:22 GMT
# gpg: using RSA key CA35624C6A9171C6
# gpg: Good signature from "Fam Zheng <famz@redhat.com>"
# Primary key fingerprint: 5003 7CB7 9706 0F76 F021 AD56 CA35 624C 6A91 71C6
* remotes/famz/tags/staging-pull-request:
docs: Add docs/devel/testing.rst
qapi: Add NVMe driver options to the schema
docs: Add section for NVMe VFIO driver
block: Move NVMe constants to a separate header
qemu-img: Map bench buffer
block/nvme: Implement .bdrv_(un)register_buf
block: Introduce buf register API
block: Add VFIO based NVMe driver
util: Introduce vfio helpers
stubs: Add stubs for ram block API
curl: convert to CoQueue
coroutine-lock: make qemu_co_enter_next thread-safe
coroutine-lock: convert CoQueue to use QemuLockable
lockable: add QemuLockable
test-coroutine: add simple CoMutex test
docker: change Fedora base image to fedora:27
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'include/qemu/lockable.h')
| -rw-r--r-- | include/qemu/lockable.h | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/include/qemu/lockable.h b/include/qemu/lockable.h new file mode 100644 index 0000000000..b6ed6c89ec --- /dev/null +++ b/include/qemu/lockable.h @@ -0,0 +1,96 @@ +/* + * Polymorphic locking functions (aka poor man templates) + * + * Copyright Red Hat, Inc. 2017, 2018 + * + * Author: Paolo Bonzini <pbonzini@redhat.com> + * + * This work is licensed under the terms of the GNU LGPL, version 2 or later. + * See the COPYING.LIB file in the top-level directory. + * + */ + +#ifndef QEMU_LOCKABLE_H +#define QEMU_LOCKABLE_H + +#include "qemu/coroutine.h" +#include "qemu/thread.h" + +typedef void QemuLockUnlockFunc(void *); + +struct QemuLockable { + void *object; + QemuLockUnlockFunc *lock; + 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. + */ +#ifdef __OPTIMIZE__ +void unknown_lock_type(void *); +#else +static inline void unknown_lock_type(void *unused) +{ + abort(); +} +#endif + +static inline __attribute__((__always_inline__)) QemuLockable * +qemu_make_lockable(void *x, QemuLockable *lockable) +{ + /* We cannot test this in a macro, otherwise we get compiler + * warnings like "the address of 'm' will always evaluate as 'true'". + */ + return x ? lockable : NULL; +} + +/* Auxiliary macros to simplify QEMU_MAKE_LOCABLE. */ +#define QEMU_LOCK_FUNC(x) ((QemuLockUnlockFunc *) \ + QEMU_GENERIC(x, \ + (QemuMutex *, qemu_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), \ + (CoMutex *, qemu_co_mutex_unlock), \ + (QemuSpin *, qemu_spin_unlock), \ + unknown_lock_type)) + +/* In C, compound literals have the lifetime of an automatic variable. + * In C++ it would be different, but then C++ wouldn't need QemuLockable + * either... + */ +#define QEMU_MAKE_LOCKABLE_(x) qemu_make_lockable((x), &(QemuLockable) { \ + .object = (x), \ + .lock = QEMU_LOCK_FUNC(x), \ + .unlock = QEMU_UNLOCK_FUNC(x), \ + }) + +/* QEMU_MAKE_LOCKABLE - Make a polymorphic QemuLockable + * + * @x: a lock object (currently one of QemuMutex, CoMutex, QemuSpin). + * + * Returns a QemuLockable object that can be passed around + * to a function that can operate with locks of any kind. + */ +#define QEMU_MAKE_LOCKABLE(x) \ + QEMU_GENERIC(x, \ + (QemuLockable *, (x)), \ + QEMU_MAKE_LOCKABLE_(x)) + +static inline void qemu_lockable_lock(QemuLockable *x) +{ + x->lock(x->object); +} + +static inline void qemu_lockable_unlock(QemuLockable *x) +{ + x->unlock(x->object); +} + +#endif |
