1
2
3
4
5
6
7
8
9
10
11
12
13#ifndef QEMU_LOCKABLE_H
14#define QEMU_LOCKABLE_H
15
16#include "qemu/coroutine.h"
17#include "qemu/thread.h"
18
19typedef void QemuLockUnlockFunc(void *);
20
21struct QemuLockable {
22 void *object;
23 QemuLockUnlockFunc *lock;
24 QemuLockUnlockFunc *unlock;
25};
26
27
28
29
30
31#if defined(__OPTIMIZE__) && !defined(__SANITIZE_ADDRESS__)
32void unknown_lock_type(void *);
33#else
34static inline void unknown_lock_type(void *unused)
35{
36 abort();
37}
38#endif
39
40static inline __attribute__((__always_inline__)) QemuLockable *
41qemu_make_lockable(void *x, QemuLockable *lockable)
42{
43
44
45
46 return x ? lockable : NULL;
47}
48
49
50#define QEMU_LOCK_FUNC(x) ((QemuLockUnlockFunc *) \
51 QEMU_GENERIC(x, \
52 (QemuMutex *, qemu_mutex_lock), \
53 (CoMutex *, qemu_co_mutex_lock), \
54 (QemuSpin *, qemu_spin_lock), \
55 unknown_lock_type))
56
57#define QEMU_UNLOCK_FUNC(x) ((QemuLockUnlockFunc *) \
58 QEMU_GENERIC(x, \
59 (QemuMutex *, qemu_mutex_unlock), \
60 (CoMutex *, qemu_co_mutex_unlock), \
61 (QemuSpin *, qemu_spin_unlock), \
62 unknown_lock_type))
63
64
65
66
67
68#define QEMU_MAKE_LOCKABLE_(x) qemu_make_lockable((x), &(QemuLockable) { \
69 .object = (x), \
70 .lock = QEMU_LOCK_FUNC(x), \
71 .unlock = QEMU_UNLOCK_FUNC(x), \
72 })
73
74
75
76
77
78
79
80
81#define QEMU_MAKE_LOCKABLE(x) \
82 QEMU_GENERIC(x, \
83 (QemuLockable *, (x)), \
84 QEMU_MAKE_LOCKABLE_(x))
85
86static inline void qemu_lockable_lock(QemuLockable *x)
87{
88 x->lock(x->object);
89}
90
91static inline void qemu_lockable_unlock(QemuLockable *x)
92{
93 x->unlock(x->object);
94}
95
96#endif
97