qemu/include/glib-compat.h
<<
>>
Prefs
   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/* 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
  26#if !GLIB_CHECK_VERSION(2, 14, 0)
  27static 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
  34#if !GLIB_CHECK_VERSION(2, 28, 0)
  35static 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
  48#if !GLIB_CHECK_VERSION(2, 16, 0)
  49static 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
  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)
  71gint g_poll_fixed(GPollFD *fds, guint nfds, gint timeout);
  72#elif !GLIB_CHECK_VERSION(2, 20, 0)
  73/*
  74 * Glib before 2.20.0 doesn't implement g_poll, so wrap it to compile properly
  75 * on older systems.
  76 */
  77static 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
  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
  96typedef struct CompatGMutex {
  97    GOnce once;
  98} CompatGMutex;
  99
 100typedef struct CompatGCond {
 101    GOnce once;
 102} CompatGCond;
 103
 104static inline gpointer do_g_mutex_new(gpointer unused)
 105{
 106    return (gpointer) g_mutex_new();
 107}
 108
 109static inline void g_mutex_init(CompatGMutex *mutex)
 110{
 111    mutex->once = (GOnce) G_ONCE_INIT;
 112}
 113
 114static 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
 123static 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
 130static 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
 138static inline void (g_mutex_unlock)(CompatGMutex *mutex)
 139{
 140    g_mutex_unlock((GMutex *) mutex->once.retval);
 141}
 142#undef g_mutex_unlock
 143
 144static inline gpointer do_g_cond_new(gpointer unused)
 145{
 146    return (gpointer) g_cond_new();
 147}
 148
 149static inline void g_cond_init(CompatGCond *cond)
 150{
 151    cond->once = (GOnce) G_ONCE_INIT;
 152}
 153
 154static 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
 163static 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
 171static 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
 178static 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() */
 187static 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
 201#endif
 202