peterdelevoryas / rpms / qemu

Forked from rpms/qemu 2 years ago
Clone

Blame 0113-glib-compat.h-add-new-thread-API-emulation-on-top-of.patch

0410ae
From 57a1d211179279727d5afa21a7feba2d249d6867 Mon Sep 17 00:00:00 2001
0410ae
From: Michael Tokarev <mjt@tls.msk.ru>
0410ae
Date: Thu, 8 May 2014 12:30:46 +0400
0410ae
Subject: [PATCH] glib-compat.h: add new thread API emulation on top of
0410ae
 pre-2.31 API
0410ae
0410ae
Thread API changed in glib-2.31 significantly.  Before that version,
0410ae
conditionals and mutexes were only allocated dynamically, using
0410ae
_new()/_free() interface.  in 2.31 and up, they're allocated statically
0410ae
as regular variables, and old interface is deprecated.
0410ae
0410ae
(Note: glib docs says the new interface is available since version
0410ae
2.32, but it was actually introduced in version 2.31).
0410ae
0410ae
Create the new interface using old primitives, by providing non-opaque
0410ae
definitions of the base types (GCond and GMutex) using GOnces.
0410ae
0410ae
Replace #ifdeffery around GCond and GMutex in trace/simple.c and
0410ae
coroutine-gthread.c too because it does not work anymore with the new
0410ae
glib-compat.h.
0410ae
0410ae
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
0410ae
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
0410ae
[Use GOnce to support lazy initialization; introduce CompatGMutex
0410ae
 and CompatGCond.  - Paolo]
0410ae
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
0410ae
0410ae
(cherry picked from commit 86946a2d835614050b90bc8e5c82982fe45deff2)
0410ae
---
0410ae
 coroutine-gthread.c   |  29 ++++--------
0410ae
 include/glib-compat.h | 119 ++++++++++++++++++++++++++++++++++++++++++++++++++
0410ae
 trace/simple.c        |  50 +++++----------------
0410ae
 3 files changed, 138 insertions(+), 60 deletions(-)
0410ae
0410ae
diff --git a/coroutine-gthread.c b/coroutine-gthread.c
0410ae
index a61efe0..6bd6d6b 100644
0410ae
--- a/coroutine-gthread.c
0410ae
+++ b/coroutine-gthread.c
0410ae
@@ -30,20 +30,14 @@ typedef struct {
0410ae
     CoroutineAction action;
0410ae
 } CoroutineGThread;
0410ae
 
0410ae
-static GStaticMutex coroutine_lock = G_STATIC_MUTEX_INIT;
0410ae
+static CompatGMutex coroutine_lock;
0410ae
+static CompatGCond coroutine_cond;
0410ae
 
0410ae
 /* GLib 2.31 and beyond deprecated various parts of the thread API,
0410ae
  * but the new interfaces are not available in older GLib versions
0410ae
  * so we have to cope with both.
0410ae
  */
0410ae
 #if GLIB_CHECK_VERSION(2, 31, 0)
0410ae
-/* Default zero-initialisation is sufficient for 2.31+ GCond */
0410ae
-static GCond the_coroutine_cond;
0410ae
-static GCond *coroutine_cond = &the_coroutine_cond;
0410ae
-static inline void init_coroutine_cond(void)
0410ae
-{
0410ae
-}
0410ae
-
0410ae
 /* Awkwardly, the GPrivate API doesn't provide a way to update the
0410ae
  * GDestroyNotify handler for the coroutine key dynamically. So instead
0410ae
  * we track whether or not the CoroutineGThread should be freed on
0410ae
@@ -84,11 +78,6 @@ static inline GThread *create_thread(GThreadFunc func, gpointer data)
0410ae
 #else
0410ae
 
0410ae
 /* Handle older GLib versions */
0410ae
-static GCond *coroutine_cond;
0410ae
-static inline void init_coroutine_cond(void)
0410ae
-{
0410ae
-    coroutine_cond = g_cond_new();
0410ae
-}
0410ae
 
0410ae
 static GStaticPrivate coroutine_key = G_STATIC_PRIVATE_INIT;
0410ae
 
0410ae
@@ -120,22 +109,20 @@ static void __attribute__((constructor)) coroutine_init(void)
0410ae
         g_thread_init(NULL);
0410ae
     }
0410ae
 #endif
0410ae
-
0410ae
-    init_coroutine_cond();
0410ae
 }
0410ae
 
0410ae
 static void coroutine_wait_runnable_locked(CoroutineGThread *co)
0410ae
 {
0410ae
     while (!co->runnable) {
0410ae
-        g_cond_wait(coroutine_cond, g_static_mutex_get_mutex(&coroutine_lock));
0410ae
+        g_cond_wait(&coroutine_cond, &coroutine_lock);
0410ae
     }
0410ae
 }
0410ae
 
0410ae
 static void coroutine_wait_runnable(CoroutineGThread *co)
0410ae
 {
0410ae
-    g_static_mutex_lock(&coroutine_lock);
0410ae
+    g_mutex_lock(&coroutine_lock);
0410ae
     coroutine_wait_runnable_locked(co);
0410ae
-    g_static_mutex_unlock(&coroutine_lock);
0410ae
+    g_mutex_unlock(&coroutine_lock);
0410ae
 }
0410ae
 
0410ae
 static gpointer coroutine_thread(gpointer opaque)
0410ae
@@ -177,17 +164,17 @@ CoroutineAction qemu_coroutine_switch(Coroutine *from_,
0410ae
     CoroutineGThread *from = DO_UPCAST(CoroutineGThread, base, from_);
0410ae
     CoroutineGThread *to = DO_UPCAST(CoroutineGThread, base, to_);
0410ae
 
0410ae
-    g_static_mutex_lock(&coroutine_lock);
0410ae
+    g_mutex_lock(&coroutine_lock);
0410ae
     from->runnable = false;
0410ae
     from->action = action;
0410ae
     to->runnable = true;
0410ae
     to->action = action;
0410ae
-    g_cond_broadcast(coroutine_cond);
0410ae
+    g_cond_broadcast(&coroutine_cond);
0410ae
 
0410ae
     if (action != COROUTINE_TERMINATE) {
0410ae
         coroutine_wait_runnable_locked(from);
0410ae
     }
0410ae
-    g_static_mutex_unlock(&coroutine_lock);
0410ae
+    g_mutex_unlock(&coroutine_lock);
0410ae
     return from->action;
0410ae
 }
0410ae
 
0410ae
diff --git a/include/glib-compat.h b/include/glib-compat.h
0410ae
index 1280fb2..4ae0671 100644
0410ae
--- a/include/glib-compat.h
0410ae
+++ b/include/glib-compat.h
0410ae
@@ -5,6 +5,8 @@
0410ae
  *
0410ae
  * Authors:
0410ae
  *  Anthony Liguori   <aliguori@us.ibm.com>
0410ae
+ *  Michael Tokarev   <mjt@tls.msk.ru>
0410ae
+ *  Paolo Bonzini     <pbonzini@redhat.com>
0410ae
  *
0410ae
  * This work is licensed under the terms of the GNU GPL, version 2 or later.
0410ae
  * See the COPYING file in the top-level directory.
0410ae
@@ -43,4 +45,121 @@ static inline gint g_poll(GPollFD *fds, guint nfds, gint timeout)
0410ae
 }
0410ae
 #endif
0410ae
 
0410ae
+#if !GLIB_CHECK_VERSION(2, 31, 0)
0410ae
+/* before glib-2.31, GMutex and GCond was dynamic-only (there was a separate
0410ae
+ * GStaticMutex, but it didn't work with condition variables).
0410ae
+ *
0410ae
+ * Our implementation uses GOnce to fake a static implementation that does
0410ae
+ * not require separate initialization.
0410ae
+ * We need to rename the types to avoid passing our CompatGMutex/CompatGCond
0410ae
+ * by mistake to a function that expects GMutex/GCond.  However, for ease
0410ae
+ * of use we keep the GLib function names.  GLib uses macros for the
0410ae
+ * implementation, we use inline functions instead and undefine the macros.
0410ae
+ */
0410ae
+
0410ae
+typedef struct CompatGMutex {
0410ae
+    GOnce once;
0410ae
+} CompatGMutex;
0410ae
+
0410ae
+typedef struct CompatGCond {
0410ae
+    GOnce once;
0410ae
+} CompatGCond;
0410ae
+
0410ae
+static inline gpointer do_g_mutex_new(gpointer unused)
0410ae
+{
0410ae
+    return (gpointer) g_mutex_new();
0410ae
+}
0410ae
+
0410ae
+static inline void g_mutex_init(CompatGMutex *mutex)
0410ae
+{
0410ae
+    mutex->once = (GOnce) G_ONCE_INIT;
0410ae
+}
0410ae
+
0410ae
+static inline void g_mutex_clear(CompatGMutex *mutex)
0410ae
+{
0410ae
+    assert(mutex->once.status != G_ONCE_STATUS_PROGRESS);
0410ae
+    if (mutex->once.retval) {
0410ae
+        g_mutex_free((GMutex *) mutex->once.retval);
0410ae
+    }
0410ae
+    mutex->once = (GOnce) G_ONCE_INIT;
0410ae
+}
0410ae
+
0410ae
+static inline void (g_mutex_lock)(CompatGMutex *mutex)
0410ae
+{
0410ae
+    g_once(&mutex->once, do_g_mutex_new, NULL);
0410ae
+    g_mutex_lock((GMutex *) mutex->once.retval);
0410ae
+}
0410ae
+#undef g_mutex_lock
0410ae
+
0410ae
+static inline gboolean (g_mutex_trylock)(CompatGMutex *mutex)
0410ae
+{
0410ae
+    g_once(&mutex->once, do_g_mutex_new, NULL);
0410ae
+    return g_mutex_trylock((GMutex *) mutex->once.retval);
0410ae
+}
0410ae
+#undef g_mutex_trylock
0410ae
+
0410ae
+
0410ae
+static inline void (g_mutex_unlock)(CompatGMutex *mutex)
0410ae
+{
0410ae
+    g_mutex_unlock((GMutex *) mutex->once.retval);
0410ae
+}
0410ae
+#undef g_mutex_unlock
0410ae
+
0410ae
+static inline gpointer do_g_cond_new(gpointer unused)
0410ae
+{
0410ae
+    return (gpointer) g_cond_new();
0410ae
+}
0410ae
+
0410ae
+static inline void g_cond_init(CompatGCond *cond)
0410ae
+{
0410ae
+    cond->once = (GOnce) G_ONCE_INIT;
0410ae
+}
0410ae
+
0410ae
+static inline void g_cond_clear(CompatGCond *cond)
0410ae
+{
0410ae
+    assert(cond->once.status != G_ONCE_STATUS_PROGRESS);
0410ae
+    if (cond->once.retval) {
0410ae
+        g_cond_free((GCond *) cond->once.retval);
0410ae
+    }
0410ae
+    cond->once = (GOnce) G_ONCE_INIT;
0410ae
+}
0410ae
+
0410ae
+static inline void (g_cond_wait)(CompatGCond *cond, CompatGMutex *mutex)
0410ae
+{
0410ae
+    assert(mutex->once.status != G_ONCE_STATUS_PROGRESS);
0410ae
+    g_once(&cond->once, do_g_cond_new, NULL);
0410ae
+    g_cond_wait((GCond *) cond->once.retval, (GMutex *) mutex->once.retval);
0410ae
+}
0410ae
+#undef g_cond_wait
0410ae
+
0410ae
+static inline void (g_cond_broadcast)(CompatGCond *cond)
0410ae
+{
0410ae
+    g_once(&cond->once, do_g_cond_new, NULL);
0410ae
+    g_cond_broadcast((GCond *) cond->once.retval);
0410ae
+}
0410ae
+#undef g_cond_broadcast
0410ae
+
0410ae
+static inline void (g_cond_signal)(CompatGCond *cond)
0410ae
+{
0410ae
+    g_once(&cond->once, do_g_cond_new, NULL);
0410ae
+    g_cond_signal((GCond *) cond->once.retval);
0410ae
+}
0410ae
+#undef g_cond_signal
0410ae
+
0410ae
+
0410ae
+/* before 2.31 there was no g_thread_new() */
0410ae
+static inline GThread *g_thread_new(const char *name,
0410ae
+                                    GThreadFunc func, gpointer data)
0410ae
+{
0410ae
+    GThread *thread = g_thread_create(func, data, TRUE, NULL);
0410ae
+    if (!thread) {
0410ae
+        g_error("creating thread");
0410ae
+    }
0410ae
+    return thread;
0410ae
+}
0410ae
+#else
0410ae
+#define CompatGMutex GMutex
0410ae
+#define CompatGCond GCond
0410ae
+#endif /* glib 2.31 */
0410ae
+
0410ae
 #endif
0410ae
diff --git a/trace/simple.c b/trace/simple.c
0410ae
index 1584bf7..8fc96fe 100644
0410ae
--- a/trace/simple.c
0410ae
+++ b/trace/simple.c
0410ae
@@ -40,28 +40,9 @@
0410ae
  * Trace records are written out by a dedicated thread.  The thread waits for
0410ae
  * records to become available, writes them out, and then waits again.
0410ae
  */
0410ae
-#if GLIB_CHECK_VERSION(2, 32, 0)
0410ae
-static GMutex trace_lock;
0410ae
-#define lock_trace_lock() g_mutex_lock(&trace_lock)
0410ae
-#define unlock_trace_lock() g_mutex_unlock(&trace_lock)
0410ae
-#define get_trace_lock_mutex() (&trace_lock)
0410ae
-#else
0410ae
-static GStaticMutex trace_lock = G_STATIC_MUTEX_INIT;
0410ae
-#define lock_trace_lock() g_static_mutex_lock(&trace_lock)
0410ae
-#define unlock_trace_lock() g_static_mutex_unlock(&trace_lock)
0410ae
-#define get_trace_lock_mutex() g_static_mutex_get_mutex(&trace_lock)
0410ae
-#endif
0410ae
-
0410ae
-/* g_cond_new() was deprecated in glib 2.31 but we still need to support it */
0410ae
-#if GLIB_CHECK_VERSION(2, 31, 0)
0410ae
-static GCond the_trace_available_cond;
0410ae
-static GCond the_trace_empty_cond;
0410ae
-static GCond *trace_available_cond = &the_trace_available_cond;
0410ae
-static GCond *trace_empty_cond = &the_trace_empty_cond;
0410ae
-#else
0410ae
-static GCond *trace_available_cond;
0410ae
-static GCond *trace_empty_cond;
0410ae
-#endif
0410ae
+static CompatGMutex trace_lock;
0410ae
+static CompatGCond trace_available_cond;
0410ae
+static CompatGCond trace_empty_cond;
0410ae
 
0410ae
 static bool trace_available;
0410ae
 static bool trace_writeout_enabled;
0410ae
@@ -151,26 +132,26 @@ static bool get_trace_record(unsigned int idx, TraceRecord **recordptr)
0410ae
  */
0410ae
 static void flush_trace_file(bool wait)
0410ae
 {
0410ae
-    lock_trace_lock();
0410ae
+    g_mutex_lock(&trace_lock);
0410ae
     trace_available = true;
0410ae
-    g_cond_signal(trace_available_cond);
0410ae
+    g_cond_signal(&trace_available_cond);
0410ae
 
0410ae
     if (wait) {
0410ae
-        g_cond_wait(trace_empty_cond, get_trace_lock_mutex());
0410ae
+        g_cond_wait(&trace_empty_cond, &trace_lock);
0410ae
     }
0410ae
 
0410ae
-    unlock_trace_lock();
0410ae
+    g_mutex_unlock(&trace_lock);
0410ae
 }
0410ae
 
0410ae
 static void wait_for_trace_records_available(void)
0410ae
 {
0410ae
-    lock_trace_lock();
0410ae
+    g_mutex_lock(&trace_lock);
0410ae
     while (!(trace_available && trace_writeout_enabled)) {
0410ae
-        g_cond_signal(trace_empty_cond);
0410ae
-        g_cond_wait(trace_available_cond, get_trace_lock_mutex());
0410ae
+        g_cond_signal(&trace_empty_cond);
0410ae
+        g_cond_wait(&trace_available_cond, &trace_lock);
0410ae
     }
0410ae
     trace_available = false;
0410ae
-    unlock_trace_lock();
0410ae
+    g_mutex_unlock(&trace_lock);
0410ae
 }
0410ae
 
0410ae
 static gpointer writeout_thread(gpointer opaque)
0410ae
@@ -399,11 +380,7 @@ static GThread *trace_thread_create(GThreadFunc fn)
0410ae
     pthread_sigmask(SIG_SETMASK, &set, &oldset);
0410ae
 #endif
0410ae
 
0410ae
-#if GLIB_CHECK_VERSION(2, 31, 0)
0410ae
     thread = g_thread_new("trace-thread", fn, NULL);
0410ae
-#else
0410ae
-    thread = g_thread_create(fn, NULL, FALSE, NULL);
0410ae
-#endif
0410ae
 
0410ae
 #ifndef _WIN32
0410ae
     pthread_sigmask(SIG_SETMASK, &oldset, NULL);
0410ae
@@ -418,11 +395,6 @@ bool trace_backend_init(const char *events, const char *file)
0410ae
 
0410ae
     trace_pid = getpid();
0410ae
 
0410ae
-#if !GLIB_CHECK_VERSION(2, 31, 0)
0410ae
-    trace_available_cond = g_cond_new();
0410ae
-    trace_empty_cond = g_cond_new();
0410ae
-#endif
0410ae
-
0410ae
     thread = trace_thread_create(writeout_thread);
0410ae
     if (!thread) {
0410ae
         fprintf(stderr, "warning: unable to initialize simple trace backend\n");