diff --git a/Makefile b/Makefile index ed887de560..0f40cdac31 100644 --- a/Makefile +++ b/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 \ diff --git a/Makefile.target b/Makefile.target index 21715873a3..82ada5a0e6 100644 --- a/Makefile.target +++ b/Makefile.target @@ -318,7 +318,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 @@ -694,7 +695,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 diff --git a/configure b/configure index b7b7b01d48..2f4ccfb407 100755 --- a/configure +++ b/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" @@ -479,8 +481,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" @@ -611,7 +617,9 @@ echo " --oss-lib path to OSS library" 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 "" @@ -1123,21 +1131,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 @@ -1245,8 +1259,7 @@ elif $cc $ARCH_CFLAGS -o $TMPE $TMPC -lrt > /dev/null 2> /dev/null ; then 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 @@ -1324,6 +1337,7 @@ echo "uname -r $uname_release" echo "NPTL support $nptl" echo "vde support $vde" echo "AIO support $aio" +echo "IO thread $io_thread" echo "Install blobs $blobs" echo "KVM support $kvm" echo "fdt support $fdt" @@ -1376,7 +1390,8 @@ echo "ARCH_LDFLAGS=$ARCH_LDFLAGS" >> $config_mak 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 @@ -1640,6 +1655,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 diff --git a/qemu-thread.c b/qemu-thread.c new file mode 100644 index 0000000000..719cfcddd4 --- /dev/null +++ b/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); +} + diff --git a/qemu-thread.h b/qemu-thread.h new file mode 100644 index 0000000000..5ef4a3aed5 --- /dev/null +++ b/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