qemu/coroutine-gthread.c
Alon Levy 42ed372753 g_thread_init users: don't call it if glib >= 2.31
since commit f9b29ca03 included in release 2.31 (docs below say 2.32 but
that is not correct) and onwards g_thread_init is deprecated and calling
it is not required:

 http://developer.gnome.org/glib/unstable/glib-Deprecated-Thread-APIs.html#g-thread-init

 g_thread_init has been deprecated since version 2.32 and should not be
 used in newly-written code. This function is no longer necessary. The
 GLib threading system is automatically initialized at the start of your
 program.

Fixes bulid failure when warnings are treated as errors on fedora 17.

I only tested the change to vl.c, and copy pasted to the two other
locations (couldn't decide if a wrapper for calling g_thread_init is
uglier).

Signed-off-by: Alon Levy <alevy@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2011-12-20 15:44:31 -06:00

136 lines
3.7 KiB
C

/*
* GThread coroutine initialization code
*
* Copyright (C) 2006 Anthony Liguori <anthony@codemonkey.ws>
* Copyright (C) 2011 Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#include <glib.h>
#include "qemu-common.h"
#include "qemu-coroutine-int.h"
typedef struct {
Coroutine base;
GThread *thread;
bool runnable;
CoroutineAction action;
} CoroutineGThread;
static GCond *coroutine_cond;
static GStaticMutex coroutine_lock = G_STATIC_MUTEX_INIT;
static GStaticPrivate coroutine_key = G_STATIC_PRIVATE_INIT;
static void __attribute__((constructor)) coroutine_init(void)
{
if (!g_thread_supported()) {
#if !GLIB_CHECK_VERSION(2, 31, 0)
g_thread_init(NULL);
#else
fprintf(stderr, "glib threading failed to initialize.\n");
exit(1);
#endif
}
coroutine_cond = g_cond_new();
}
static void coroutine_wait_runnable_locked(CoroutineGThread *co)
{
while (!co->runnable) {
g_cond_wait(coroutine_cond, g_static_mutex_get_mutex(&coroutine_lock));
}
}
static void coroutine_wait_runnable(CoroutineGThread *co)
{
g_static_mutex_lock(&coroutine_lock);
coroutine_wait_runnable_locked(co);
g_static_mutex_unlock(&coroutine_lock);
}
static gpointer coroutine_thread(gpointer opaque)
{
CoroutineGThread *co = opaque;
g_static_private_set(&coroutine_key, co, NULL);
coroutine_wait_runnable(co);
co->base.entry(co->base.entry_arg);
qemu_coroutine_switch(&co->base, co->base.caller, COROUTINE_TERMINATE);
return NULL;
}
Coroutine *qemu_coroutine_new(void)
{
CoroutineGThread *co;
co = g_malloc0(sizeof(*co));
co->thread = g_thread_create_full(coroutine_thread, co, 0, TRUE, TRUE,
G_THREAD_PRIORITY_NORMAL, NULL);
if (!co->thread) {
g_free(co);
return NULL;
}
return &co->base;
}
void qemu_coroutine_delete(Coroutine *co_)
{
CoroutineGThread *co = DO_UPCAST(CoroutineGThread, base, co_);
g_thread_join(co->thread);
g_free(co);
}
CoroutineAction qemu_coroutine_switch(Coroutine *from_,
Coroutine *to_,
CoroutineAction action)
{
CoroutineGThread *from = DO_UPCAST(CoroutineGThread, base, from_);
CoroutineGThread *to = DO_UPCAST(CoroutineGThread, base, to_);
g_static_mutex_lock(&coroutine_lock);
from->runnable = false;
from->action = action;
to->runnable = true;
to->action = action;
g_cond_broadcast(coroutine_cond);
if (action != COROUTINE_TERMINATE) {
coroutine_wait_runnable_locked(from);
}
g_static_mutex_unlock(&coroutine_lock);
return from->action;
}
Coroutine *qemu_coroutine_self(void)
{
CoroutineGThread *co = g_static_private_get(&coroutine_key);
if (!co) {
co = g_malloc0(sizeof(*co));
co->runnable = true;
g_static_private_set(&coroutine_key, co, (GDestroyNotify)g_free);
}
return &co->base;
}
bool qemu_in_coroutine(void)
{
CoroutineGThread *co = g_static_private_get(&coroutine_key);
return co && co->base.caller;
}