* [Qemu-devel] [PATCH 0/6] Spread the use of QEMU threading & locking API
@ 2011-09-20 16:53 Jan Kiszka
2011-09-20 16:53 ` [Qemu-devel] [PATCH 1/6] Enable joinable POSIX threads Jan Kiszka
` (5 more replies)
0 siblings, 6 replies; 17+ messages in thread
From: Jan Kiszka @ 2011-09-20 16:53 UTC (permalink / raw)
To: Anthony Liguori, qemu-devel
Cc: Kevin Wolf, Paolo Bonzini, Andreas Färber
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.
CC: Andreas Färber <andreas.faerber@web.de>
CC: Kevin Wolf <kwolf@redhat.com>
CC: malc <av1474@comtv.ru>
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(-)
--
1.7.3.4
^ permalink raw reply [flat|nested] 17+ messages in thread
* [Qemu-devel] [PATCH 1/6] Enable joinable POSIX threads
2011-09-20 16:53 [Qemu-devel] [PATCH 0/6] Spread the use of QEMU threading & locking API Jan Kiszka
@ 2011-09-20 16:53 ` Jan Kiszka
2011-09-21 7:16 ` Paolo Bonzini
2011-09-20 16:53 ` [Qemu-devel] [PATCH 2/6] Introduce qemu_cond_timedwait Jan Kiszka
` (4 subsequent siblings)
5 siblings, 1 reply; 17+ messages in thread
From: Jan Kiszka @ 2011-09-20 16:53 UTC (permalink / raw)
To: Anthony Liguori, qemu-devel; +Cc: Paolo Bonzini
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).
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
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(-)
diff --git a/cpus.c b/cpus.c
index d0cfe91..3f7724a 100644
--- a/cpus.c
+++ b/cpus.c
@@ -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);
}
diff --git a/hw/ccid-card-emulated.c b/hw/ccid-card-emulated.c
index 092301b..9fe9db5 100644
--- a/hw/ccid-card-emulated.c
+++ b/hw/ccid-card-emulated.c
@@ -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;
}
diff --git a/qemu-thread-posix.c b/qemu-thread-posix.c
index 2bd02ef..f76427e 100644
--- a/qemu-thread-posix.c
+++ b/qemu-thread-posix.c
@@ -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__);
+ }
+}
diff --git a/qemu-thread-posix.h b/qemu-thread-posix.h
index ee4618e..540fa0b 100644
--- a/qemu-thread-posix.h
+++ b/qemu-thread-posix.h
@@ -14,4 +14,7 @@ struct QemuThread {
pthread_t thread;
};
+/* only provided for posix so far */
+void qemu_thread_join(QemuThread *thread);
+
#endif
diff --git a/qemu-thread-win32.c b/qemu-thread-win32.c
index a27332e..4819ff4 100644
--- a/qemu-thread-win32.c
+++ b/qemu-thread-win32.c
@@ -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);
diff --git a/qemu-thread.h b/qemu-thread.h
index 0a73d50..aa1ae55 100644
--- a/qemu-thread.h
+++ b/qemu-thread.h
@@ -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);
diff --git a/ui/vnc-jobs-async.c b/ui/vnc-jobs-async.c
index de5ea6b..9b3016c 100644
--- a/ui/vnc-jobs-async.c
+++ b/ui/vnc-jobs-async.c
@@ -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 */
}
--
1.7.3.4
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [Qemu-devel] [PATCH 2/6] Introduce qemu_cond_timedwait
2011-09-20 16:53 [Qemu-devel] [PATCH 0/6] Spread the use of QEMU threading & locking API Jan Kiszka
2011-09-20 16:53 ` [Qemu-devel] [PATCH 1/6] Enable joinable POSIX threads Jan Kiszka
@ 2011-09-20 16:53 ` Jan Kiszka
2011-09-20 18:22 ` Paolo Bonzini
2011-09-20 16:53 ` [Qemu-devel] [PATCH 3/6] Switch POSIX compat AIO to QEMU abstractions Jan Kiszka
` (3 subsequent siblings)
5 siblings, 1 reply; 17+ messages in thread
From: Jan Kiszka @ 2011-09-20 16:53 UTC (permalink / raw)
To: Anthony Liguori, qemu-devel; +Cc: Paolo Bonzini
First user will be posix compat aio.
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
qemu-thread-posix.c | 22 ++++++++++++++++++++++
qemu-thread-win32.c | 16 +++++++++++++++-
qemu-thread.h | 2 ++
3 files changed, 39 insertions(+), 1 deletions(-)
diff --git a/qemu-thread-posix.c b/qemu-thread-posix.c
index f76427e..1d970fb 100644
--- a/qemu-thread-posix.c
+++ b/qemu-thread-posix.c
@@ -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)
diff --git a/qemu-thread-win32.c b/qemu-thread-win32.c
index 4819ff4..1b01a8b 100644
--- a/qemu-thread-win32.c
+++ b/qemu-thread-win32.c
@@ -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 {
diff --git a/qemu-thread.h b/qemu-thread.h
index aa1ae55..8be48e4 100644
--- a/qemu-thread.h
+++ b/qemu-thread.h
@@ -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 *),
--
1.7.3.4
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [Qemu-devel] [PATCH 3/6] Switch POSIX compat AIO to QEMU abstractions
2011-09-20 16:53 [Qemu-devel] [PATCH 0/6] Spread the use of QEMU threading & locking API Jan Kiszka
2011-09-20 16:53 ` [Qemu-devel] [PATCH 1/6] Enable joinable POSIX threads Jan Kiszka
2011-09-20 16:53 ` [Qemu-devel] [PATCH 2/6] Introduce qemu_cond_timedwait Jan Kiszka
@ 2011-09-20 16:53 ` Jan Kiszka
2011-09-21 13:57 ` Kevin Wolf
2011-09-20 16:53 ` [Qemu-devel] [PATCH 4/6] Switch compatfd to QEMU thread Jan Kiszka
` (2 subsequent siblings)
5 siblings, 1 reply; 17+ messages in thread
From: Jan Kiszka @ 2011-09-20 16:53 UTC (permalink / raw)
To: Anthony Liguori, qemu-devel; +Cc: Kevin Wolf, Paolo Bonzini
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 <kwolf@redhat.com>
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
posix-aio-compat.c | 115 ++++++++++++++-------------------------------------
1 files changed, 32 insertions(+), 83 deletions(-)
diff --git a/posix-aio-compat.c b/posix-aio-compat.c
index d3c1174..0715aba 100644
--- a/posix-aio-compat.c
+++ b/posix-aio-compat.c
@@ -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);
--
1.7.3.4
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [Qemu-devel] [PATCH 4/6] Switch compatfd to QEMU thread
2011-09-20 16:53 [Qemu-devel] [PATCH 0/6] Spread the use of QEMU threading & locking API Jan Kiszka
` (2 preceding siblings ...)
2011-09-20 16:53 ` [Qemu-devel] [PATCH 3/6] Switch POSIX compat AIO to QEMU abstractions Jan Kiszka
@ 2011-09-20 16:53 ` Jan Kiszka
2011-09-20 16:53 ` [Qemu-devel] [PATCH 5/6] audio: Use QEMU threads & synchronization Jan Kiszka
2011-09-20 16:53 ` [Qemu-devel] [PATCH 6/6] audio: Switch coreaudio to QemuMutex Jan Kiszka
5 siblings, 0 replies; 17+ messages in thread
From: Jan Kiszka @ 2011-09-20 16:53 UTC (permalink / raw)
To: Anthony Liguori, qemu-devel; +Cc: Paolo Bonzini
qemu_thread_create already does signal blocking and detaching for us.
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
compatfd.c | 16 +++-------------
1 files changed, 3 insertions(+), 13 deletions(-)
diff --git a/compatfd.c b/compatfd.c
index 31654c6..5431e4b 100644
--- a/compatfd.c
+++ b/compatfd.c
@@ -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_info
static 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];
}
--
1.7.3.4
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [Qemu-devel] [PATCH 5/6] audio: Use QEMU threads & synchronization
2011-09-20 16:53 [Qemu-devel] [PATCH 0/6] Spread the use of QEMU threading & locking API Jan Kiszka
` (3 preceding siblings ...)
2011-09-20 16:53 ` [Qemu-devel] [PATCH 4/6] Switch compatfd to QEMU thread Jan Kiszka
@ 2011-09-20 16:53 ` Jan Kiszka
2011-09-20 16:53 ` [Qemu-devel] [PATCH 6/6] audio: Switch coreaudio to QemuMutex Jan Kiszka
5 siblings, 0 replies; 17+ messages in thread
From: Jan Kiszka @ 2011-09-20 16:53 UTC (permalink / raw)
To: Anthony Liguori, qemu-devel; +Cc: Paolo Bonzini
This both simplifies error handling and enables central management of
threads and locks.
CC: malc <av1474@comtv.ru>
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
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(-)
diff --git a/audio/audio_pt_int.c b/audio/audio_pt_int.c
index 9a9c306..d47bd63 100644
--- a/audio/audio_pt_int.c
+++ b/audio/audio_pt_int.c
@@ -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);
}
diff --git a/audio/audio_pt_int.h b/audio/audio_pt_int.h
index 0dfff76..e395f7d 100644
--- a/audio/audio_pt_int.h
+++ b/audio/audio_pt_int.h
@@ -1,22 +1,41 @@
#ifndef QEMU_AUDIO_PT_INT_H
#define QEMU_AUDIO_PT_INT_H
-#include <pthread.h>
+#include "qemu-thread.h"
struct audio_pt {
- const char *drv;
- pthread_t thread;
- pthread_cond_t cond;
- pthread_mutex_t mutex;
+ QemuThread thread;
+ QemuCond cond;
+ QemuMutex mutex;
};
-int audio_pt_init (struct audio_pt *, void *(*) (void *), void *,
- const char *, const char *);
-int audio_pt_fini (struct audio_pt *, const char *);
-int audio_pt_lock (struct audio_pt *, const char *);
-int audio_pt_unlock (struct audio_pt *, const char *);
-int audio_pt_wait (struct audio_pt *, const char *);
-int audio_pt_unlock_and_signal (struct audio_pt *, const char *);
-int audio_pt_join (struct audio_pt *, void **, const char *);
+void audio_pt_init (struct audio_pt *, void *(*) (void *), void *);
+void audio_pt_fini (struct audio_pt *);
+
+static inline void audio_pt_lock (struct audio_pt *p)
+{
+ qemu_mutex_lock(&p->mutex);
+}
+
+static inline void audio_pt_unlock (struct audio_pt *p)
+{
+ qemu_mutex_unlock(&p->mutex);
+}
+
+static inline void audio_pt_wait (struct audio_pt *p)
+{
+ qemu_cond_wait(&p->cond, &p->mutex);
+}
+
+static inline void audio_pt_unlock_and_signal (struct audio_pt *p)
+{
+ qemu_mutex_unlock(&p->mutex);
+ qemu_cond_signal(&p->cond);
+}
+
+static inline void audio_pt_join (struct audio_pt *p)
+{
+ qemu_thread_join(&p->thread);
+}
#endif /* audio_pt_int.h */
diff --git a/audio/esdaudio.c b/audio/esdaudio.c
index bd6e1cc..fd1b25d 100644
--- a/audio/esdaudio.c
+++ b/audio/esdaudio.c
@@ -81,9 +81,7 @@ static void *qesd_thread_out (void *arg)
threshold = conf.divisor ? hw->samples / conf.divisor : 0;
- if (audio_pt_lock (&esd->pt, AUDIO_FUNC)) {
- return NULL;
- }
+ audio_pt_lock (&esd->pt);
for (;;) {
int decr, to_mix, rpos;
@@ -97,17 +95,13 @@ static void *qesd_thread_out (void *arg)
break;
}
- if (audio_pt_wait (&esd->pt, AUDIO_FUNC)) {
- goto exit;
- }
+ audio_pt_wait (&esd->pt);
}
decr = to_mix = esd->live;
rpos = hw->rpos;
- if (audio_pt_unlock (&esd->pt, AUDIO_FUNC)) {
- return NULL;
- }
+ audio_pt_unlock (&esd->pt);
while (to_mix) {
ssize_t written;
@@ -143,9 +137,7 @@ static void *qesd_thread_out (void *arg)
to_mix -= chunk;
}
- if (audio_pt_lock (&esd->pt, AUDIO_FUNC)) {
- return NULL;
- }
+ audio_pt_lock (&esd->pt);
esd->rpos = rpos;
esd->live -= decr;
@@ -153,7 +145,7 @@ static void *qesd_thread_out (void *arg)
}
exit:
- audio_pt_unlock (&esd->pt, AUDIO_FUNC);
+ audio_pt_unlock (&esd->pt);
return NULL;
}
@@ -162,19 +154,17 @@ static int qesd_run_out (HWVoiceOut *hw, int live)
int decr;
ESDVoiceOut *esd = (ESDVoiceOut *) hw;
- if (audio_pt_lock (&esd->pt, AUDIO_FUNC)) {
- return 0;
- }
+ audio_pt_lock (&esd->pt);
decr = audio_MIN (live, esd->decr);
esd->decr -= decr;
esd->live = live - decr;
hw->rpos = esd->rpos;
if (esd->live > 0) {
- audio_pt_unlock_and_signal (&esd->pt, AUDIO_FUNC);
+ audio_pt_unlock_and_signal (&esd->pt);
}
else {
- audio_pt_unlock (&esd->pt, AUDIO_FUNC);
+ audio_pt_unlock (&esd->pt);
}
return decr;
}
@@ -232,19 +222,10 @@ static int qesd_init_out (HWVoiceOut *hw, struct audsettings *as)
goto fail1;
}
- if (audio_pt_init (&esd->pt, qesd_thread_out, esd, AUDIO_CAP, AUDIO_FUNC)) {
- goto fail2;
- }
+ audio_pt_init (&esd->pt, qesd_thread_out, esd);
return 0;
- fail2:
- if (close (esd->fd)) {
- qesd_logerr (errno, "%s: close on esd socket(%d) failed\n",
- AUDIO_FUNC, esd->fd);
- }
- esd->fd = -1;
-
fail1:
g_free (esd->pcm_buf);
esd->pcm_buf = NULL;
@@ -253,13 +234,12 @@ static int qesd_init_out (HWVoiceOut *hw, struct audsettings *as)
static void qesd_fini_out (HWVoiceOut *hw)
{
- void *ret;
ESDVoiceOut *esd = (ESDVoiceOut *) hw;
- audio_pt_lock (&esd->pt, AUDIO_FUNC);
+ audio_pt_lock (&esd->pt);
esd->done = 1;
- audio_pt_unlock_and_signal (&esd->pt, AUDIO_FUNC);
- audio_pt_join (&esd->pt, &ret, AUDIO_FUNC);
+ audio_pt_unlock_and_signal (&esd->pt);
+ audio_pt_join (&esd->pt);
if (esd->fd >= 0) {
if (close (esd->fd)) {
@@ -268,7 +248,7 @@ static void qesd_fini_out (HWVoiceOut *hw)
esd->fd = -1;
}
- audio_pt_fini (&esd->pt, AUDIO_FUNC);
+ audio_pt_fini (&esd->pt);
g_free (esd->pcm_buf);
esd->pcm_buf = NULL;
@@ -290,9 +270,7 @@ static void *qesd_thread_in (void *arg)
threshold = conf.divisor ? hw->samples / conf.divisor : 0;
- if (audio_pt_lock (&esd->pt, AUDIO_FUNC)) {
- return NULL;
- }
+ audio_pt_lock (&esd->pt);
for (;;) {
int incr, to_grab, wpos;
@@ -306,17 +284,13 @@ static void *qesd_thread_in (void *arg)
break;
}
- if (audio_pt_wait (&esd->pt, AUDIO_FUNC)) {
- goto exit;
- }
+ audio_pt_wait (&esd->pt);
}
incr = to_grab = esd->dead;
wpos = hw->wpos;
- if (audio_pt_unlock (&esd->pt, AUDIO_FUNC)) {
- return NULL;
- }
+ audio_pt_unlock (&esd->pt);
while (to_grab) {
ssize_t nread;
@@ -351,9 +325,7 @@ static void *qesd_thread_in (void *arg)
to_grab -= chunk;
}
- if (audio_pt_lock (&esd->pt, AUDIO_FUNC)) {
- return NULL;
- }
+ audio_pt_lock (&esd->pt);
esd->wpos = wpos;
esd->dead -= incr;
@@ -361,7 +333,7 @@ static void *qesd_thread_in (void *arg)
}
exit:
- audio_pt_unlock (&esd->pt, AUDIO_FUNC);
+ audio_pt_unlock (&esd->pt);
return NULL;
}
@@ -370,9 +342,7 @@ static int qesd_run_in (HWVoiceIn *hw)
int live, incr, dead;
ESDVoiceIn *esd = (ESDVoiceIn *) hw;
- if (audio_pt_lock (&esd->pt, AUDIO_FUNC)) {
- return 0;
- }
+ audio_pt_lock (&esd->pt);
live = audio_pcm_hw_get_live_in (hw);
dead = hw->samples - live;
@@ -381,10 +351,10 @@ static int qesd_run_in (HWVoiceIn *hw)
esd->dead = dead - incr;
hw->wpos = esd->wpos;
if (esd->dead > 0) {
- audio_pt_unlock_and_signal (&esd->pt, AUDIO_FUNC);
+ audio_pt_unlock_and_signal (&esd->pt);
}
else {
- audio_pt_unlock (&esd->pt, AUDIO_FUNC);
+ audio_pt_unlock (&esd->pt);
}
return incr;
}
@@ -439,19 +409,10 @@ static int qesd_init_in (HWVoiceIn *hw, struct audsettings *as)
goto fail1;
}
- if (audio_pt_init (&esd->pt, qesd_thread_in, esd, AUDIO_CAP, AUDIO_FUNC)) {
- goto fail2;
- }
+ audio_pt_init (&esd->pt, qesd_thread_in, esd);
return 0;
- fail2:
- if (close (esd->fd)) {
- qesd_logerr (errno, "%s: close on esd socket(%d) failed\n",
- AUDIO_FUNC, esd->fd);
- }
- esd->fd = -1;
-
fail1:
g_free (esd->pcm_buf);
esd->pcm_buf = NULL;
@@ -460,13 +421,12 @@ static int qesd_init_in (HWVoiceIn *hw, struct audsettings *as)
static void qesd_fini_in (HWVoiceIn *hw)
{
- void *ret;
ESDVoiceIn *esd = (ESDVoiceIn *) hw;
- audio_pt_lock (&esd->pt, AUDIO_FUNC);
+ audio_pt_lock (&esd->pt);
esd->done = 1;
- audio_pt_unlock_and_signal (&esd->pt, AUDIO_FUNC);
- audio_pt_join (&esd->pt, &ret, AUDIO_FUNC);
+ audio_pt_unlock_and_signal (&esd->pt);
+ audio_pt_join (&esd->pt);
if (esd->fd >= 0) {
if (close (esd->fd)) {
@@ -475,7 +435,7 @@ static void qesd_fini_in (HWVoiceIn *hw)
esd->fd = -1;
}
- audio_pt_fini (&esd->pt, AUDIO_FUNC);
+ audio_pt_fini (&esd->pt);
g_free (esd->pcm_buf);
esd->pcm_buf = NULL;
diff --git a/audio/paaudio.c b/audio/paaudio.c
index d1f3912..b539a72 100644
--- a/audio/paaudio.c
+++ b/audio/paaudio.c
@@ -56,9 +56,7 @@ static void *qpa_thread_out (void *arg)
PAVoiceOut *pa = arg;
HWVoiceOut *hw = &pa->hw;
- if (audio_pt_lock (&pa->pt, AUDIO_FUNC)) {
- return NULL;
- }
+ audio_pt_lock (&pa->pt);
for (;;) {
int decr, to_mix, rpos;
@@ -72,17 +70,13 @@ static void *qpa_thread_out (void *arg)
break;
}
- if (audio_pt_wait (&pa->pt, AUDIO_FUNC)) {
- goto exit;
- }
+ audio_pt_wait (&pa->pt);
}
decr = to_mix = audio_MIN (pa->live, conf.samples >> 2);
rpos = pa->rpos;
- if (audio_pt_unlock (&pa->pt, AUDIO_FUNC)) {
- return NULL;
- }
+ audio_pt_unlock (&pa->pt);
while (to_mix) {
int error;
@@ -101,9 +95,7 @@ static void *qpa_thread_out (void *arg)
to_mix -= chunk;
}
- if (audio_pt_lock (&pa->pt, AUDIO_FUNC)) {
- return NULL;
- }
+ audio_pt_lock (&pa->pt);
pa->rpos = rpos;
pa->live -= decr;
@@ -111,7 +103,7 @@ static void *qpa_thread_out (void *arg)
}
exit:
- audio_pt_unlock (&pa->pt, AUDIO_FUNC);
+ audio_pt_unlock (&pa->pt);
return NULL;
}
@@ -120,19 +112,17 @@ static int qpa_run_out (HWVoiceOut *hw, int live)
int decr;
PAVoiceOut *pa = (PAVoiceOut *) hw;
- if (audio_pt_lock (&pa->pt, AUDIO_FUNC)) {
- return 0;
- }
+ audio_pt_lock (&pa->pt);
decr = audio_MIN (live, pa->decr);
pa->decr -= decr;
pa->live = live - decr;
hw->rpos = pa->rpos;
if (pa->live > 0) {
- audio_pt_unlock_and_signal (&pa->pt, AUDIO_FUNC);
+ audio_pt_unlock_and_signal (&pa->pt);
}
else {
- audio_pt_unlock (&pa->pt, AUDIO_FUNC);
+ audio_pt_unlock (&pa->pt);
}
return decr;
}
@@ -148,9 +138,7 @@ static void *qpa_thread_in (void *arg)
PAVoiceIn *pa = arg;
HWVoiceIn *hw = &pa->hw;
- if (audio_pt_lock (&pa->pt, AUDIO_FUNC)) {
- return NULL;
- }
+ audio_pt_lock (&pa->pt);
for (;;) {
int incr, to_grab, wpos;
@@ -164,17 +152,13 @@ static void *qpa_thread_in (void *arg)
break;
}
- if (audio_pt_wait (&pa->pt, AUDIO_FUNC)) {
- goto exit;
- }
+ audio_pt_wait (&pa->pt);
}
incr = to_grab = audio_MIN (pa->dead, conf.samples >> 2);
wpos = pa->wpos;
- if (audio_pt_unlock (&pa->pt, AUDIO_FUNC)) {
- return NULL;
- }
+ audio_pt_unlock (&pa->pt);
while (to_grab) {
int error;
@@ -192,9 +176,7 @@ static void *qpa_thread_in (void *arg)
to_grab -= chunk;
}
- if (audio_pt_lock (&pa->pt, AUDIO_FUNC)) {
- return NULL;
- }
+ audio_pt_lock (&pa->pt);
pa->wpos = wpos;
pa->dead -= incr;
@@ -202,7 +184,7 @@ static void *qpa_thread_in (void *arg)
}
exit:
- audio_pt_unlock (&pa->pt, AUDIO_FUNC);
+ audio_pt_unlock (&pa->pt);
return NULL;
}
@@ -211,9 +193,7 @@ static int qpa_run_in (HWVoiceIn *hw)
int live, incr, dead;
PAVoiceIn *pa = (PAVoiceIn *) hw;
- if (audio_pt_lock (&pa->pt, AUDIO_FUNC)) {
- return 0;
- }
+ audio_pt_lock (&pa->pt);
live = audio_pcm_hw_get_live_in (hw);
dead = hw->samples - live;
@@ -222,10 +202,10 @@ static int qpa_run_in (HWVoiceIn *hw)
pa->dead = dead - incr;
hw->wpos = pa->wpos;
if (pa->dead > 0) {
- audio_pt_unlock_and_signal (&pa->pt, AUDIO_FUNC);
+ audio_pt_unlock_and_signal (&pa->pt);
}
else {
- audio_pt_unlock (&pa->pt, AUDIO_FUNC);
+ audio_pt_unlock (&pa->pt);
}
return incr;
}
@@ -332,15 +312,10 @@ static int qpa_init_out (HWVoiceOut *hw, struct audsettings *as)
goto fail2;
}
- if (audio_pt_init (&pa->pt, qpa_thread_out, hw, AUDIO_CAP, AUDIO_FUNC)) {
- goto fail3;
- }
+ audio_pt_init (&pa->pt, qpa_thread_out, hw);
return 0;
- fail3:
- g_free (pa->pcm_buf);
- pa->pcm_buf = NULL;
fail2:
pa_simple_free (pa->s);
pa->s = NULL;
@@ -387,15 +362,10 @@ static int qpa_init_in (HWVoiceIn *hw, struct audsettings *as)
goto fail2;
}
- if (audio_pt_init (&pa->pt, qpa_thread_in, hw, AUDIO_CAP, AUDIO_FUNC)) {
- goto fail3;
- }
+ audio_pt_init (&pa->pt, qpa_thread_in, hw);
return 0;
- fail3:
- g_free (pa->pcm_buf);
- pa->pcm_buf = NULL;
fail2:
pa_simple_free (pa->s);
pa->s = NULL;
@@ -405,40 +375,38 @@ static int qpa_init_in (HWVoiceIn *hw, struct audsettings *as)
static void qpa_fini_out (HWVoiceOut *hw)
{
- void *ret;
PAVoiceOut *pa = (PAVoiceOut *) hw;
- audio_pt_lock (&pa->pt, AUDIO_FUNC);
+ audio_pt_lock (&pa->pt);
pa->done = 1;
- audio_pt_unlock_and_signal (&pa->pt, AUDIO_FUNC);
- audio_pt_join (&pa->pt, &ret, AUDIO_FUNC);
+ audio_pt_unlock_and_signal (&pa->pt);
+ audio_pt_join (&pa->pt);
if (pa->s) {
pa_simple_free (pa->s);
pa->s = NULL;
}
- audio_pt_fini (&pa->pt, AUDIO_FUNC);
+ audio_pt_fini (&pa->pt);
g_free (pa->pcm_buf);
pa->pcm_buf = NULL;
}
static void qpa_fini_in (HWVoiceIn *hw)
{
- void *ret;
PAVoiceIn *pa = (PAVoiceIn *) hw;
- audio_pt_lock (&pa->pt, AUDIO_FUNC);
+ audio_pt_lock (&pa->pt);
pa->done = 1;
- audio_pt_unlock_and_signal (&pa->pt, AUDIO_FUNC);
- audio_pt_join (&pa->pt, &ret, AUDIO_FUNC);
+ audio_pt_unlock_and_signal (&pa->pt);
+ audio_pt_join (&pa->pt);
if (pa->s) {
pa_simple_free (pa->s);
pa->s = NULL;
}
- audio_pt_fini (&pa->pt, AUDIO_FUNC);
+ audio_pt_fini (&pa->pt);
g_free (pa->pcm_buf);
pa->pcm_buf = NULL;
}
--
1.7.3.4
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [Qemu-devel] [PATCH 6/6] audio: Switch coreaudio to QemuMutex
2011-09-20 16:53 [Qemu-devel] [PATCH 0/6] Spread the use of QEMU threading & locking API Jan Kiszka
` (4 preceding siblings ...)
2011-09-20 16:53 ` [Qemu-devel] [PATCH 5/6] audio: Use QEMU threads & synchronization Jan Kiszka
@ 2011-09-20 16:53 ` Jan Kiszka
2011-09-26 7:58 ` Andreas Färber
5 siblings, 1 reply; 17+ messages in thread
From: Jan Kiszka @ 2011-09-20 16:53 UTC (permalink / raw)
To: Anthony Liguori, qemu-devel; +Cc: Paolo Bonzini, Andreas Färber
Using the error management of QemuMutex allows to simplify the code.
CC: malc <av1474@comtv.ru>
CC: Andreas Färber <andreas.faerber@web.de>
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
audio/coreaudio.c | 56 +++++++---------------------------------------------
1 files changed, 8 insertions(+), 48 deletions(-)
diff --git a/audio/coreaudio.c b/audio/coreaudio.c
index 5964c62..c34a593 100644
--- a/audio/coreaudio.c
+++ b/audio/coreaudio.c
@@ -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, ...)
--
1.7.3.4
^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [Qemu-devel] [PATCH 2/6] Introduce qemu_cond_timedwait
2011-09-20 16:53 ` [Qemu-devel] [PATCH 2/6] Introduce qemu_cond_timedwait Jan Kiszka
@ 2011-09-20 18:22 ` Paolo Bonzini
2011-09-20 19:02 ` [Qemu-devel] [PATCH v2 2/6] Introduce qemu_cond_timedwait for POSIX Jan Kiszka
0 siblings, 1 reply; 17+ messages in thread
From: Paolo Bonzini @ 2011-09-20 18:22 UTC (permalink / raw)
To: Jan Kiszka; +Cc: Anthony Liguori, qemu-devel
On 09/20/2011 06:53 PM, Jan Kiszka wrote:
> First user will be posix compat aio.
>
> Signed-off-by: Jan Kiszka<jan.kiszka@siemens.com>
I'm pretty sure the win32 version is not thread-safe, but posix compat
aio is currently POSIX only. Just leave it out.
Paolo
^ permalink raw reply [flat|nested] 17+ messages in thread
* [Qemu-devel] [PATCH v2 2/6] Introduce qemu_cond_timedwait for POSIX
2011-09-20 18:22 ` Paolo Bonzini
@ 2011-09-20 19:02 ` Jan Kiszka
0 siblings, 0 replies; 17+ messages in thread
From: Jan Kiszka @ 2011-09-20 19:02 UTC (permalink / raw)
To: Paolo Bonzini; +Cc: Anthony Liguori, qemu-devel
On 2011-09-20 20:22, Paolo Bonzini wrote:
> On 09/20/2011 06:53 PM, Jan Kiszka wrote:
>> First user will be posix compat aio.
>>
>> Signed-off-by: Jan Kiszka<jan.kiszka@siemens.com>
>
> I'm pretty sure the win32 version is not thread-safe,
Yeah, I would even say it's completely broken. Was a naive hack.
> but posix compat
> aio is currently POSIX only. Just leave it out.
>
-------8<-------
From: Jan Kiszka <jan.kiszka@siemens.com>
First user will be POSIX compat aio. Windows use cases aren't in sight,
so this remains a POSIX-only service for now.
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
qemu-thread-posix.c | 22 ++++++++++++++++++++++
qemu-thread-posix.h | 2 ++
2 files changed, 24 insertions(+), 0 deletions(-)
diff --git a/qemu-thread-posix.c b/qemu-thread-posix.c
index f76427e..1d970fb 100644
--- a/qemu-thread-posix.c
+++ b/qemu-thread-posix.c
@@ -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)
diff --git a/qemu-thread-posix.h b/qemu-thread-posix.h
index 540fa0b..b4ae5ad 100644
--- a/qemu-thread-posix.h
+++ b/qemu-thread-posix.h
@@ -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
^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [Qemu-devel] [PATCH 1/6] Enable joinable POSIX threads
2011-09-20 16:53 ` [Qemu-devel] [PATCH 1/6] Enable joinable POSIX threads Jan Kiszka
@ 2011-09-21 7:16 ` Paolo Bonzini
2011-09-21 13:40 ` Kevin Wolf
0 siblings, 1 reply; 17+ messages in thread
From: Paolo Bonzini @ 2011-09-21 7:16 UTC (permalink / raw)
To: Jan Kiszka; +Cc: Anthony Liguori, Alon Levy, qemu-devel
On 09/20/2011 06:53 PM, Jan Kiszka wrote:
> - 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
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [Qemu-devel] [PATCH 1/6] Enable joinable POSIX threads
2011-09-21 13:40 ` Kevin Wolf
@ 2011-09-21 13:38 ` Paolo Bonzini
0 siblings, 0 replies; 17+ messages in thread
From: Paolo Bonzini @ 2011-09-21 13:38 UTC (permalink / raw)
To: Kevin Wolf; +Cc: Jan Kiszka, Anthony Liguori, Alon Levy, qemu-devel
On 09/21/2011 03:40 PM, Kevin Wolf wrote:
>> >
>> > 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
>> >
>> > Reviewed-by: Paolo Bonzini<pbonzini@redhat.com>
> 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
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [Qemu-devel] [PATCH 1/6] Enable joinable POSIX threads
2011-09-21 7:16 ` Paolo Bonzini
@ 2011-09-21 13:40 ` Kevin Wolf
2011-09-21 13:38 ` Paolo Bonzini
0 siblings, 1 reply; 17+ messages in thread
From: Kevin Wolf @ 2011-09-21 13:40 UTC (permalink / raw)
To: Paolo Bonzini; +Cc: Jan Kiszka, Anthony Liguori, Alon Levy, qemu-devel
Am 21.09.2011 09:16, schrieb Paolo Bonzini:
> On 09/20/2011 06:53 PM, Jan Kiszka wrote:
>> - 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
>
> Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Actually, the man page says that joinable is the default, so this patch
does change the behaviour.
Kevin
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [Qemu-devel] [PATCH 3/6] Switch POSIX compat AIO to QEMU abstractions
2011-09-20 16:53 ` [Qemu-devel] [PATCH 3/6] Switch POSIX compat AIO to QEMU abstractions Jan Kiszka
@ 2011-09-21 13:57 ` Kevin Wolf
2011-09-21 14:02 ` Jan Kiszka
0 siblings, 1 reply; 17+ messages in thread
From: Kevin Wolf @ 2011-09-21 13:57 UTC (permalink / raw)
To: Jan Kiszka; +Cc: Paolo Bonzini, Anthony Liguori, qemu-devel
Am 20.09.2011 18:53, schrieb Jan Kiszka:
> 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 <kwolf@redhat.com>
> Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
> ---
> posix-aio-compat.c | 115 ++++++++++++++-------------------------------------
> 1 files changed, 32 insertions(+), 83 deletions(-)
>
> diff --git a/posix-aio-compat.c b/posix-aio-compat.c
> index d3c1174..0715aba 100644
> --- a/posix-aio-compat.c
> +++ b/posix-aio-compat.c
> @@ -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;
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
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [Qemu-devel] [PATCH 3/6] Switch POSIX compat AIO to QEMU abstractions
2011-09-21 13:57 ` Kevin Wolf
@ 2011-09-21 14:02 ` Jan Kiszka
2011-09-21 14:11 ` Kevin Wolf
0 siblings, 1 reply; 17+ messages in thread
From: Jan Kiszka @ 2011-09-21 14:02 UTC (permalink / raw)
To: Kevin Wolf; +Cc: Paolo Bonzini, Anthony Liguori, qemu-devel@nongnu.org
On 2011-09-21 15:57, Kevin Wolf wrote:
> Am 20.09.2011 18:53, schrieb Jan Kiszka:
>> 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 <kwolf@redhat.com>
>> Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
>> ---
>> posix-aio-compat.c | 115 ++++++++++++++-------------------------------------
>> 1 files changed, 32 insertions(+), 83 deletions(-)
>>
>> diff --git a/posix-aio-compat.c b/posix-aio-compat.c
>> index d3c1174..0715aba 100644
>> --- a/posix-aio-compat.c
>> +++ b/posix-aio-compat.c
>> @@ -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;
>
> 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.
>
> + 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).
Will switch to a bool return code (and document it).
Thanks,
Jan
--
Siemens AG, Corporate Technology, CT T DE IT 1
Corporate Competence Center Embedded Linux
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [Qemu-devel] [PATCH 3/6] Switch POSIX compat AIO to QEMU abstractions
2011-09-21 14:02 ` Jan Kiszka
@ 2011-09-21 14:11 ` Kevin Wolf
0 siblings, 0 replies; 17+ messages in thread
From: Kevin Wolf @ 2011-09-21 14:11 UTC (permalink / raw)
To: Jan Kiszka; +Cc: Paolo Bonzini, Anthony Liguori, qemu-devel@nongnu.org
Am 21.09.2011 16:02, schrieb Jan Kiszka:
> On 2011-09-21 15:57, Kevin Wolf wrote:
>> Am 20.09.2011 18:53, schrieb Jan Kiszka:
>>> 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 <kwolf@redhat.com>
>>> Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
>>> ---
>>> posix-aio-compat.c | 115 ++++++++++++++-------------------------------------
>>> 1 files changed, 32 insertions(+), 83 deletions(-)
>>> @@ -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;
>>
>> 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.
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;
>> + 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).
>
> Will switch to a bool return code (and document it).
Ok.
Kevin
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [Qemu-devel] [PATCH 6/6] audio: Switch coreaudio to QemuMutex
2011-09-20 16:53 ` [Qemu-devel] [PATCH 6/6] audio: Switch coreaudio to QemuMutex Jan Kiszka
@ 2011-09-26 7:58 ` Andreas Färber
2011-09-26 8:06 ` Jan Kiszka
0 siblings, 1 reply; 17+ messages in thread
From: Andreas Färber @ 2011-09-26 7:58 UTC (permalink / raw)
To: Jan Kiszka; +Cc: Paolo Bonzini, Anthony Liguori, qemu-devel
Hello Jan,
Am 20.09.2011 um 18:53 schrieb Jan Kiszka:
> Using the error management of QemuMutex allows to simplify the code.
>
> CC: malc <av1474@comtv.ru>
> CC: Andreas Färber <andreas.faerber@web.de>
> Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
> ---
> 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.
diff --git a/audio/coreaudio.c b/audio/coreaudio.c
index c34a593..1cb3fce 100644
--- a/audio/coreaudio.c
+++ b/audio/coreaudio.c
@@ -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
^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [Qemu-devel] [PATCH 6/6] audio: Switch coreaudio to QemuMutex
2011-09-26 7:58 ` Andreas Färber
@ 2011-09-26 8:06 ` Jan Kiszka
0 siblings, 0 replies; 17+ messages in thread
From: Jan Kiszka @ 2011-09-26 8:06 UTC (permalink / raw)
To: Andreas Färber; +Cc: Paolo Bonzini, Anthony Liguori, qemu-devel@nongnu.org
On 2011-09-26 09:58, Andreas Färber wrote:
> Hello Jan,
>
> Am 20.09.2011 um 18:53 schrieb Jan Kiszka:
>
>> Using the error management of QemuMutex allows to simplify the code.
>>
>> CC: malc <av1474@comtv.ru>
>> CC: Andreas Färber <andreas.faerber@web.de>
>> Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
>> ---
>> 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.
>
> diff --git a/audio/coreaudio.c b/audio/coreaudio.c
> index c34a593..1cb3fce 100644
> --- a/audio/coreaudio.c
> +++ b/audio/coreaudio.c
> @@ -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. ;)
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
--
Siemens AG, Corporate Technology, CT T DE IT 1
Corporate Competence Center Embedded Linux
^ permalink raw reply [flat|nested] 17+ messages in thread
end of thread, other threads:[~2011-09-26 8:06 UTC | newest]
Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-09-20 16:53 [Qemu-devel] [PATCH 0/6] Spread the use of QEMU threading & locking API Jan Kiszka
2011-09-20 16:53 ` [Qemu-devel] [PATCH 1/6] Enable joinable POSIX threads Jan Kiszka
2011-09-21 7:16 ` Paolo Bonzini
2011-09-21 13:40 ` Kevin Wolf
2011-09-21 13:38 ` Paolo Bonzini
2011-09-20 16:53 ` [Qemu-devel] [PATCH 2/6] Introduce qemu_cond_timedwait Jan Kiszka
2011-09-20 18:22 ` Paolo Bonzini
2011-09-20 19:02 ` [Qemu-devel] [PATCH v2 2/6] Introduce qemu_cond_timedwait for POSIX Jan Kiszka
2011-09-20 16:53 ` [Qemu-devel] [PATCH 3/6] Switch POSIX compat AIO to QEMU abstractions Jan Kiszka
2011-09-21 13:57 ` Kevin Wolf
2011-09-21 14:02 ` Jan Kiszka
2011-09-21 14:11 ` Kevin Wolf
2011-09-20 16:53 ` [Qemu-devel] [PATCH 4/6] Switch compatfd to QEMU thread Jan Kiszka
2011-09-20 16:53 ` [Qemu-devel] [PATCH 5/6] audio: Use QEMU threads & synchronization Jan Kiszka
2011-09-20 16:53 ` [Qemu-devel] [PATCH 6/6] audio: Switch coreaudio to QemuMutex Jan Kiszka
2011-09-26 7:58 ` Andreas Färber
2011-09-26 8:06 ` Jan Kiszka
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).