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 (QemuRecMutex *, qemu_rec_mutex_lock), \
54 (CoMutex *, qemu_co_mutex_lock), \
55 (QemuSpin *, qemu_spin_lock), \
56 unknown_lock_type))
57
58#define QEMU_UNLOCK_FUNC(x) ((QemuLockUnlockFunc *) \
59 QEMU_GENERIC(x, \
60 (QemuMutex *, qemu_mutex_unlock), \
61 (QemuRecMutex *, qemu_rec_mutex_unlock), \
62 (CoMutex *, qemu_co_mutex_unlock), \
63 (QemuSpin *, qemu_spin_unlock), \
64 unknown_lock_type))
65
66
67
68
69
70#define QEMU_MAKE_LOCKABLE_(x) (&(QemuLockable) { \
71 .object = (x), \
72 .lock = QEMU_LOCK_FUNC(x), \
73 .unlock = QEMU_UNLOCK_FUNC(x), \
74 })
75
76
77
78
79
80
81
82
83
84#define QEMU_MAKE_LOCKABLE(x) \
85 QEMU_GENERIC(x, \
86 (QemuLockable *, (x)), \
87 qemu_make_lockable((x), QEMU_MAKE_LOCKABLE_(x)))
88
89
90
91
92
93
94
95
96#define QEMU_MAKE_LOCKABLE_NONNULL(x) \
97 QEMU_GENERIC(x, \
98 (QemuLockable *, (x)), \
99 QEMU_MAKE_LOCKABLE_(x))
100
101static inline void qemu_lockable_lock(QemuLockable *x)
102{
103 x->lock(x->object);
104}
105
106static inline void qemu_lockable_unlock(QemuLockable *x)
107{
108 x->unlock(x->object);
109}
110
111static inline QemuLockable *qemu_lockable_auto_lock(QemuLockable *x)
112{
113 qemu_lockable_lock(x);
114 return x;
115}
116
117static inline void qemu_lockable_auto_unlock(QemuLockable *x)
118{
119 if (x) {
120 qemu_lockable_unlock(x);
121 }
122}
123
124G_DEFINE_AUTOPTR_CLEANUP_FUNC(QemuLockable, qemu_lockable_auto_unlock)
125
126#define WITH_QEMU_LOCK_GUARD_(x, var) \
127 for (g_autoptr(QemuLockable) var = \
128 qemu_lockable_auto_lock(QEMU_MAKE_LOCKABLE_NONNULL((x))); \
129 var; \
130 qemu_lockable_auto_unlock(var), var = NULL)
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154#define WITH_QEMU_LOCK_GUARD(x) \
155 WITH_QEMU_LOCK_GUARD_((x), glue(qemu_lockable_auto, __COUNTER__))
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172#define QEMU_LOCK_GUARD(x) \
173 g_autoptr(QemuLockable) \
174 glue(qemu_lockable_auto, __COUNTER__) G_GNUC_UNUSED = \
175 qemu_lockable_auto_lock(QEMU_MAKE_LOCKABLE((x)))
176
177#endif
178