From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from [140.186.70.92] (port=42866 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1PhTXA-0003k1-8q for qemu-devel@nongnu.org; Mon, 24 Jan 2011 16:01:09 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1PhTX8-0005Zy-B9 for qemu-devel@nongnu.org; Mon, 24 Jan 2011 16:01:08 -0500 Received: from e5.ny.us.ibm.com ([32.97.182.145]:60521) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1PhTX8-0005Zs-3Q for qemu-devel@nongnu.org; Mon, 24 Jan 2011 16:01:06 -0500 Received: from d01dlp02.pok.ibm.com (d01dlp02.pok.ibm.com [9.56.224.85]) by e5.ny.us.ibm.com (8.14.4/8.13.1) with ESMTP id p0OKbNGj022516 for ; Mon, 24 Jan 2011 15:37:30 -0500 Received: from d01relay05.pok.ibm.com (d01relay05.pok.ibm.com [9.56.227.237]) by d01dlp02.pok.ibm.com (Postfix) with ESMTP id 7DA764DE8043 for ; Mon, 24 Jan 2011 15:57:37 -0500 (EST) Received: from d01av03.pok.ibm.com (d01av03.pok.ibm.com [9.56.224.217]) by d01relay05.pok.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id p0OL15L2178438 for ; Mon, 24 Jan 2011 16:01:05 -0500 Received: from d01av03.pok.ibm.com (loopback [127.0.0.1]) by d01av03.pok.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id p0OL13qY023829 for ; Mon, 24 Jan 2011 19:01:04 -0200 From: Anthony Liguori Date: Mon, 24 Jan 2011 15:00:41 -0600 Message-Id: <1295902845-29807-4-git-send-email-aliguori@us.ibm.com> In-Reply-To: <1295902845-29807-1-git-send-email-aliguori@us.ibm.com> References: <1295902845-29807-1-git-send-email-aliguori@us.ibm.com> Subject: [Qemu-devel] [PATCH 3/7] Add support for glib based threading and convert qemu thread to use it List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Anthony Liguori , Stefan Hajnoczi , Marcelo Tosatti , Paul Brook , Paulo Bonzini , Arun Bharadwaj 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 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 <> $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 -#include -#include -#include -#include -#include -#include -#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 +#include 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 + //#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