[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH 3/7] Add support for glib based threading and co
From: |
Aurelien Jarno |
Subject: |
Re: [Qemu-devel] [PATCH 3/7] Add support for glib based threading and convert qemu thread to use it |
Date: |
Tue, 25 Jan 2011 15:24:48 +0100 |
User-agent: |
Mutt/1.5.18 (2008-05-17) |
On Mon, Jan 24, 2011 at 03:00:41PM -0600, Anthony Liguori wrote:
> 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>
Why removing <signal.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);
If it is still in use here? This simply doesn't build:
qemu-thread.c: In function ‘q_thread_create_nosignal’:
qemu-thread.c:34: error: implicit declaration of function ‘sigfillset’
qemu-thread.c:34: error: nested extern declaration of ‘sigfillset’
qemu-thread.c:35: error: implicit declaration of function ‘pthread_sigmask’
qemu-thread.c:35: error: nested extern declaration of ‘pthread_sigmask’
qemu-thread.c:35: error: ‘SIG_SETMASK’ undeclared (first use in this function)
qemu-thread.c:35: error: (Each undeclared identifier is reported only once
qemu-thread.c:35: error: for each function it appears in.)
qemu-thread.c: In function ‘qemu_sthread_create’:
qemu-thread.c:80: error: ‘SIG_SETMASK’ undeclared (first use in this function)
qemu-thread.c: In function ‘qemu_sthread_signal’:
qemu-thread.c:96: error: implicit declaration of function ‘pthread_kill’
qemu-thread.c:96: error: nested extern declaration of ‘pthread_kill’
> - 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
>
>
>
--
Aurelien Jarno GPG: 1024D/F1BCDB73
address@hidden http://www.aurel32.net
- Re: [Qemu-devel] Re: [PATCH 2/7] Enable I/O thread and VNC threads by default, (continued)
[Qemu-devel] [PATCH 0/2] vnc: the lost parts, Corentin Chary, 2011/01/25
[Qemu-devel] [PATCH 2/2] vnc: qemu can die if the client is disconnected while updating screen, Corentin Chary, 2011/01/25
[Qemu-devel] [PATCH 1/2] vl.c: set NULL upon deleting handlers in qemu_set_fd_handler2(), Corentin Chary, 2011/01/25
[Qemu-devel] [PATCH 3/7] Add support for glib based threading and convert qemu thread to use it, Anthony Liguori, 2011/01/24
- Re: [Qemu-devel] [PATCH 3/7] Add support for glib based threading and convert qemu thread to use it,
Aurelien Jarno <=
[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
[Qemu-devel] [PATCH 5/7] threads: get rid of QemuCond and teach callers about GCond, Anthony Liguori, 2011/01/24