]>
Commit | Line | Data |
---|---|---|
d63c9477 AL |
1 | /* |
2 | * GLIB Compatibility Functions | |
3 | * | |
4 | * Copyright IBM, Corp. 2013 | |
5 | * | |
6 | * Authors: | |
7 | * Anthony Liguori <aliguori@us.ibm.com> | |
86946a2d MT |
8 | * Michael Tokarev <mjt@tls.msk.ru> |
9 | * Paolo Bonzini <pbonzini@redhat.com> | |
d63c9477 AL |
10 | * |
11 | * This work is licensed under the terms of the GNU GPL, version 2 or later. | |
12 | * See the COPYING file in the top-level directory. | |
13 | * | |
14 | */ | |
15 | ||
16 | #ifndef QEMU_GLIB_COMPAT_H | |
17 | #define QEMU_GLIB_COMPAT_H | |
18 | ||
19 | #include <glib.h> | |
20 | ||
89b516d8 SH |
21 | /* GLIB version compatibility flags */ |
22 | #if !GLIB_CHECK_VERSION(2, 26, 0) | |
23 | #define G_TIME_SPAN_SECOND (G_GINT64_CONSTANT(1000000)) | |
24 | #endif | |
25 | ||
d63c9477 AL |
26 | #if !GLIB_CHECK_VERSION(2, 14, 0) |
27 | static inline guint g_timeout_add_seconds(guint interval, GSourceFunc function, | |
28 | gpointer data) | |
29 | { | |
30 | return g_timeout_add(interval * 1000, function, data); | |
31 | } | |
32 | #endif | |
33 | ||
89b516d8 | 34 | #if !GLIB_CHECK_VERSION(2, 28, 0) |
14655e9a | 35 | static inline gint64 qemu_g_get_monotonic_time(void) |
89b516d8 SH |
36 | { |
37 | /* g_get_monotonic_time() is best-effort so we can use the wall clock as a | |
38 | * fallback. | |
39 | */ | |
40 | ||
41 | GTimeVal time; | |
42 | g_get_current_time(&time); | |
43 | ||
44 | return time.tv_sec * G_TIME_SPAN_SECOND + time.tv_usec; | |
45 | } | |
14655e9a CH |
46 | /* work around distro backports of this interface */ |
47 | #define g_get_monotonic_time() qemu_g_get_monotonic_time() | |
89b516d8 SH |
48 | #endif |
49 | ||
5f77ef69 GA |
50 | #if !GLIB_CHECK_VERSION(2, 16, 0) |
51 | static inline int g_strcmp0(const char *str1, const char *str2) | |
52 | { | |
53 | int result; | |
54 | ||
55 | if (!str1) { | |
56 | result = -(str1 != str2); | |
57 | } else if (!str2) { | |
58 | result = (str1 != str2); | |
59 | } else { | |
60 | result = strcmp(str1, str2); | |
61 | } | |
62 | ||
63 | return result; | |
64 | } | |
65 | #endif | |
66 | ||
5a007547 SP |
67 | #ifdef _WIN32 |
68 | /* | |
69 | * g_poll has a problem on Windows when using | |
70 | * timeouts < 10ms, so use wrapper. | |
71 | */ | |
72 | #define g_poll(fds, nfds, timeout) g_poll_fixed(fds, nfds, timeout) | |
73 | gint g_poll_fixed(GPollFD *fds, guint nfds, gint timeout); | |
74 | #elif !GLIB_CHECK_VERSION(2, 20, 0) | |
f95c967a SH |
75 | /* |
76 | * Glib before 2.20.0 doesn't implement g_poll, so wrap it to compile properly | |
77 | * on older systems. | |
78 | */ | |
79 | static inline gint g_poll(GPollFD *fds, guint nfds, gint timeout) | |
80 | { | |
81 | GMainContext *ctx = g_main_context_default(); | |
82 | return g_main_context_get_poll_func(ctx)(fds, nfds, timeout); | |
83 | } | |
84 | #endif | |
85 | ||
86946a2d MT |
86 | #if !GLIB_CHECK_VERSION(2, 31, 0) |
87 | /* before glib-2.31, GMutex and GCond was dynamic-only (there was a separate | |
88 | * GStaticMutex, but it didn't work with condition variables). | |
89 | * | |
90 | * Our implementation uses GOnce to fake a static implementation that does | |
91 | * not require separate initialization. | |
92 | * We need to rename the types to avoid passing our CompatGMutex/CompatGCond | |
93 | * by mistake to a function that expects GMutex/GCond. However, for ease | |
94 | * of use we keep the GLib function names. GLib uses macros for the | |
95 | * implementation, we use inline functions instead and undefine the macros. | |
96 | */ | |
97 | ||
98 | typedef struct CompatGMutex { | |
99 | GOnce once; | |
100 | } CompatGMutex; | |
101 | ||
102 | typedef struct CompatGCond { | |
103 | GOnce once; | |
104 | } CompatGCond; | |
105 | ||
106 | static inline gpointer do_g_mutex_new(gpointer unused) | |
107 | { | |
108 | return (gpointer) g_mutex_new(); | |
109 | } | |
110 | ||
111 | static inline void g_mutex_init(CompatGMutex *mutex) | |
112 | { | |
113 | mutex->once = (GOnce) G_ONCE_INIT; | |
114 | } | |
115 | ||
116 | static inline void g_mutex_clear(CompatGMutex *mutex) | |
117 | { | |
118 | assert(mutex->once.status != G_ONCE_STATUS_PROGRESS); | |
119 | if (mutex->once.retval) { | |
120 | g_mutex_free((GMutex *) mutex->once.retval); | |
121 | } | |
122 | mutex->once = (GOnce) G_ONCE_INIT; | |
123 | } | |
124 | ||
125 | static inline void (g_mutex_lock)(CompatGMutex *mutex) | |
126 | { | |
127 | g_once(&mutex->once, do_g_mutex_new, NULL); | |
128 | g_mutex_lock((GMutex *) mutex->once.retval); | |
129 | } | |
130 | #undef g_mutex_lock | |
131 | ||
132 | static inline gboolean (g_mutex_trylock)(CompatGMutex *mutex) | |
133 | { | |
134 | g_once(&mutex->once, do_g_mutex_new, NULL); | |
135 | return g_mutex_trylock((GMutex *) mutex->once.retval); | |
136 | } | |
137 | #undef g_mutex_trylock | |
138 | ||
139 | ||
140 | static inline void (g_mutex_unlock)(CompatGMutex *mutex) | |
141 | { | |
142 | g_mutex_unlock((GMutex *) mutex->once.retval); | |
143 | } | |
144 | #undef g_mutex_unlock | |
145 | ||
146 | static inline gpointer do_g_cond_new(gpointer unused) | |
147 | { | |
148 | return (gpointer) g_cond_new(); | |
149 | } | |
150 | ||
151 | static inline void g_cond_init(CompatGCond *cond) | |
152 | { | |
153 | cond->once = (GOnce) G_ONCE_INIT; | |
154 | } | |
155 | ||
156 | static inline void g_cond_clear(CompatGCond *cond) | |
157 | { | |
158 | assert(cond->once.status != G_ONCE_STATUS_PROGRESS); | |
159 | if (cond->once.retval) { | |
160 | g_cond_free((GCond *) cond->once.retval); | |
161 | } | |
162 | cond->once = (GOnce) G_ONCE_INIT; | |
163 | } | |
164 | ||
165 | static inline void (g_cond_wait)(CompatGCond *cond, CompatGMutex *mutex) | |
166 | { | |
167 | assert(mutex->once.status != G_ONCE_STATUS_PROGRESS); | |
168 | g_once(&cond->once, do_g_cond_new, NULL); | |
169 | g_cond_wait((GCond *) cond->once.retval, (GMutex *) mutex->once.retval); | |
170 | } | |
171 | #undef g_cond_wait | |
172 | ||
173 | static inline void (g_cond_broadcast)(CompatGCond *cond) | |
174 | { | |
175 | g_once(&cond->once, do_g_cond_new, NULL); | |
176 | g_cond_broadcast((GCond *) cond->once.retval); | |
177 | } | |
178 | #undef g_cond_broadcast | |
179 | ||
180 | static inline void (g_cond_signal)(CompatGCond *cond) | |
181 | { | |
182 | g_once(&cond->once, do_g_cond_new, NULL); | |
183 | g_cond_signal((GCond *) cond->once.retval); | |
184 | } | |
185 | #undef g_cond_signal | |
186 | ||
187 | ||
188 | /* before 2.31 there was no g_thread_new() */ | |
189 | static inline GThread *g_thread_new(const char *name, | |
190 | GThreadFunc func, gpointer data) | |
191 | { | |
192 | GThread *thread = g_thread_create(func, data, TRUE, NULL); | |
193 | if (!thread) { | |
194 | g_error("creating thread"); | |
195 | } | |
196 | return thread; | |
197 | } | |
198 | #else | |
199 | #define CompatGMutex GMutex | |
200 | #define CompatGCond GCond | |
201 | #endif /* glib 2.31 */ | |
202 | ||
d63c9477 | 203 | #endif |