]>
Commit | Line | Data |
---|---|---|
d63c9477 AL |
1 | /* |
2 | * GLIB Compatibility Functions | |
3 | * | |
4 | * Copyright IBM, Corp. 2013 | |
5 | * | |
6 | * Authors: | |
7 | * Anthony Liguori <[email protected]> | |
86946a2d MT |
8 | * Michael Tokarev <[email protected]> |
9 | * Paolo Bonzini <[email protected]> | |
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 SH |
34 | #if !GLIB_CHECK_VERSION(2, 28, 0) |
35 | static inline gint64 g_get_monotonic_time(void) | |
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 | } | |
46 | #endif | |
47 | ||
5f77ef69 GA |
48 | #if !GLIB_CHECK_VERSION(2, 16, 0) |
49 | static inline int g_strcmp0(const char *str1, const char *str2) | |
50 | { | |
51 | int result; | |
52 | ||
53 | if (!str1) { | |
54 | result = -(str1 != str2); | |
55 | } else if (!str2) { | |
56 | result = (str1 != str2); | |
57 | } else { | |
58 | result = strcmp(str1, str2); | |
59 | } | |
60 | ||
61 | return result; | |
62 | } | |
63 | #endif | |
64 | ||
5a007547 SP |
65 | #ifdef _WIN32 |
66 | /* | |
67 | * g_poll has a problem on Windows when using | |
68 | * timeouts < 10ms, so use wrapper. | |
69 | */ | |
70 | #define g_poll(fds, nfds, timeout) g_poll_fixed(fds, nfds, timeout) | |
71 | gint g_poll_fixed(GPollFD *fds, guint nfds, gint timeout); | |
72 | #elif !GLIB_CHECK_VERSION(2, 20, 0) | |
f95c967a SH |
73 | /* |
74 | * Glib before 2.20.0 doesn't implement g_poll, so wrap it to compile properly | |
75 | * on older systems. | |
76 | */ | |
77 | static inline gint g_poll(GPollFD *fds, guint nfds, gint timeout) | |
78 | { | |
79 | GMainContext *ctx = g_main_context_default(); | |
80 | return g_main_context_get_poll_func(ctx)(fds, nfds, timeout); | |
81 | } | |
82 | #endif | |
83 | ||
86946a2d MT |
84 | #if !GLIB_CHECK_VERSION(2, 31, 0) |
85 | /* before glib-2.31, GMutex and GCond was dynamic-only (there was a separate | |
86 | * GStaticMutex, but it didn't work with condition variables). | |
87 | * | |
88 | * Our implementation uses GOnce to fake a static implementation that does | |
89 | * not require separate initialization. | |
90 | * We need to rename the types to avoid passing our CompatGMutex/CompatGCond | |
91 | * by mistake to a function that expects GMutex/GCond. However, for ease | |
92 | * of use we keep the GLib function names. GLib uses macros for the | |
93 | * implementation, we use inline functions instead and undefine the macros. | |
94 | */ | |
95 | ||
96 | typedef struct CompatGMutex { | |
97 | GOnce once; | |
98 | } CompatGMutex; | |
99 | ||
100 | typedef struct CompatGCond { | |
101 | GOnce once; | |
102 | } CompatGCond; | |
103 | ||
104 | static inline gpointer do_g_mutex_new(gpointer unused) | |
105 | { | |
106 | return (gpointer) g_mutex_new(); | |
107 | } | |
108 | ||
109 | static inline void g_mutex_init(CompatGMutex *mutex) | |
110 | { | |
111 | mutex->once = (GOnce) G_ONCE_INIT; | |
112 | } | |
113 | ||
114 | static inline void g_mutex_clear(CompatGMutex *mutex) | |
115 | { | |
116 | assert(mutex->once.status != G_ONCE_STATUS_PROGRESS); | |
117 | if (mutex->once.retval) { | |
118 | g_mutex_free((GMutex *) mutex->once.retval); | |
119 | } | |
120 | mutex->once = (GOnce) G_ONCE_INIT; | |
121 | } | |
122 | ||
123 | static inline void (g_mutex_lock)(CompatGMutex *mutex) | |
124 | { | |
125 | g_once(&mutex->once, do_g_mutex_new, NULL); | |
126 | g_mutex_lock((GMutex *) mutex->once.retval); | |
127 | } | |
128 | #undef g_mutex_lock | |
129 | ||
130 | static inline gboolean (g_mutex_trylock)(CompatGMutex *mutex) | |
131 | { | |
132 | g_once(&mutex->once, do_g_mutex_new, NULL); | |
133 | return g_mutex_trylock((GMutex *) mutex->once.retval); | |
134 | } | |
135 | #undef g_mutex_trylock | |
136 | ||
137 | ||
138 | static inline void (g_mutex_unlock)(CompatGMutex *mutex) | |
139 | { | |
140 | g_mutex_unlock((GMutex *) mutex->once.retval); | |
141 | } | |
142 | #undef g_mutex_unlock | |
143 | ||
144 | static inline gpointer do_g_cond_new(gpointer unused) | |
145 | { | |
146 | return (gpointer) g_cond_new(); | |
147 | } | |
148 | ||
149 | static inline void g_cond_init(CompatGCond *cond) | |
150 | { | |
151 | cond->once = (GOnce) G_ONCE_INIT; | |
152 | } | |
153 | ||
154 | static inline void g_cond_clear(CompatGCond *cond) | |
155 | { | |
156 | assert(cond->once.status != G_ONCE_STATUS_PROGRESS); | |
157 | if (cond->once.retval) { | |
158 | g_cond_free((GCond *) cond->once.retval); | |
159 | } | |
160 | cond->once = (GOnce) G_ONCE_INIT; | |
161 | } | |
162 | ||
163 | static inline void (g_cond_wait)(CompatGCond *cond, CompatGMutex *mutex) | |
164 | { | |
165 | assert(mutex->once.status != G_ONCE_STATUS_PROGRESS); | |
166 | g_once(&cond->once, do_g_cond_new, NULL); | |
167 | g_cond_wait((GCond *) cond->once.retval, (GMutex *) mutex->once.retval); | |
168 | } | |
169 | #undef g_cond_wait | |
170 | ||
171 | static inline void (g_cond_broadcast)(CompatGCond *cond) | |
172 | { | |
173 | g_once(&cond->once, do_g_cond_new, NULL); | |
174 | g_cond_broadcast((GCond *) cond->once.retval); | |
175 | } | |
176 | #undef g_cond_broadcast | |
177 | ||
178 | static inline void (g_cond_signal)(CompatGCond *cond) | |
179 | { | |
180 | g_once(&cond->once, do_g_cond_new, NULL); | |
181 | g_cond_signal((GCond *) cond->once.retval); | |
182 | } | |
183 | #undef g_cond_signal | |
184 | ||
185 | ||
186 | /* before 2.31 there was no g_thread_new() */ | |
187 | static inline GThread *g_thread_new(const char *name, | |
188 | GThreadFunc func, gpointer data) | |
189 | { | |
190 | GThread *thread = g_thread_create(func, data, TRUE, NULL); | |
191 | if (!thread) { | |
192 | g_error("creating thread"); | |
193 | } | |
194 | return thread; | |
195 | } | |
196 | #else | |
197 | #define CompatGMutex GMutex | |
198 | #define CompatGCond GCond | |
199 | #endif /* glib 2.31 */ | |
200 | ||
d63c9477 | 201 | #endif |