Signed-off-by: Marcelo Tosatti Index: qemu/Makefile =================================================================== --- qemu.orig/Makefile +++ qemu/Makefile @@ -30,7 +30,8 @@ else DOCS= endif -LIBS+=$(AIOLIBS) +LIBS+=$(PTHREADLIBS) +LIBS+=$(CLOCKLIBS) ifdef CONFIG_SOLARIS LIBS+=-lsocket -lnsl -lresolv @@ -170,6 +171,10 @@ ifdef CONFIG_COCOA OBJS+=cocoa.o endif +ifdef CONFIG_IOTHREAD +OBJS+=qemu-thread.o +endif + ifdef CONFIG_SLIRP CPPFLAGS+=-I$(SRC_PATH)/slirp SLIRP_OBJS=cksum.o if.o ip_icmp.o ip_input.o ip_output.o \ Index: qemu/Makefile.target =================================================================== --- qemu.orig/Makefile.target +++ qemu/Makefile.target @@ -315,7 +315,8 @@ endif OBJS= main.o syscall.o strace.o mmap.o signal.o path.o thunk.o \ elfload.o linuxload.o uaccess.o envlist.o -LIBS+= $(AIOLIBS) +LIBS+= $(PTHREADLIBS) +LIBS+= $(CLOCKLIBS) ifdef TARGET_HAS_BFLT OBJS+= flatload.o endif @@ -683,7 +684,8 @@ ifdef CONFIG_SLIRP CPPFLAGS+=-I$(SRC_PATH)/slirp endif -LIBS+=$(AIOLIBS) +LIBS+=$(PTHREADLIBS) +LIBS+=$(CLOCKLIBS) # specific flags are needed for non soft mmu emulator ifdef CONFIG_STATIC LDFLAGS+=-static Index: qemu/configure =================================================================== --- qemu.orig/configure +++ qemu/configure @@ -181,7 +181,9 @@ bsd_user="no" build_docs="no" uname_release="" curses="yes" +pthread="yes" aio="yes" +io_thread="no" nptl="yes" mixemu="no" bluez="yes" @@ -476,8 +478,12 @@ for opt do ;; --enable-mixemu) mixemu="yes" ;; + --disable-pthread) pthread="no" + ;; --disable-aio) aio="no" ;; + --enable-io-thread) io_thread="yes" + ;; --disable-blobs) blobs="no" ;; --kerneldir=*) kerneldir="$optarg" @@ -607,7 +613,9 @@ echo " --oss-lib path to echo " --enable-uname-release=R Return R for uname -r in usermode emulation" echo " --sparc_cpu=V Build qemu for Sparc architecture v7, v8, v8plus, v8plusa, v9" echo " --disable-vde disable support for vde network" +echo " --disable-pthread disable pthread support" echo " --disable-aio disable AIO support" +echo " --enable-io-thread enable IO thread" echo " --disable-blobs disable installing provided firmware blobs" echo " --kerneldir=PATH look for kernel includes in PATH" echo "" @@ -1103,21 +1111,26 @@ EOF fi ########################################## -# AIO probe -AIOLIBS="" +# pthread probe +PTHREADLIBS="" -if test "$aio" = "yes" ; then - aio=no - cat > $TMPC << EOF +if test "$pthread" = yes; then + pthread=no +cat > $TMPC << EOF #include int main(void) { pthread_mutex_t lock; return 0; } EOF - if $cc $ARCH_CFLAGS -o $TMPE $AIOLIBS $TMPC 2> /dev/null ; then - aio=yes - AIOLIBS="-lpthread" + if $cc $ARCH_CFLAGS -o $TMPE $PTHREADLIBS $TMPC 2> /dev/null ; then + pthread=yes + PTHREADLIBS="-lpthread" fi fi +if test "$pthread" = no; then + aio=no + io_thread=no +fi + ########################################## # iovec probe cat > $TMPC < $TMPC < #include @@ -1225,8 +1239,7 @@ elif $cc $ARCH_CFLAGS -o $TMPE $TMPC -lr fi if test "$rt" = "yes" ; then - # Hack, we should have a general purpose LIBS for this sort of thing - AIOLIBS="$AIOLIBS -lrt" + CLOCKLIBS="-lrt" fi if test "$mingw32" = "yes" ; then @@ -1302,7 +1315,8 @@ echo "Documentation $build_docs" echo "uname -r $uname_release" echo "NPTL support $nptl" echo "vde support $vde" -echo "AIO support $aio" +echo "IO support $aio" +echo "IO thread $io_thread" echo "Install blobs $blobs" echo "KVM support $kvm" echo "fdt support $fdt" @@ -1352,7 +1366,8 @@ echo "ARCH_LDFLAGS=$ARCH_LDFLAGS" >> $co echo "CFLAGS=$CFLAGS" >> $config_mak echo "LDFLAGS=$LDFLAGS" >> $config_mak echo "EXESUF=$EXESUF" >> $config_mak -echo "AIOLIBS=$AIOLIBS" >> $config_mak +echo "PTHREADLIBS=$PTHREADLIBS" >> $config_mak +echo "CLOCKLIBS=$CLOCKLIBS" >> $config_mak case "$cpu" in i386) echo "ARCH=i386" >> $config_mak @@ -1613,6 +1628,10 @@ if test "$aio" = "yes" ; then echo "#define CONFIG_AIO 1" >> $config_h echo "CONFIG_AIO=yes" >> $config_mak fi +if test "$io_thread" = "yes" ; then + echo "CONFIG_IOTHREAD=yes" >> $config_mak + echo "#define CONFIG_IOTHREAD 1" >> $config_h +fi if test "$blobs" = "yes" ; then echo "INSTALL_BLOBS=yes" >> $config_mak fi Index: qemu/qemu-thread.c =================================================================== --- /dev/null +++ qemu/qemu-thread.c @@ -0,0 +1,163 @@ +/* + * Wrappers around mutex/cond/thread functions + * + * Copyright Red Hat, Inc. 2009 + * + * Author: + * Marcelo Tosatti + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * 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); +} + +void qemu_mutex_init(QemuMutex *mutex) +{ + int err; + + err = pthread_mutex_init(&mutex->lock, NULL); + if (err) + error_exit(err, __func__); +} + +void qemu_mutex_lock(QemuMutex *mutex) +{ + int err; + + err = pthread_mutex_lock(&mutex->lock); + if (err) + error_exit(err, __func__); +} + +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; +} + +void qemu_mutex_unlock(QemuMutex *mutex) +{ + int err; + + err = pthread_mutex_unlock(&mutex->lock); + if (err) + error_exit(err, __func__); +} + +void qemu_cond_init(QemuCond *cond) +{ + int err; + + err = pthread_cond_init(&cond->cond, NULL); + if (err) + error_exit(err, __func__); +} + +void qemu_cond_signal(QemuCond *cond) +{ + int err; + + err = pthread_cond_signal(&cond->cond); + if (err) + error_exit(err, __func__); +} + +void qemu_cond_broadcast(QemuCond *cond) +{ + int err; + + err = pthread_cond_broadcast(&cond->cond); + if (err) + error_exit(err, __func__); +} + +void qemu_cond_wait(QemuCond *cond, QemuMutex *mutex) +{ + int err; + + err = pthread_cond_wait(&cond->cond, &mutex->lock); + if (err) + error_exit(err, __func__); +} + +int qemu_cond_timedwait(QemuCond *cond, QemuMutex *mutex, uint64_t msecs) +{ + struct timespec ts; + int err; + + clock_gettime(CLOCK_REALTIME, &ts); + timespec_add_ms(&ts, msecs); + + err = pthread_cond_timedwait(&cond->cond, &mutex->lock, &ts); + if (err && err != ETIMEDOUT) + error_exit(err, __func__); + return err; +} + +void qemu_thread_create(QemuThread *thread, + void *(*start_routine)(void*), + void *arg) +{ + int err; + + err = pthread_create(&thread->thread, NULL, start_routine, arg); + if (err) + error_exit(err, __func__); +} + +void qemu_thread_signal(QemuThread *thread, int sig) +{ + int err; + + err = pthread_kill(thread->thread, sig); + if (err) + error_exit(err, __func__); +} + +void qemu_thread_self(QemuThread *thread) +{ + thread->thread = pthread_self(); +} + +int qemu_thread_equal(QemuThread *thread1, QemuThread *thread2) +{ + return (thread1->thread == thread2->thread); +} + Index: qemu/qemu-thread.h =================================================================== --- /dev/null +++ qemu/qemu-thread.h @@ -0,0 +1,40 @@ +#ifndef __QEMU_THREAD_H +#define __QEMU_THREAD_H 1 +#include "semaphore.h" +#include "pthread.h" + +struct QemuMutex { + pthread_mutex_t lock; +}; + +struct QemuCond { + pthread_cond_t cond; +}; + +struct QemuThread { + pthread_t thread; +}; + +typedef struct QemuMutex QemuMutex; +typedef struct QemuCond QemuCond; +typedef struct QemuThread QemuThread; + +void qemu_mutex_init(QemuMutex *mutex); +void qemu_mutex_lock(QemuMutex *mutex); +int qemu_mutex_trylock(QemuMutex *mutex); +int qemu_mutex_timedlock(QemuMutex *mutex, uint64_t msecs); +void qemu_mutex_unlock(QemuMutex *mutex); + +void qemu_cond_init(QemuCond *cond); +void qemu_cond_signal(QemuCond *cond); +void qemu_cond_broadcast(QemuCond *cond); +void qemu_cond_wait(QemuCond *cond, QemuMutex *mutex); +int qemu_cond_timedwait(QemuCond *cond, QemuMutex *mutex, uint64_t msecs); + +void qemu_thread_create(QemuThread *thread, + void *(*start_routine)(void*), + void *arg); +void qemu_thread_signal(QemuThread *thread, int sig); +void qemu_thread_self(QemuThread *thread); +int qemu_thread_equal(QemuThread *thread1, QemuThread *thread2); +#endif --