Spread the use of QEMU threading & locking API
cover Spread the use of QEMU threading & locking API
This adds two missing features to our QEMU threading and locking abstractions, qemu_thread_join and qemu_cond_timedwait, and then converts compat AIO, compatfd, and several audio subsystems. This not only saves a few lines of code, it also allows to apply certain thread and lock parameters centrally which is specifically important when using SCHED_FIFO.
Note that patch 6 is untested. Am I right that the other threads coreaudioVoiceOut::mutex addresses are created by the coreaudio core? Just curious.
Furthermore note that the changes to posix-aio-compat.c depend on patches in Kevin's latest pull request.
Jan Kiszka (6):
Enable joinable POSIX threads
Introduce qemu_cond_timedwait
Switch POSIX compat AIO to QEMU abstractions
Switch compatfd to QEMU thread
audio: Use QEMU threads & synchronization
audio: Switch coreaudio to QemuMutex
audio/audio_pt_int.c | 167 ++--------------------------------------------- audio/audio_pt_int.h | 45 +++++++++---- audio/coreaudio.c | 56 ++-------------- audio/esdaudio.c | 92 +++++++------------------- audio/paaudio.c | 84 +++++++---------------- compatfd.c | 16 +---- cpus.c | 6 +- hw/ccid-card-emulated.c | 5 +- posix-aio-compat.c | 115 +++++++++----------------------- qemu-thread-posix.c | 53 ++++++++++++++- qemu-thread-posix.h | 3 + qemu-thread-win32.c | 20 +++++- qemu-thread.h | 9 ++- ui/vnc-jobs-async.c | 2 +- 14 files changed, 219 insertions(+), 454 deletions(-)
Signature · 1 line
1.7.3.4
PATCH 1/6 Enable joinable POSIX threads
Allow to control if a QEMU thread is created joinable or not. Make it not joinable by default to avoid that we keep the associated resources around when terminating a thread without joining it (what we couldn't do so far for obvious reasons).
The audio subsystem will need the join feature when converting it to QEMU threading/locking abstractions, so provide that service. Join will only be provided for POSIX as there is no setup in sight yet where Windows would need it as well (+implementation is non-trivial).
--- cpus.c | 6 ++++-- hw/ccid-card-emulated.c | 5 +++-- qemu-thread-posix.c | 31 +++++++++++++++++++++++++++---- qemu-thread-posix.h | 3 +++ qemu-thread-win32.c | 4 +++- qemu-thread.h | 7 +++++-- ui/vnc-jobs-async.c | 2 +- 7 files changed, 46 insertions(+), 12 deletions(-)
cpus.c +4 -2
@@ -822,7 +822,8 @@ static void qemu_tcg_init_vcpu(void *_env) env->halt_cond =g_malloc0 (sizeof (QemuCond));qemu_cond_init (env->halt_cond); tcg_halt_cond = env->halt_cond; -qemu_thread_create (env->thread, qemu_tcg_cpu_thread_fn, env); +qemu_thread_create (env->thread, qemu_tcg_cpu_thread_fn, env, +QEMU_THREAD_DETACHED );while (env->created ==0 ) {qemu_cond_wait (&qemu_cpu_cond, &qemu_global_mutex); }
@@ -838,7 +839,8 @@ static void qemu_kvm_start_vcpu(CPUState *env) env->thread =g_malloc0 (sizeof (QemuThread)); env->halt_cond =g_malloc0 (sizeof (QemuCond));qemu_cond_init (env->halt_cond); -qemu_thread_create (env->thread, qemu_kvm_cpu_thread_fn, env); +qemu_thread_create (env->thread, qemu_kvm_cpu_thread_fn, env, +QEMU_THREAD_DETACHED );while (env->created ==0 ) {qemu_cond_wait (&qemu_cpu_cond, &qemu_global_mutex); }
hw/ccid-card-emulated.c +3 -2
@@ -541,8 +541,9 @@ static int emulated_initfn(CCIDCardState *base)printf ("%s: failed to initialize vcard\n" ,EMULATED_DEV_NAME );return -1 ; } -qemu_thread_create (&thread_id, event_thread, card); -qemu_thread_create (&thread_id, handle_apdu_thread, card); +qemu_thread_create (&thread_id, event_thread, card,QEMU_THREAD_DETACHED ); +qemu_thread_create (&thread_id, handle_apdu_thread, card, +QEMU_THREAD_DETACHED );return 0 ; }
qemu-thread-posix.c +27 -4
@@ -117,20 +117,33 @@ void qemu_cond_wait(QemuCond *cond, QemuMutex *mutex)void qemu_thread_create (QemuThread *thread,void *(*start_routine)(void *), -void *arg) +void *arg,int mode) { +sigset_t set, oldset; +pthread_attr_t attr;int err; -/* Leave signal handling to the iothread. */ -sigset_t set, oldset; + err =pthread_attr_init (&attr); +if (err) { +error_exit (err, __func__); + } +if (mode ==QEMU_THREAD_DETACHED ) { + err =pthread_attr_setdetachstate (&attr,PTHREAD_CREATE_DETACHED ); +if (err) { +error_exit (err, __func__); + } + } +/* Leave signal handling to the iothread. */ sigfillset (&set);pthread_sigmask (SIG_SETMASK , &set, &oldset); - err =pthread_create (&thread->thread,NULL , start_routine, arg); + err =pthread_create (&thread->thread, &attr, start_routine, arg);if (err)error_exit (err, __func__);pthread_sigmask (SIG_SETMASK , &oldset,NULL ); + +pthread_attr_destroy (&attr); }void qemu_thread_get_self (QemuThread *thread)
@@ -147,3 +160,13 @@ void qemu_thread_exit(void *retval) {pthread_exit (retval); } + +void qemu_thread_join (QemuThread *thread) +{ +int err; + + err =pthread_join (thread->thread,NULL ); +if (err) { +error_exit (err, __func__); + } +}
qemu-thread-posix.h +3 -0
@@ -14,4 +14,7 @@ struct QemuThread { pthread_t thread; }; +/* only provided for posix so far */ +void qemu_thread_join (QemuThread *thread); +#endif
qemu-thread-win32.c +3 -1
@@ -243,10 +243,12 @@ static inline void qemu_thread_init(void)void qemu_thread_create (QemuThread *thread,void *(*start_routine)(void *), -void *arg) +void *arg,int mode) {HANDLE hThread; +assert (mode ==QEMU_THREAD_DETACHED ); +struct QemuThreadData *data;qemu_thread_init (); data =g_malloc (sizeof *data);
qemu-thread.h +5 -2
@@ -13,6 +13,9 @@ typedef struct QemuThread QemuThread;#include "qemu-thread-posix.h" #endif +#define QEMU_THREAD_JOINABLE 0 +#define QEMU_THREAD_DETACHED 1 +void qemu_mutex_init (QemuMutex *mutex);void qemu_mutex_destroy (QemuMutex *mutex);void qemu_mutex_lock (QemuMutex *mutex);
@@ -32,8 +35,8 @@ void qemu_cond_broadcast(QemuCond *cond);void qemu_cond_wait (QemuCond *cond,QemuMutex *mutex);void qemu_thread_create (QemuThread *thread, -void *(*start_routine)(void *), -void *arg); +void *(*start_routine)(void *), +void *arg,int mode);void qemu_thread_get_self (QemuThread *thread);int qemu_thread_is_self (QemuThread *thread);void qemu_thread_exit (void *retval);
ui/vnc-jobs-async.c +1 -1
@@ -318,7 +318,7 @@ void vnc_start_worker_thread(void)return ; q =vnc_queue_init (); -qemu_thread_create (&q->thread, vnc_worker_thread, q); +qemu_thread_create (&q->thread, vnc_worker_thread, q,QEMU_THREAD_DETACHED ); queue = q;/* Set global queue */ }
Signature · 1 line
1.7.3.4
Re: [Qemu-devel] [PATCH 1/6] Enable joinable POSIX threads
hw/ccid-card-emulated.c static int emulated_initfn(CCIDCardState *base) · line 548
Quoted 7 lines · Jan Kiszka
hw/ccid-card-emulated.c +3
-2-qemu_thread_create (&thread_id, event_thread, card); -qemu_thread_create (&thread_id, handle_apdu_thread, card); +qemu_thread_create (&thread_id, event_thread, card,QEMU_THREAD_DETACHED ); +qemu_thread_create (&thread_id, handle_apdu_thread, card, +QEMU_THREAD_DETACHED );return 0 ; }
I think these two should be joinable. Otherwise, you might be destroying the apdu_thread_quit_mutex while the handle_apdu_thread hasn't yet finished unlocking it (even though it already progressed enough in qemu_mutex_destroy to release the main thread).
Anyhow, the bug is not introduced by your patch, so
Re: [Qemu-devel] [PATCH 1/6] Enable joinable POSIX threads
Am 21.09.2011 09:16, schrieb Paolo Bonzini:
Quoted 9 lines · Jan Kiszka
hw/ccid-card-emulated.c static int emulated_initfn(CCIDCardState *base) · line 548
Quoted 7 lines
hw/ccid-card-emulated.c +3
-2-qemu_thread_create (&thread_id, event_thread, card); -qemu_thread_create (&thread_id, handle_apdu_thread, card); +qemu_thread_create (&thread_id, event_thread, card,QEMU_THREAD_DETACHED ); +qemu_thread_create (&thread_id, handle_apdu_thread, card, +QEMU_THREAD_DETACHED );return 0 ; }
Quoted 8 lines
I think these two should be joinable. Otherwise, you might be destroying the
apdu_thread_quit_mutexwhile thehandle_apdu_threadhasn't yet finished unlocking it (even though it already progressed enough inqemu_mutex_destroyto release the main thread).Anyhow, the bug is not introduced by your patch, so
Reviewed-by Paolo Bonzini <[email protected]>
Actually, the man page says that joinable is the default, so this patch does change the behaviour.
Kevin
Re: [Qemu-devel] [PATCH 1/6] Enable joinable POSIX threads
Quoted 11 lines · Kevin Wolf
Quoted 9 lines
Quoted 9 lines
I think these two should be joinable. Otherwise, you might be destroying the
apdu_thread_quit_mutexwhile thehandle_apdu_threadhasn't yet finished unlocking it (even though it already progressed enough inqemu_mutex_destroyto release the main thread).Anyhow, the bug is not introduced by your patch, so
Reviewed-by Paolo Bonzini<[email protected]>Actually, the man page says that joinable is the default, so this patch does change the behaviour.
Yes, but it doesn't change the fact that mutexes are destroyed under the thread's feet. i.e. it doesn't introduce the race.
Paolo
PATCH 2/6 Introduce qemu_cond_timedwait
In reply to Jan KiszkaFirst user will be posix compat aio.
--- qemu-thread-posix.c | 22 ++++++++++++++++++++++ qemu-thread-win32.c | 16 +++++++++++++++- qemu-thread.h | 2 ++ 3 files changed, 39 insertions(+), 1 deletions(-)
qemu-thread-posix.c +22 -0
@@ -17,6 +17,7 @@#include <signal.h> #include <stdint.h> #include <string.h> +#include <sys/time.h> #include "qemu-thread.h" static void error_exit (int err,const char *msg)
@@ -115,6 +116,27 @@ void qemu_cond_wait(QemuCond *cond, QemuMutex *mutex)error_exit (err, __func__); } +int qemu_cond_timedwait (QemuCond *cond,QemuMutex *mutex, +unsigned int timeout_ms) +{ +struct timespec ts; +struct timeval tv; +int err; + +gettimeofday (&tv,NULL ); + ts.tv_sec = tv.tv_sec + timeout_ms /1000 ; + ts.tv_nsec = tv.tv_usec *1000 + timeout_ms %1000 ; +if (ts.tv_nsec >1000000000 ) { + ts.tv_sec++; + ts.tv_nsec -=1000000000 ; + } + err =pthread_cond_timedwait (&cond->cond, &mutex->lock, &ts); +if (err && err !=ETIMEDOUT ) { +error_exit (err, __func__); + } +return err ==0 ; +} +void qemu_thread_create (QemuThread *thread,void *(*start_routine)(void *),void *arg,int mode)
qemu-thread-win32.c +15 -1
@@ -158,6 +158,14 @@ void qemu_cond_broadcast(QemuCond *cond)void qemu_cond_wait (QemuCond *cond,QemuMutex *mutex) { +qemu_cond_timedwait (cond, mutex,INFINITE ); +} + +int qemu_cond_timedwait (QemuCond *cond,QemuMutex *mutex, +unsigned int timeout_ms) +{ +DWORD result; +/* * This access is protected under the mutex. */
@@ -170,7 +178,11 @@ void qemu_cond_wait(QemuCond *cond, QemuMutex *mutex)* leaving mutex unlocked before we wait on semaphore. */ qemu_mutex_unlock (mutex); -WaitForSingleObject (cond->sema,INFINITE ); + result =WaitForSingleObject (cond->sema, timeout_ms); + +if (result !=WAIT_OBJECT_0 && result !=WAIT_TIMEOUT ) { +error_exit (GetLastError (), __func__); + }/* Now waiters must rendez-vous with the signaling thread and * let it continue. For cond_broadcast this has heavy contention
@@ -190,6 +202,8 @@ void qemu_cond_wait(QemuCond *cond, QemuMutex *mutex) }qemu_mutex_lock (mutex); + +return result ==WAIT_OBJECT_0 ; }struct QemuThreadData {
qemu-thread.h +2 -0
@@ -33,6 +33,8 @@ void qemu_cond_destroy(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, +unsigned int timeout_ms); void qemu_thread_create(QemuThread *thread, void *(*start_routine)(void *),
Signature · 1 line
1.7.3.4
Re: [Qemu-devel] [PATCH 2/6] Introduce qemu_cond_timedwait
Quoted 3 lines · Jan Kiszka
First user will be posix compat aio.
Signed-off-by Jan Kiszka<[email protected]>
I'm pretty sure the win32 version is not thread-safe, but posix compat aio is currently POSIX only. Just leave it out.
Paolo
PATCH v2 2/6 Introduce qemu_cond_timedwait for POSIX
Quoted 6 lines · Paolo Bonzini
Quoted 3 lines · Jan Kiszka
First user will be posix compat aio.
Signed-off-by Jan Kiszka<[email protected]>I'm pretty sure the win32 version is not thread-safe,
Yeah, I would even say it's completely broken. Was a naive hack.
Quoted 3 lines
but posix compat
aio is currently POSIX only. Just leave it out.
-------8<-------
From: Jan Kiszka <[email protected]>
First user will be POSIX compat aio. Windows use cases aren't in sight, so this remains a POSIX-only service for now.
--- qemu-thread-posix.c | 22 ++++++++++++++++++++++ qemu-thread-posix.h | 2 ++ 2 files changed, 24 insertions(+), 0 deletions(-)
qemu-thread-posix.c +22 -0
@@ -17,6 +17,7 @@#include <signal.h> #include <stdint.h> #include <string.h> +#include <sys/time.h> #include "qemu-thread.h" static void error_exit (int err,const char *msg)
@@ -115,6 +116,27 @@ void qemu_cond_wait(QemuCond *cond, QemuMutex *mutex)error_exit (err, __func__); } +int qemu_cond_timedwait (QemuCond *cond,QemuMutex *mutex, +unsigned int timeout_ms) +{ +struct timespec ts; +struct timeval tv; +int err; + +gettimeofday (&tv,NULL ); + ts.tv_sec = tv.tv_sec + timeout_ms /1000 ; + ts.tv_nsec = tv.tv_usec *1000 + timeout_ms %1000 ; +if (ts.tv_nsec >1000000000 ) { + ts.tv_sec++; + ts.tv_nsec -=1000000000 ; + } + err =pthread_cond_timedwait (&cond->cond, &mutex->lock, &ts); +if (err && err !=ETIMEDOUT ) { +error_exit (err, __func__); + } +return err ==0 ; +} +void qemu_thread_create (QemuThread *thread,void *(*start_routine)(void *),void *arg,int mode)
qemu-thread-posix.h +2 -0
@@ -16,5 +16,7 @@ struct QemuThread {/* only provided for posix so far */ void qemu_thread_join (QemuThread *thread); +int qemu_cond_timedwait (QemuCond *cond,QemuMutex *mutex, +unsigned int timeout_ms);#endif
PATCH 3/6 Switch POSIX compat AIO to QEMU abstractions
In reply to Jan KiszkaAlthough there is nothing to wrap for non-POSIX here, redirecting thread and synchronization services to our core simplifies managements jobs like scheduling parameter adjustment. It also frees compat AIO from some duplicate code (/wrt qemu-thread).
--- posix-aio-compat.c | 115 ++++++++++++++------------------------------------- 1 files changed, 32 insertions(+), 83 deletions(-)
posix-aio-compat.c +32 -83
@@ -13,7 +13,6 @@#include <sys/ioctl.h> #include <sys/types.h> -#include <pthread.h> #include <unistd.h> #include <errno.h> #include <time.h>
@@ -27,9 +26,12 @@#include "qemu-common.h" #include "trace.h" #include "block_int.h" +#include "qemu-thread.h" #include "block/raw-posix-aio.h" +#define AIO_THREAD_IDLE_TIMEOUT 10000/* 10 s */ +static void do_spawn_thread (void );struct qemu_paiocb {
@@ -57,10 +59,9 @@ typedef struct PosixAioState { } PosixAioState; -static pthread_mutex_t lock =PTHREAD_MUTEX_INITIALIZER ; -static pthread_cond_t cond =PTHREAD_COND_INITIALIZER ; -static pthread_t thread_id; -static pthread_attr_t attr; +static QemuMutex lock; +static QemuCond cond; +static QemuThread thread;static int max_threads =64 ;static int cur_threads =0 ;static int idle_threads =0 ;
@@ -86,39 +87,6 @@ static void die(const char *what)die2 (errno, what); } -static void mutex_lock (pthread_mutex_t *mutex) -{ -int ret =pthread_mutex_lock (mutex); -if (ret)die2 (ret,"pthread_mutex_lock" ); -} - -static void mutex_unlock (pthread_mutex_t *mutex) -{ -int ret =pthread_mutex_unlock (mutex); -if (ret)die2 (ret,"pthread_mutex_unlock" ); -} - -static int cond_timedwait (pthread_cond_t *cond,pthread_mutex_t *mutex, -struct timespec *ts) -{ -int ret =pthread_cond_timedwait (cond, mutex, ts); -if (ret && ret !=ETIMEDOUT )die2 (ret,"pthread_cond_timedwait" ); -return ret; -} - -static void cond_signal (pthread_cond_t *cond) -{ -int ret =pthread_cond_signal (cond); -if (ret)die2 (ret,"pthread_cond_signal" ); -} - -static void thread_create (pthread_t *thread,pthread_attr_t *attr, -void *(*start_routine)(void *),void *arg) -{ -int ret =pthread_create (thread, attr, start_routine, arg); -if (ret)die2 (ret,"pthread_create" ); -} -static ssize_t handle_aiocb_ioctl (struct qemu_paiocb *aiocb) {int ret;
@@ -311,27 +279,22 @@ static void posix_aio_notify_event(void);static void *aio_thread (void *unused) { -mutex_lock (&lock); +qemu_mutex_lock (&lock); pending_threads--; -mutex_unlock (&lock); +qemu_mutex_unlock (&lock);do_spawn_thread ();while (1 ) {struct qemu_paiocb *aiocb; -ssize_t ret =0 ; -qemu_timeval tv; -struct timespec ts; - -qemu_gettimeofday (&tv); - ts.tv_sec = tv.tv_sec +10 ; - ts.tv_nsec =0 ; +bool timed_out = false; +ssize_t ret; -mutex_lock (&lock); +qemu_mutex_lock (&lock); -while (QTAILQ_EMPTY (&request_list) && - !(ret ==ETIMEDOUT )) { +while (QTAILQ_EMPTY (&request_list) && !timed_out) { idle_threads++; - ret =cond_timedwait (&cond, &lock, &ts); + timed_out =qemu_cond_timedwait (&cond, &lock, +AIO_THREAD_IDLE_TIMEOUT ) !=0 ; idle_threads--; }
@@ -341,7 +304,7 @@ static void *aio_thread(void *unused) aiocb =QTAILQ_FIRST (&request_list);QTAILQ_REMOVE (&request_list, aiocb, node); aiocb->active =1 ; -mutex_unlock (&lock); +qemu_mutex_unlock (&lock);switch (aiocb->aio_type &QEMU_AIO_TYPE_MASK ) {case QEMU_AIO_READ :
@@ -373,41 +336,33 @@ static void *aio_thread(void *unused)break ; } -mutex_lock (&lock); +qemu_mutex_lock (&lock); aiocb->ret = ret; -mutex_unlock (&lock); +qemu_mutex_unlock (&lock);posix_aio_notify_event (); } cur_threads--; -mutex_unlock (&lock); +qemu_mutex_unlock (&lock);return NULL ; }static void do_spawn_thread (void ) { -sigset_t set, oldset; - -mutex_lock (&lock); +qemu_mutex_lock (&lock);if (!new_threads) { -mutex_unlock (&lock); +qemu_mutex_unlock (&lock);return ; } new_threads--; pending_threads++; -mutex_unlock (&lock); +qemu_mutex_unlock (&lock); -/* block all signals */ -if (sigfillset (&set))die ("sigfillset" ); -if (sigprocmask (SIG_SETMASK , &set, &oldset))die ("sigprocmask" ); - -thread_create (&thread_id, &attr, aio_thread,NULL ); - -if (sigprocmask (SIG_SETMASK , &oldset,NULL ))die ("sigprocmask restore" ); +qemu_thread_create (&thread, aio_thread,NULL ,QEMU_THREAD_DETACHED ); }static void spawn_thread_bh_fn (void *opaque)
@@ -435,21 +390,21 @@ static void qemu_paio_submit(struct qemu_paiocb *aiocb) { aiocb->ret = -EINPROGRESS ; aiocb->active =0 ; -mutex_lock (&lock); +qemu_mutex_lock (&lock);if (idle_threads ==0 && cur_threads < max_threads)spawn_thread ();QTAILQ_INSERT_TAIL (&request_list, aiocb, node); -mutex_unlock (&lock); -cond_signal (&cond); +qemu_mutex_unlock (&lock); +qemu_cond_signal (&cond); }static ssize_t qemu_paio_return (struct qemu_paiocb *aiocb) {ssize_t ret; -mutex_lock (&lock); +qemu_mutex_lock (&lock); ret = aiocb->ret; -mutex_unlock (&lock); +qemu_mutex_unlock (&lock);return ret; }
@@ -580,14 +535,14 @@ static void paio_cancel(BlockDriverAIOCB *blockacb)trace_paio_cancel (acb, acb->common.opaque); -mutex_lock (&lock); +qemu_mutex_lock (&lock);if (!acb->active) {QTAILQ_REMOVE (&request_list, acb, node); acb->ret = -ECANCELED ; }else if (acb->ret == -EINPROGRESS ) { active =1 ; } -mutex_unlock (&lock); +qemu_mutex_unlock (&lock);if (active) {/* fail safe: if the aio could not be canceled, we wait for
@@ -657,11 +612,13 @@ int paio_init(void) {PosixAioState *s;int fds[2 ]; -int ret;if (posix_aio_state)return 0 ; +qemu_mutex_init (&lock); +qemu_cond_init (&cond); + s =g_malloc (sizeof (PosixAioState)); s->first_aio =NULL ;
@@ -679,14 +636,6 @@ int paio_init(void)qemu_aio_set_fd_handler (s->rfd, posix_aio_read,NULL , posix_aio_flush, posix_aio_process_queue, s); - ret =pthread_attr_init (&attr); -if (ret) -die2 (ret,"pthread_attr_init" ); - - ret =pthread_attr_setdetachstate (&attr,PTHREAD_CREATE_DETACHED ); -if (ret) -die2 (ret,"pthread_attr_setdetachstate" ); -QTAILQ_INIT (&request_list); new_thread_bh =qemu_bh_new (spawn_thread_bh_fn,NULL );
Signature · 1 line
1.7.3.4
Re: [Qemu-devel] [PATCH 3/6] Switch POSIX compat AIO to QEMU abstractions
Am 20.09.2011 18:53, schrieb Jan Kiszka:
Quoted 113 lines
Although there is nothing to wrap for non-POSIX here, redirecting thread and synchronization services to our core simplifies managements jobs like scheduling parameter adjustment. It also frees compat AIO from some duplicate code (/wrt qemu-thread).
CC Kevin Wolf <[email protected]>Signed-off-by Jan Kiszka <[email protected]>--- posix-aio-compat.c | 115 ++++++++++++++------------------------------------- 1 files changed, 32 insertions(+), 83 deletions(-)posix-aio-compat.c +10
-47@@ -13,7 +13,6 @@#include <sys/ioctl.h> #include <sys/types.h> -#include <pthread.h> #include <unistd.h> #include <errno.h> #include <time.h> @@ -27,9 +26,12 @@#include "qemu-common.h" #include "trace.h" #include "block_int.h" +#include "qemu-thread.h" #include "block/raw-posix-aio.h" +#define AIO_THREAD_IDLE_TIMEOUT 10000/* 10 s */ +static void do_spawn_thread (void );struct qemu_paiocb {@@ -57,10 +59,9 @@ typedef struct PosixAioState { } PosixAioState; -static pthread_mutex_t lock =PTHREAD_MUTEX_INITIALIZER ; -static pthread_cond_t cond =PTHREAD_COND_INITIALIZER ; -static pthread_t thread_id; -static pthread_attr_t attr; +static QemuMutex lock; +static QemuCond cond; +static QemuThread thread;static int max_threads =64 ;static int cur_threads =0 ;static int idle_threads =0 ;@@ -86,39 +87,6 @@ static void die(const char *what)die2 (errno, what); } -static void mutex_lock (pthread_mutex_t *mutex) -{ -int ret =pthread_mutex_lock (mutex); -if (ret)die2 (ret,"pthread_mutex_lock" ); -} - -static void mutex_unlock (pthread_mutex_t *mutex) -{ -int ret =pthread_mutex_unlock (mutex); -if (ret)die2 (ret,"pthread_mutex_unlock" ); -} - -static int cond_timedwait (pthread_cond_t *cond,pthread_mutex_t *mutex, -struct timespec *ts) -{ -int ret =pthread_cond_timedwait (cond, mutex, ts); -if (ret && ret !=ETIMEDOUT )die2 (ret,"pthread_cond_timedwait" ); -return ret; -} - -static void cond_signal (pthread_cond_t *cond) -{ -int ret =pthread_cond_signal (cond); -if (ret)die2 (ret,"pthread_cond_signal" ); -} - -static void thread_create (pthread_t *thread,pthread_attr_t *attr, -void *(*start_routine)(void *),void *arg) -{ -int ret =pthread_create (thread, attr, start_routine, arg); -if (ret)die2 (ret,"pthread_create" ); -} -static ssize_t handle_aiocb_ioctl (struct qemu_paiocb *aiocb) {int ret;@@ -311,27 +279,22 @@ static void posix_aio_notify_event(void);static void *aio_thread (void *unused) { -mutex_lock (&lock); +qemu_mutex_lock (&lock); pending_threads--; -mutex_unlock (&lock); +qemu_mutex_unlock (&lock);do_spawn_thread ();while (1 ) {struct qemu_paiocb *aiocb; -ssize_t ret =0 ; -qemu_timeval tv; -struct timespec ts; - -qemu_gettimeofday (&tv); - ts.tv_sec = tv.tv_sec +10 ; - ts.tv_nsec =0 ; +bool timed_out = false; +ssize_t ret;
posix-aio-compat.c static void posix_aio_notify_event(void); · line 297
Quoted 10 lines
posix-aio-compat.c +4
-4-mutex_lock (&lock); +qemu_mutex_lock (&lock); -while (QTAILQ_EMPTY (&request_list) && - !(ret ==ETIMEDOUT )) { +while (QTAILQ_EMPTY (&request_list) && !timed_out) { idle_threads++; - ret =cond_timedwait (&cond, &lock, &ts); + timed_out =qemu_cond_timedwait (&cond, &lock, +AIO_THREAD_IDLE_TIMEOUT ) !=0 ;
Maybe I'm confused by too many negations, but isn't this the wrong way round?
+ err = pthread_cond_timedwait(&cond->cond, &mutex->lock, &ts);
+ if (err && err != ETIMEDOUT) {
+ error_exit(err, __func__);
+ }
+ return err == 0;
So if there was an timeout, qemu_cond_timedwait returns 0 (should it return a bool? Also documenting the return value wouldn't hurt) and timed_out becomes false (0 != 0).
Kevin
Re: [Qemu-devel] [PATCH 3/6] Switch POSIX compat AIO to QEMU abstractions
Quoted 117 lines · Kevin Wolf
Am 20.09.2011 18:53, schrieb Jan Kiszka:
Quoted 116 lines
Although there is nothing to wrap for non-POSIX here, redirecting thread and synchronization services to our core simplifies managements jobs like scheduling parameter adjustment. It also frees compat AIO from some duplicate code (/wrt qemu-thread).
CC Kevin Wolf <[email protected]>Signed-off-by Jan Kiszka <[email protected]>--- posix-aio-compat.c | 115 ++++++++++++++------------------------------------- 1 files changed, 32 insertions(+), 83 deletions(-)posix-aio-compat.c +11
-48@@ -13,7 +13,6 @@#include <sys/ioctl.h> #include <sys/types.h> -#include <pthread.h> #include <unistd.h> #include <errno.h> #include <time.h> @@ -27,9 +26,12 @@#include "qemu-common.h" #include "trace.h" #include "block_int.h" +#include "qemu-thread.h" #include "block/raw-posix-aio.h" +#define AIO_THREAD_IDLE_TIMEOUT 10000/* 10 s */ +static void do_spawn_thread (void );struct qemu_paiocb {@@ -57,10 +59,9 @@ typedef struct PosixAioState { } PosixAioState; -static pthread_mutex_t lock =PTHREAD_MUTEX_INITIALIZER ; -static pthread_cond_t cond =PTHREAD_COND_INITIALIZER ; -static pthread_t thread_id; -static pthread_attr_t attr; +static QemuMutex lock; +static QemuCond cond; +static QemuThread thread;static int max_threads =64 ;static int cur_threads =0 ;static int idle_threads =0 ;@@ -86,39 +87,6 @@ static void die(const char *what)die2 (errno, what); } -static void mutex_lock (pthread_mutex_t *mutex) -{ -int ret =pthread_mutex_lock (mutex); -if (ret)die2 (ret,"pthread_mutex_lock" ); -} - -static void mutex_unlock (pthread_mutex_t *mutex) -{ -int ret =pthread_mutex_unlock (mutex); -if (ret)die2 (ret,"pthread_mutex_unlock" ); -} - -static int cond_timedwait (pthread_cond_t *cond,pthread_mutex_t *mutex, -struct timespec *ts) -{ -int ret =pthread_cond_timedwait (cond, mutex, ts); -if (ret && ret !=ETIMEDOUT )die2 (ret,"pthread_cond_timedwait" ); -return ret; -} - -static void cond_signal (pthread_cond_t *cond) -{ -int ret =pthread_cond_signal (cond); -if (ret)die2 (ret,"pthread_cond_signal" ); -} - -static void thread_create (pthread_t *thread,pthread_attr_t *attr, -void *(*start_routine)(void *),void *arg) -{ -int ret =pthread_create (thread, attr, start_routine, arg); -if (ret)die2 (ret,"pthread_create" ); -} -static ssize_t handle_aiocb_ioctl (struct qemu_paiocb *aiocb) {int ret;@@ -311,27 +279,22 @@ static void posix_aio_notify_event(void);static void *aio_thread (void *unused) { -mutex_lock (&lock); +qemu_mutex_lock (&lock); pending_threads--; -mutex_unlock (&lock); +qemu_mutex_unlock (&lock);do_spawn_thread ();while (1 ) {struct qemu_paiocb *aiocb; -ssize_t ret =0 ; -qemu_timeval tv; -struct timespec ts; - -qemu_gettimeofday (&tv); - ts.tv_sec = tv.tv_sec +10 ; - ts.tv_nsec =0 ; +bool timed_out = false; +ssize_t ret; -mutex_lock (&lock); +qemu_mutex_lock (&lock);
Quoted 10 lines
posix-aio-compat.c static void posix_aio_notify_event(void); · line 297
Quoted 7 lines
posix-aio-compat.c +3
-3-while (QTAILQ_EMPTY (&request_list) && - !(ret ==ETIMEDOUT )) { +while (QTAILQ_EMPTY (&request_list) && !timed_out) { idle_threads++; - ret =cond_timedwait (&cond, &lock, &ts); + timed_out =qemu_cond_timedwait (&cond, &lock, +AIO_THREAD_IDLE_TIMEOUT ) !=0 ;Maybe I'm confused by too many negations, but isn't this the wrong way round?
You mean design-wise? Maybe. In any case, I think this code would also win if we just do
if (timed_out) break;
in the loop instead of testing the inverse on entry.
Quoted 10 lines
(quoted diff) +5
-0+ err = pthread_cond_timedwait(&cond->cond, &mutex->lock, &ts); + if (err && err != ETIMEDOUT) { + error_exit(err, __func__); + } + return err == 0;So if there was an timeout,
qemu_cond_timedwaitreturns 0 (should it return a bool? Also documenting the return value wouldn't hurt) andtimed_outbecomes false (0 != 0).
Will switch to a bool return code (and document it).
Thanks,
Jan
Signature · 2 lines
Siemens AG, Corporate Technology, CT T DE IT 1 Corporate Competence Center Embedded Linux
Re: [Qemu-devel] [PATCH 3/6] Switch POSIX compat AIO to QEMU abstractions
Am 21.09.2011 16:02, schrieb Jan Kiszka:
Quoted 50 lines · Kevin Wolf
Quoted 38 lines
Am 20.09.2011 18:53, schrieb Jan Kiszka:
Quoted 37 lines
Although there is nothing to wrap for non-POSIX here, redirecting thread and synchronization services to our core simplifies managements jobs like scheduling parameter adjustment. It also frees compat AIO from some duplicate code (/wrt qemu-thread).
CC Kevin Wolf <[email protected]>Signed-off-by Jan Kiszka <[email protected]>--- posix-aio-compat.c | 115 ++++++++++++++------------------------------------- 1 files changed, 32 insertions(+), 83 deletions(-)posix-aio-compat.c +5
-10@@ -311,27 +279,22 @@ static void posix_aio_notify_event(void);static void *aio_thread (void *unused) { -mutex_lock (&lock); +qemu_mutex_lock (&lock); pending_threads--; -mutex_unlock (&lock); +qemu_mutex_unlock (&lock);do_spawn_thread ();while (1 ) {struct qemu_paiocb *aiocb; -ssize_t ret =0 ; -qemu_timeval tv; -struct timespec ts; - -qemu_gettimeofday (&tv); - ts.tv_sec = tv.tv_sec +10 ; - ts.tv_nsec =0 ; +bool timed_out = false; +ssize_t ret; -mutex_lock (&lock); +qemu_mutex_lock (&lock);Quoted 10 lines
posix-aio-compat.c static void posix_aio_notify_event(void); · line 297
Quoted 7 lines
posix-aio-compat.c +3
-3-while (QTAILQ_EMPTY (&request_list) && - !(ret ==ETIMEDOUT )) { +while (QTAILQ_EMPTY (&request_list) && !timed_out) { idle_threads++; - ret =cond_timedwait (&cond, &lock, &ts); + timed_out =qemu_cond_timedwait (&cond, &lock, +AIO_THREAD_IDLE_TIMEOUT ) !=0 ;Maybe I'm confused by too many negations, but isn't this the wrong way round?
Quoted 7 lines
You mean design-wise? Maybe. In any case, I think this code would also win if we just do
if (timed_out) break;in the loop instead of testing the inverse on entry.
Design-wise I'm not sure. Maybe it would be more consistent if qemu_cond_timedwait returned 0/ETIMEDOUT, maybe it doesn't really make a difference. I just felt a bit confused when reading it.
What I really meant is that I think it should be == instead of !=:
timed_out = qemu_cond_timedwait(...) == 0;
Quoted 11 lines
Quoted 9 lines
(quoted diff) +5
-0+ err = pthread_cond_timedwait(&cond->cond, &mutex->lock, &ts); + if (err && err != ETIMEDOUT) { + error_exit(err, __func__); + } + return err == 0;So if there was an timeout,
qemu_cond_timedwaitreturns 0 (should it return a bool? Also documenting the return value wouldn't hurt) andtimed_outbecomes false (0 != 0).Will switch to a bool return code (and document it).
Ok.
Kevin
PATCH 4/6 Switch compatfd to QEMU thread
In reply to Jan Kiszkaqemu_thread_create already does signal blocking and detaching for us.
--- compatfd.c | 16 +++------------- 1 files changed, 3 insertions(+), 13 deletions(-)
compatfd.c +3 -13
@@ -12,10 +12,10 @@*/ #include "qemu-common.h" +#include "qemu-thread.h" #include "compatfd.h" #include <sys/syscall.h> -#include <pthread.h> struct sigfd_compat_info {
@@ -26,10 +26,6 @@ struct sigfd_compat_infostatic void *sigwait_compat (void *opaque) {struct sigfd_compat_info *info = opaque; -sigset_t all; - -sigfillset (&all); -pthread_sigmask (SIG_BLOCK , &all,NULL );while (1 ) {int sig;
@@ -69,9 +65,8 @@ static void *sigwait_compat(void *opaque)static int qemu_signalfd_compat (const sigset_t *mask) { -pthread_attr_t attr; -pthread_t tid;struct sigfd_compat_info *info; +QemuThread thread;int fds[2 ]; info =malloc (sizeof (*info));
@@ -91,12 +86,7 @@ static int qemu_signalfd_compat(const sigset_t *mask)memcpy (&info->mask, mask,sizeof (*mask)); info->fd = fds[1 ]; -pthread_attr_init (&attr); -pthread_attr_setdetachstate (&attr,PTHREAD_CREATE_DETACHED ); - -pthread_create (&tid, &attr, sigwait_compat, info); - -pthread_attr_destroy (&attr); +qemu_thread_create (&thread, sigwait_compat, info,QEMU_THREAD_DETACHED );return fds[0 ]; }
Signature · 1 line
1.7.3.4
PATCH 5/6 audio: Use QEMU threads & synchronization
In reply to Jan KiszkaThis both simplifies error handling and enables central management of threads and locks.
--- audio/audio_pt_int.c | 167 ++----------------------------------------------- audio/audio_pt_int.h | 45 ++++++++++---- audio/esdaudio.c | 92 ++++++++-------------------- audio/paaudio.c | 84 ++++++++----------------- 4 files changed, 91 insertions(+), 297 deletions(-)
audio/audio_pt_int.c +7 -160
@@ -6,168 +6,15 @@#include "audio_int.h" #include "audio_pt_int.h" -static void GCC_FMT_ATTR(3, 4) logerr (struct audio_pt *pt, int err, - const char *fmt, ...) +void audio_pt_init (struct audio_pt *p,void *(*func) (void *),void *opaque) { - va_list ap; - - va_start (ap, fmt); - AUD_vlog (pt->drv, fmt, ap); -va_end (ap); - - AUD_log (NULL, "\n"); - AUD_log (pt->drv, "Reason: %s\n", strerror (err)); -} - -int audio_pt_init (struct audio_pt *p, void *(*func) (void *), - void *opaque, const char *drv, const char *cap) -{ - int err, err2; -const char *efunc; -sigset_t set, old_set; - - p->drv = drv; - - err = sigfillset (&set); - if (err) { -logerr (p, errno,"%s(%s): sigfillset failed" , cap,AUDIO_FUNC ); -return -1 ; - } - - err =pthread_mutex_init (&p->mutex,NULL ); -if (err) { - efunc ="pthread_mutex_init" ; - goto err0; - } - - err =pthread_cond_init (&p->cond,NULL ); -if (err) { - efunc ="pthread_cond_init" ; - goto err1; - } - - err =pthread_sigmask (SIG_BLOCK , &set, &old_set); -if (err) { - efunc ="pthread_sigmask" ; - goto err2; - } - - err =pthread_create (&p->thread,NULL , func, opaque); - - err2 =pthread_sigmask (SIG_SETMASK , &old_set,NULL ); -if (err2) { -logerr (p, err2,"%s(%s): pthread_sigmask (restore) failed" , - cap,AUDIO_FUNC ); -/* We have failed to restore original signal mask, all bets are off, -so terminate the process */ -exit (EXIT_FAILURE ); - } - -if (err) { - efunc ="pthread_create" ; - goto err2; - } - -return 0 ; - - err2: - err2 =pthread_cond_destroy (&p->cond); -if (err2) { -logerr (p, err2,"%s(%s): pthread_cond_destroy failed" , cap,AUDIO_FUNC ); - } - - err1: - err2 =pthread_mutex_destroy (&p->mutex); -if (err2) { -logerr (p, err2,"%s(%s): pthread_mutex_destroy failed" , cap,AUDIO_FUNC ); - } - - err0: -logerr (p, err,"%s(%s): %s failed" , cap,AUDIO_FUNC , efunc); -return -1 ; +qemu_mutex_init (&p->mutex); +qemu_cond_init (&p->cond); +qemu_thread_create (&p->thread, func, opaque,QEMU_THREAD_JOINABLE ); } -int audio_pt_fini (struct audio_pt *p,const char *cap) +void audio_pt_fini (struct audio_pt *p) { -int err, ret =0 ; - - err =pthread_cond_destroy (&p->cond); -if (err) { -logerr (p, err,"%s(%s): pthread_cond_destroy failed" , cap,AUDIO_FUNC ); - ret =-1 ; - } - - err =pthread_mutex_destroy (&p->mutex); -if (err) { -logerr (p, err,"%s(%s): pthread_mutex_destroy failed" , cap,AUDIO_FUNC ); - ret =-1 ; - } -return ret; -} - -int audio_pt_lock (struct audio_pt *p,const char *cap) -{ -int err; - - err =pthread_mutex_lock (&p->mutex); -if (err) { -logerr (p, err,"%s(%s): pthread_mutex_lock failed" , cap,AUDIO_FUNC ); -return -1 ; - } -return 0 ; -} - -int audio_pt_unlock (struct audio_pt *p,const char *cap) -{ -int err; - - err =pthread_mutex_unlock (&p->mutex); -if (err) { -logerr (p, err,"%s(%s): pthread_mutex_unlock failed" , cap,AUDIO_FUNC ); -return -1 ; - } -return 0 ; -} - -int audio_pt_wait (struct audio_pt *p,const char *cap) -{ -int err; - - err =pthread_cond_wait (&p->cond, &p->mutex); -if (err) { -logerr (p, err,"%s(%s): pthread_cond_wait failed" , cap,AUDIO_FUNC ); -return -1 ; - } -return 0 ; -} - -int audio_pt_unlock_and_signal (struct audio_pt *p,const char *cap) -{ -int err; - - err =pthread_mutex_unlock (&p->mutex); -if (err) { -logerr (p, err,"%s(%s): pthread_mutex_unlock failed" , cap,AUDIO_FUNC ); -return -1 ; - } - err =pthread_cond_signal (&p->cond); -if (err) { -logerr (p, err,"%s(%s): pthread_cond_signal failed" , cap,AUDIO_FUNC ); -return -1 ; - } -return 0 ; -} - -int audio_pt_join (struct audio_pt *p,void **arg,const char *cap) -{ -int err; -void *ret; - - err =pthread_join (p->thread, &ret); -if (err) { -logerr (p, err,"%s(%s): pthread_join failed" , cap,AUDIO_FUNC ); -return -1 ; - } - *arg = ret; -return 0 ; +qemu_cond_destroy (&p->cond); +qemu_mutex_destroy (&p->mutex); }
audio/audio_pt_int.h +32 -13
54 lines not on this page · raw message
audio/esdaudio.c +26 -66
226 lines not on this page · raw message
audio/paaudio.c +26 -58
218 lines not on this page · raw message
Signature · 1 line
1.7.3.4
PATCH 6/6 audio: Switch coreaudio to QemuMutex
In reply to Jan KiszkaUsing the error management of QemuMutex allows to simplify the code.
--- audio/coreaudio.c | 56 +++++++--------------------------------------------- 1 files changed, 8 insertions(+), 48 deletions(-)
audio/coreaudio.c +8 -48
@@ -24,9 +24,9 @@#include <CoreAudio/CoreAudio.h> #include <string.h> /* strerror */ -#include <pthread.h> /* pthread_X */ #include "qemu-common.h" +#include "qemu-thread.h" #include "audio.h" #define AUDIO_CAP "coreaudio"
@@ -44,7 +44,7 @@ struct { typedef struct coreaudioVoiceOut { HWVoiceOut hw; - pthread_mutex_t mutex; + QemuMutex mutex; int isAtexit; AudioDeviceID outputDeviceID; UInt32 audioDevicePropertyBufferFrameSize;
@@ -164,40 +164,12 @@ static void coreaudio_atexit (void) conf.isAtexit =1 ; } -static int coreaudio_lock (coreaudioVoiceOut *core,const char *fn_name) -{ -int err; - - err =pthread_mutex_lock (&core->mutex); -if (err) { -dolog ("Could not lock voice for %s\nReason: %s\n" , - fn_name,strerror (err)); -return -1 ; - } -return 0 ; -} - -static int coreaudio_unlock (coreaudioVoiceOut *core,const char *fn_name) -{ -int err; - - err =pthread_mutex_unlock (&core->mutex); -if (err) { -dolog ("Could not unlock voice for %s\nReason: %s\n" , - fn_name,strerror (err)); -return -1 ; - } -return 0 ; -} -static int coreaudio_run_out (HWVoiceOut *hw,int live) {int decr;coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw; -if (coreaudio_lock (core,"coreaudio_run_out" )) { -return 0 ; - } +qemu_mutex_lock (&core->mutex);if (core->decr > live) { ldebug ("core->decr %d live %d core->live %d\n",
@@ -240,10 +212,7 @@ static OSStatus audioDeviceIOProc(#endif #endif -if (coreaudio_lock (core,"audioDeviceIOProc" )) { - inInputTime =0 ; -return 0 ; - } +qemu_mutex_lock (&core->mutex); frameCount = core->audioDevicePropertyBufferFrameSize; live = core->live;
@@ -251,7 +220,7 @@ static OSStatus audioDeviceIOProc(/* if there are not enough samples, set signal and return */ if (live < frameCount) { inInputTime =0 ; -coreaudio_unlock (core,"audioDeviceIOProc(empty)" ); +qemu_mutex_unlock (&core->mutex);return 0 ; }
@@ -278,7 +247,7 @@ static OSStatus audioDeviceIOProc( core->decr += frameCount; core->rpos = rpos; -coreaudio_unlock (core,"audioDeviceIOProc" ); +qemu_mutex_unlock (&core->mutex);return 0 ; }
@@ -296,12 +265,7 @@ static int coreaudio_init_out (HWVoiceOut *hw, struct audsettings *as)const char *typ ="playback" ;AudioValueRange frameRange; -/* create mutex */ - err =pthread_mutex_init (&core->mutex,NULL ); -if (err) { -dolog ("Could not create mutex\nReason: %s\n" ,strerror (err)); -return -1 ; - } +qemu_mutex_init (&core->mutex);audio_pcm_init_info (&hw->info, as);
@@ -461,11 +425,7 @@ static void coreaudio_fini_out (HWVoiceOut *hw) } core->outputDeviceID = kAudioDeviceUnknown; -/* destroy mutex */ - err =pthread_mutex_destroy (&core->mutex); -if (err) { -dolog ("Could not destroy mutex\nReason: %s\n" ,strerror (err)); - } +qemu_mutex_destroy (&core->mutex); }static int coreaudio_ctl_out (HWVoiceOut *hw,int cmd, ...)
Signature · 1 line
1.7.3.4
Re: [Qemu-devel] [PATCH 6/6] audio: Switch coreaudio to QemuMutex
Hello Jan,
Am 20.09.2011 um 18:53 schrieb Jan Kiszka:
Quoted 8 lines
Using the error management of QemuMutex allows to simplify the code.
CC malc <[email protected]>CC Andreas Färber <[email protected]>Signed-off-by Jan Kiszka <[email protected]>---
audio/coreaudio.c| 56 +++++++---------------------------------------------1 files changed, 8 insertions(+), 48 deletions(-)
You missed one coreaudio_unlock() occurrence in line 187. Other than that looks okay, with some more softfloat workarounds it compiles and doesn't noticeably regress on Darwin/i386 v10.6.8.
audio/coreaudio.c +1 -1
@@ -184,7 +184,7 @@ static int coreaudio_run_out (HWVoiceOut *hw, int live) core->live = live - decr; hw->rpos = core->rpos; -coreaudio_unlock (core,"coreaudio_run_out" ); +qemu_mutex_unlock (&core->mutex);return decr;
}
Do you have a particular test case? Any parameters needed? I've never used audio in my guests. ;)
Regards,
Andreas
Re: [Qemu-devel] [PATCH 6/6] audio: Switch coreaudio to QemuMutex
Quoted 29 lines · Andreas Färber
Hello Jan,
Am 20.09.2011 um 18:53 schrieb Jan Kiszka:
Quoted 8 lines
Using the error management of QemuMutex allows to simplify the code.
CC malc <[email protected]>CC Andreas Färber <[email protected]>Signed-off-by Jan Kiszka <[email protected]>---
audio/coreaudio.c| 56 +++++++---------------------------------------------1 files changed, 8 insertions(+), 48 deletions(-)You missed one
coreaudio_unlock()occurrence in line 187. Other than that looks okay, with some more softfloat workarounds it compiles and doesn't noticeably regress on Darwin/i386 v10.6.8.audio/coreaudio.c +1
-1@@ -184,7 +184,7 @@ static int coreaudio_run_out (HWVoiceOut *hw, int live) core->live = live - decr; hw->rpos = core->rpos; -coreaudio_unlock (core,"coreaudio_run_out" ); +qemu_mutex_unlock (&core->mutex);return decr; }
Quoted 1 line
Do you have a particular test case? Any parameters needed? I've never used audio in my guests. ;)
Nope, I hoped you had. :)
But I received indications that the implicit logging removal is not welcome. So I will likely refrain from touching the audio subsystem in the first step.
Thanks,
Jan
Signature · 2 lines
Siemens AG, Corporate Technology, CT T DE IT 1 Corporate Competence Center Embedded Linux