1 /* 2 * GLIB Compatibility Functions 3 * 4 * Copyright IBM, Corp. 2013 5 * 6 * Authors: 7 * Anthony Liguori <aliguori@us.ibm.com> 8 * Michael Tokarev <mjt@tls.msk.ru> 9 * Paolo Bonzini <pbonzini@redhat.com> 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 21 #if !GLIB_CHECK_VERSION(2, 14, 0) 22 static inline guint g_timeout_add_seconds(guint interval, GSourceFunc function, 23 gpointer data) 24 { 25 return g_timeout_add(interval * 1000, function, data); 26 } 27 #endif 28 29 #ifdef _WIN32 30 /* 31 * g_poll has a problem on Windows when using 32 * timeouts < 10ms, so use wrapper. 33 */ 34 #define g_poll(fds, nfds, timeout) g_poll_fixed(fds, nfds, timeout) 35 gint g_poll_fixed(GPollFD *fds, guint nfds, gint timeout); 36 #elif !GLIB_CHECK_VERSION(2, 20, 0) 37 /* 38 * Glib before 2.20.0 doesn't implement g_poll, so wrap it to compile properly 39 * on older systems. 40 */ 41 static inline gint g_poll(GPollFD *fds, guint nfds, gint timeout) 42 { 43 GMainContext *ctx = g_main_context_default(); 44 return g_main_context_get_poll_func(ctx)(fds, nfds, timeout); 45 } 46 #endif 47 48 #if !GLIB_CHECK_VERSION(2, 31, 0) 49 /* before glib-2.31, GMutex and GCond was dynamic-only (there was a separate 50 * GStaticMutex, but it didn't work with condition variables). 51 * 52 * Our implementation uses GOnce to fake a static implementation that does 53 * not require separate initialization. 54 * We need to rename the types to avoid passing our CompatGMutex/CompatGCond 55 * by mistake to a function that expects GMutex/GCond. However, for ease 56 * of use we keep the GLib function names. GLib uses macros for the 57 * implementation, we use inline functions instead and undefine the macros. 58 */ 59 60 typedef struct CompatGMutex { 61 GOnce once; 62 } CompatGMutex; 63 64 typedef struct CompatGCond { 65 GOnce once; 66 } CompatGCond; 67 68 static inline gpointer do_g_mutex_new(gpointer unused) 69 { 70 return (gpointer) g_mutex_new(); 71 } 72 73 static inline void g_mutex_init(CompatGMutex *mutex) 74 { 75 mutex->once = (GOnce) G_ONCE_INIT; 76 } 77 78 static inline void g_mutex_clear(CompatGMutex *mutex) 79 { 80 assert(mutex->once.status != G_ONCE_STATUS_PROGRESS); 81 if (mutex->once.retval) { 82 g_mutex_free((GMutex *) mutex->once.retval); 83 } 84 mutex->once = (GOnce) G_ONCE_INIT; 85 } 86 87 static inline void (g_mutex_lock)(CompatGMutex *mutex) 88 { 89 g_once(&mutex->once, do_g_mutex_new, NULL); 90 g_mutex_lock((GMutex *) mutex->once.retval); 91 } 92 #undef g_mutex_lock 93 94 static inline gboolean (g_mutex_trylock)(CompatGMutex *mutex) 95 { 96 g_once(&mutex->once, do_g_mutex_new, NULL); 97 return g_mutex_trylock((GMutex *) mutex->once.retval); 98 } 99 #undef g_mutex_trylock 100 101 102 static inline void (g_mutex_unlock)(CompatGMutex *mutex) 103 { 104 g_mutex_unlock((GMutex *) mutex->once.retval); 105 } 106 #undef g_mutex_unlock 107 108 static inline gpointer do_g_cond_new(gpointer unused) 109 { 110 return (gpointer) g_cond_new(); 111 } 112 113 static inline void g_cond_init(CompatGCond *cond) 114 { 115 cond->once = (GOnce) G_ONCE_INIT; 116 } 117 118 static inline void g_cond_clear(CompatGCond *cond) 119 { 120 assert(cond->once.status != G_ONCE_STATUS_PROGRESS); 121 if (cond->once.retval) { 122 g_cond_free((GCond *) cond->once.retval); 123 } 124 cond->once = (GOnce) G_ONCE_INIT; 125 } 126 127 static inline void (g_cond_wait)(CompatGCond *cond, CompatGMutex *mutex) 128 { 129 assert(mutex->once.status != G_ONCE_STATUS_PROGRESS); 130 g_once(&cond->once, do_g_cond_new, NULL); 131 g_cond_wait((GCond *) cond->once.retval, (GMutex *) mutex->once.retval); 132 } 133 #undef g_cond_wait 134 135 static inline void (g_cond_broadcast)(CompatGCond *cond) 136 { 137 g_once(&cond->once, do_g_cond_new, NULL); 138 g_cond_broadcast((GCond *) cond->once.retval); 139 } 140 #undef g_cond_broadcast 141 142 static inline void (g_cond_signal)(CompatGCond *cond) 143 { 144 g_once(&cond->once, do_g_cond_new, NULL); 145 g_cond_signal((GCond *) cond->once.retval); 146 } 147 #undef g_cond_signal 148 149 150 /* before 2.31 there was no g_thread_new() */ 151 static inline GThread *g_thread_new(const char *name, 152 GThreadFunc func, gpointer data) 153 { 154 GThread *thread = g_thread_create(func, data, TRUE, NULL); 155 if (!thread) { 156 g_error("creating thread"); 157 } 158 return thread; 159 } 160 #else 161 #define CompatGMutex GMutex 162 #define CompatGCond GCond 163 #endif /* glib 2.31 */ 164 165 #endif 166