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
27static inline __attribute__((__always_inline__)) QemuLockable *
28qemu_make_lockable(void *x, QemuLockable *lockable)
29{
30
31
32
33
34 return x ? lockable : NULL;
35}
36
37static inline __attribute__((__always_inline__)) QemuLockable *
38qemu_null_lockable(void *x)
39{
40 if (x != NULL) {
41 qemu_build_not_reached();
42 }
43 return NULL;
44}
45
46
47
48
49
50
51#define QML_OBJ_(x, name) (&(QemuLockable) { \
52 .object = (x), \
53 .lock = (QemuLockUnlockFunc *) qemu_ ## name ## _lock, \
54 .unlock = (QemuLockUnlockFunc *) qemu_ ## name ## _unlock \
55 })
56
57
58
59
60
61
62
63
64
65
66
67
68
69#define QEMU_MAKE_LOCKABLE(x) \
70 _Generic((x), QemuLockable *: (x), \
71 void *: qemu_null_lockable(x), \
72 QemuMutex *: qemu_make_lockable(x, QML_OBJ_(x, mutex)), \
73 QemuRecMutex *: qemu_make_lockable(x, QML_OBJ_(x, rec_mutex)), \
74 CoMutex *: qemu_make_lockable(x, QML_OBJ_(x, co_mutex)), \
75 QemuSpin *: qemu_make_lockable(x, QML_OBJ_(x, spin)))
76
77
78
79
80
81
82
83
84
85
86#define QEMU_MAKE_LOCKABLE_NONNULL(x) \
87 _Generic((x), QemuLockable *: (x), \
88 QemuMutex *: QML_OBJ_(x, mutex), \
89 QemuRecMutex *: QML_OBJ_(x, rec_mutex), \
90 CoMutex *: QML_OBJ_(x, co_mutex), \
91 QemuSpin *: QML_OBJ_(x, spin))
92
93static inline void qemu_lockable_lock(QemuLockable *x)
94{
95 x->lock(x->object);
96}
97
98static inline void qemu_lockable_unlock(QemuLockable *x)
99{
100 x->unlock(x->object);
101}
102
103static inline QemuLockable *qemu_lockable_auto_lock(QemuLockable *x)
104{
105 qemu_lockable_lock(x);
106 return x;
107}
108
109static inline void qemu_lockable_auto_unlock(QemuLockable *x)
110{
111 if (x) {
112 qemu_lockable_unlock(x);
113 }
114}
115
116G_DEFINE_AUTOPTR_CLEANUP_FUNC(QemuLockable, qemu_lockable_auto_unlock)
117
118#define WITH_QEMU_LOCK_GUARD_(x, var) \
119 for (g_autoptr(QemuLockable) var = \
120 qemu_lockable_auto_lock(QEMU_MAKE_LOCKABLE_NONNULL((x))); \
121 var; \
122 qemu_lockable_auto_unlock(var), var = NULL)
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146#define WITH_QEMU_LOCK_GUARD(x) \
147 WITH_QEMU_LOCK_GUARD_((x), glue(qemu_lockable_auto, __COUNTER__))
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164#define QEMU_LOCK_GUARD(x) \
165 g_autoptr(QemuLockable) \
166 glue(qemu_lockable_auto, __COUNTER__) G_GNUC_UNUSED = \
167 qemu_lockable_auto_lock(QEMU_MAKE_LOCKABLE((x)))
168
169#endif
170