[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 3/7] Add support for glib based threading and conver
From: |
Anthony Liguori |
Subject: |
[Qemu-devel] [PATCH 3/7] Add support for glib based threading and convert qemu thread to use it |
Date: |
Mon, 24 Jan 2011 15:00:41 -0600 |
GLib is an extremely common library that has a portable thread implementation
along with tons of other goodies.
GLib and GObject have a fantastic amount of infrastructure we can leverage in
QEMU including an object oriented programming infrastructure.
Short term, it has a very nice thread pool implementation that we could leverage
in something like virtio-9p.
Signed-off-by: Anthony Liguori <address@hidden>
diff --git a/Makefile b/Makefile
index 6d601ee..bf24d1b 100644
--- a/Makefile
+++ b/Makefile
@@ -104,6 +104,8 @@ audio/audio.o audio/fmodaudio.o: QEMU_CFLAGS +=
$(FMOD_CFLAGS)
QEMU_CFLAGS+=$(CURL_CFLAGS)
+QEMU_CFLAGS+=$(GLIB_CFLAGS)
+
ui/cocoa.o: ui/cocoa.m
ui/sdl.o audio/sdlaudio.o ui/sdl_zoom.o baum.o: QEMU_CFLAGS += $(SDL_CFLAGS)
diff --git a/Makefile.objs b/Makefile.objs
index c3e52c5..283e62a 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -316,3 +316,5 @@ vl.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)
vl.o: QEMU_CFLAGS+=$(SDL_CFLAGS)
+vl.o: QEMU_CFLAGS+=$(GLIB_CFLAGS)
+
diff --git a/Makefile.target b/Makefile.target
index e15b1c4..2c1c90e 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -204,6 +204,7 @@ QEMU_CFLAGS += $(VNC_TLS_CFLAGS)
QEMU_CFLAGS += $(VNC_SASL_CFLAGS)
QEMU_CFLAGS += $(VNC_JPEG_CFLAGS)
QEMU_CFLAGS += $(VNC_PNG_CFLAGS)
+QEMU_CFLAGS += $(GLIB_CFLAGS)
# xen backend driver support
obj-$(CONFIG_XEN) += xen_machine_pv.o xen_domainbuild.o
diff --git a/configure b/configure
index d5ac074..820fde9 100755
--- a/configure
+++ b/configure
@@ -1658,6 +1658,17 @@ EOF
fi
##########################################
+# glib support probe
+if $pkg_config --modversion gthread-2.0 > /dev/null 2>&1 ; then
+ glib_cflags=`$pkg_config --cflags gthread-2.0 2>/dev/null`
+ glib_libs=`$pkg_config --libs gthread-2.0 2>/dev/null`
+ libs_softmmu="$glib_libs $libs_softmmu"
+else
+ echo "glib-2.0 required to compile QEMU"
+ exit 1
+fi
+
+##########################################
# kvm probe
if test "$kvm" != "no" ; then
cat > $TMPC <<EOF
@@ -2677,6 +2688,7 @@ if test "$bluez" = "yes" ; then
echo "CONFIG_BLUEZ=y" >> $config_host_mak
echo "BLUEZ_CFLAGS=$bluez_cflags" >> $config_host_mak
fi
+echo "GLIB_CFLAGS=$glib_cflags" >> $config_host_mak
if test "$xen" = "yes" ; then
echo "CONFIG_XEN=y" >> $config_host_mak
fi
diff --git a/qemu-thread.c b/qemu-thread.c
index fbc78fe..2c521ab 100644
--- a/qemu-thread.c
+++ b/qemu-thread.c
@@ -10,183 +10,142 @@
* See the COPYING file in the top-level directory.
*
*/
-#include <stdlib.h>
-#include <stdio.h>
-#include <errno.h>
-#include <time.h>
-#include <signal.h>
-#include <stdint.h>
-#include <string.h>
-#include "qemu-thread.h"
-static void error_exit(int err, const char *msg)
-{
- fprintf(stderr, "qemu: %s: %s\n", msg, strerror(err));
- exit(1);
-}
+#include "qemu-common.h"
+#include "qemu-thread.h"
void qemu_mutex_init(QemuMutex *mutex)
{
- int err;
-
- err = pthread_mutex_init(&mutex->lock, NULL);
- if (err)
- error_exit(err, __func__);
+ g_static_mutex_init(&mutex->lock);
}
void qemu_mutex_destroy(QemuMutex *mutex)
{
- int err;
-
- err = pthread_mutex_destroy(&mutex->lock);
- if (err)
- error_exit(err, __func__);
+ g_static_mutex_free(&mutex->lock);
}
void qemu_mutex_lock(QemuMutex *mutex)
{
- int err;
-
- err = pthread_mutex_lock(&mutex->lock);
- if (err)
- error_exit(err, __func__);
+ g_static_mutex_lock(&mutex->lock);
}
int qemu_mutex_trylock(QemuMutex *mutex)
{
- return pthread_mutex_trylock(&mutex->lock);
-}
-
-static void timespec_add_ms(struct timespec *ts, uint64_t msecs)
-{
- ts->tv_sec = ts->tv_sec + (long)(msecs / 1000);
- ts->tv_nsec = (ts->tv_nsec + ((long)msecs % 1000) * 1000000);
- if (ts->tv_nsec >= 1000000000) {
- ts->tv_nsec -= 1000000000;
- ts->tv_sec++;
- }
-}
-
-int qemu_mutex_timedlock(QemuMutex *mutex, uint64_t msecs)
-{
- int err;
- struct timespec ts;
-
- clock_gettime(CLOCK_REALTIME, &ts);
- timespec_add_ms(&ts, msecs);
-
- err = pthread_mutex_timedlock(&mutex->lock, &ts);
- if (err && err != ETIMEDOUT)
- error_exit(err, __func__);
- return err;
+ return g_static_mutex_trylock(&mutex->lock);
}
void qemu_mutex_unlock(QemuMutex *mutex)
{
- int err;
-
- err = pthread_mutex_unlock(&mutex->lock);
- if (err)
- error_exit(err, __func__);
+ g_static_mutex_unlock(&mutex->lock);
}
void qemu_cond_init(QemuCond *cond)
{
- int err;
-
- err = pthread_cond_init(&cond->cond, NULL);
- if (err)
- error_exit(err, __func__);
+ cond->cond = g_cond_new();
}
void qemu_cond_destroy(QemuCond *cond)
{
- int err;
-
- err = pthread_cond_destroy(&cond->cond);
- if (err)
- error_exit(err, __func__);
+ g_cond_free(cond->cond);
}
void qemu_cond_signal(QemuCond *cond)
{
- int err;
-
- err = pthread_cond_signal(&cond->cond);
- if (err)
- error_exit(err, __func__);
+ g_cond_signal(cond->cond);
}
void qemu_cond_broadcast(QemuCond *cond)
{
- int err;
-
- err = pthread_cond_broadcast(&cond->cond);
- if (err)
- error_exit(err, __func__);
+ g_cond_broadcast(cond->cond);
}
void qemu_cond_wait(QemuCond *cond, QemuMutex *mutex)
{
- int err;
-
- err = pthread_cond_wait(&cond->cond, &mutex->lock);
- if (err)
- error_exit(err, __func__);
+ g_cond_wait(cond->cond, g_static_mutex_get_mutex(&mutex->lock));
}
int qemu_cond_timedwait(QemuCond *cond, QemuMutex *mutex, uint64_t msecs)
{
- struct timespec ts;
- int err;
+ GTimeVal abs_time;
+
+ assert(cond->cond != NULL);
- clock_gettime(CLOCK_REALTIME, &ts);
- timespec_add_ms(&ts, msecs);
+ g_get_current_time(&abs_time);
+ g_time_val_add(&abs_time, msecs * 1000); /* MSEC to USEC */
- err = pthread_cond_timedwait(&cond->cond, &mutex->lock, &ts);
- if (err && err != ETIMEDOUT)
- error_exit(err, __func__);
- return err;
+ return g_cond_timed_wait(cond->cond,
+ g_static_mutex_get_mutex(&mutex->lock),
&abs_time);
+}
+
+struct trampoline_data
+{
+ QemuThread *thread;
+ void *(*startfn)(void *);
+ void *opaque;
+ QemuMutex lock;
+};
+
+static gpointer thread_trampoline(gpointer data)
+{
+ struct trampoline_data *td = data;
+ gpointer retval;
+
+ td->thread->tid = pthread_self();
+ qemu_mutex_unlock(&td->lock);
+
+ retval = td->startfn(td->opaque);
+ qemu_free(td);
+
+ return retval;
}
void qemu_thread_create(QemuThread *thread,
- void *(*start_routine)(void*),
- void *arg)
+ void *(*start_routine)(void*),
+ void *arg)
{
- int err;
+ struct trampoline_data *td = qemu_malloc(sizeof(*td));
+ sigset_t set, old;
- /* Leave signal handling to the iothread. */
- sigset_t set, oldset;
+ td->startfn = start_routine;
+ td->opaque = arg;
+ td->thread = thread;
+ qemu_mutex_init(&td->lock);
+
+ /* on behalf of the new thread */
+ qemu_mutex_lock(&td->lock);
sigfillset(&set);
- pthread_sigmask(SIG_SETMASK, &set, &oldset);
- err = pthread_create(&thread->thread, NULL, start_routine, arg);
- if (err)
- error_exit(err, __func__);
+ pthread_sigmask(SIG_SETMASK, &set, &old);
+ thread->thread = g_thread_create(thread_trampoline, td, TRUE, NULL);
+ pthread_sigmask(SIG_SETMASK, &old, NULL);
+
+ /* we're transfering ownership of this lock to the thread so we no
+ * longer hold it here */
- pthread_sigmask(SIG_SETMASK, &oldset, NULL);
+ qemu_mutex_lock(&td->lock);
+ /* validate tid */
+ qemu_mutex_unlock(&td->lock);
+
+ qemu_mutex_destroy(&td->lock);
}
void qemu_thread_signal(QemuThread *thread, int sig)
{
- int err;
-
- err = pthread_kill(thread->thread, sig);
- if (err)
- error_exit(err, __func__);
+ pthread_kill(thread->tid, sig);
}
void qemu_thread_self(QemuThread *thread)
{
- thread->thread = pthread_self();
+ thread->thread = g_thread_self();
+ thread->tid = pthread_self();
}
int qemu_thread_equal(QemuThread *thread1, QemuThread *thread2)
{
- return pthread_equal(thread1->thread, thread2->thread);
+ return (thread1->thread == thread2->thread);
}
void qemu_thread_exit(void *retval)
{
- pthread_exit(retval);
+ g_thread_exit(retval);
}
diff --git a/qemu-thread.h b/qemu-thread.h
index 19bb30c..dc22a60 100644
--- a/qemu-thread.h
+++ b/qemu-thread.h
@@ -1,18 +1,19 @@
#ifndef __QEMU_THREAD_H
#define __QEMU_THREAD_H 1
-#include "semaphore.h"
-#include "pthread.h"
+#include <glib.h>
+#include <pthread.h>
struct QemuMutex {
- pthread_mutex_t lock;
+ GStaticMutex lock;
};
struct QemuCond {
- pthread_cond_t cond;
+ GCond *cond;
};
struct QemuThread {
- pthread_t thread;
+ GThread *thread;
+ pthread_t tid;
};
typedef struct QemuMutex QemuMutex;
diff --git a/vl.c b/vl.c
index 0292184..bbe0931 100644
--- a/vl.c
+++ b/vl.c
@@ -165,6 +165,8 @@ int main(int argc, char **argv)
#include "ui/qemu-spice.h"
+#include <glib.h>
+
//#define DEBUG_NET
//#define DEBUG_SLIRP
@@ -1918,6 +1920,8 @@ int main(int argc, char **argv, char **envp)
atexit(qemu_run_exit_notifiers);
error_set_progname(argv[0]);
+ g_thread_init(NULL);
+
init_clocks();
qemu_cache_utils_init(envp);
--
1.7.0.4
[Qemu-devel] [PATCH 3/7] Add support for glib based threading and convert qemu thread to use it,
Anthony Liguori <=
[Qemu-devel] [PATCH 7/7] Rename QemuThread to QemuSThread to indicate that it is not a generic thread, Anthony Liguori, 2011/01/24
[Qemu-devel] [PATCH 6/7] Teach vnc server to use GThread directly, Anthony Liguori, 2011/01/24
[Qemu-devel] [PATCH 4/7] Get rid of QemuMutex and teach its callers about GStaticMutex, Anthony Liguori, 2011/01/24
[Qemu-devel] [PATCH 1/7] io-thread: make sure to initialize qemu_work_cond and qemu_cpu_cond, Anthony Liguori, 2011/01/24