Skip to contentSkip to conversation

Spread the use of QEMU threading & locking API

PATCH In review Jan Kiszka 5 participants 17 messages Sep 20, 2011 – Sep 26, 2011

lore
Share & tools
lore

Jan Kiszka

author
#0 lore raw

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.

CC Andreas Färber <[email protected]>
CC Kevin Wolf <[email protected]>

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
author
#1 lore raw

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
index d0cfe91..3f7724a 100644
@@ -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
index 092301b..9fe9db5 100644
@@ -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
index 2bd02ef..f76427e 100644
@@ -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
index ee4618e..540fa0b 100644
@@ -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
index a27332e..4819ff4 100644
@@ -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
index 0a73d50..aa1ae55 100644
@@ -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
index de5ea6b..9b3016c 100644
@@ -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
Reviewed-by on v1 1/6
#2 lore raw

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

#3 lore raw

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_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

Actually, the man page says that joinable is the default, so this patch does change the behaviour.

Kevin

#4 lore raw

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_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

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

author
#5 lore raw

PATCH 2/6 Introduce qemu_cond_timedwait

In reply to Jan Kiszka

First 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
index f76427e..1d970fb 100644
@@ -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
index 4819ff4..1b01a8b 100644
@@ -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
index aa1ae55..8be48e4 100644
@@ -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
#6 lore raw

Re: [Qemu-devel] [PATCH 2/6] Introduce qemu_cond_timedwait

Quoted 3 lines · Jan Kiszka

First user will be posix compat aio.

I'm pretty sure the win32 version is not thread-safe, but posix compat aio is currently POSIX only. Just leave it out.

Paolo

#7 lore raw

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.

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
index f76427e..1d970fb 100644
@@ -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
index 540fa0b..b4ae5ad 100644
@@ -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
author
#8 lore raw

PATCH 3/6 Switch POSIX compat AIO to QEMU abstractions

In reply to 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).

---
 posix-aio-compat.c |  115 ++++++++++++++-------------------------------------
 1 files changed, 32 insertions(+), 83 deletions(-)
posix-aio-compat.c +32 -83
index d3c1174..0715aba 100644
@@ -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
#9 lore raw

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).

---
 posix-aio-compat.c |  115 ++++++++++++++-------------------------------------
 1 files changed, 32 insertions(+), 83 deletions(-)
posix-aio-compat.c +10 -47
index d3c1174..0715aba 100644
@@ -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

author
#10 lore raw

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).

---
 posix-aio-compat.c |  115 ++++++++++++++-------------------------------------
 1 files changed, 32 insertions(+), 83 deletions(-)
posix-aio-compat.c +11 -48
index d3c1174..0715aba 100644
@@ -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_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

Signature · 2 lines
Siemens AG, Corporate Technology, CT T DE IT 1
Corporate Competence Center Embedded Linux
#11 lore raw

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).

---
 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_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

author
#12 lore raw

PATCH 4/6 Switch compatfd to QEMU thread

In reply to Jan Kiszka

qemu_thread_create already does signal blocking and detaching for us.

---
 compatfd.c |   16 +++-------------
 1 files changed, 3 insertions(+), 13 deletions(-)
compatfd.c +3 -13
index 31654c6..5431e4b 100644
@@ -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];
 }
Signature · 1 line
1.7.3.4
author
#13 lore raw

PATCH 5/6 audio: Use QEMU threads & synchronization

In reply to Jan Kiszka

This 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
index 9a9c306..d47bd63 100644
@@ -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
author
#14 lore raw

PATCH 6/6 audio: Switch coreaudio to QemuMutex

In reply to Jan Kiszka

Using the error management of QemuMutex allows to simplify the code.

CC Andreas Färber <[email protected]>
---
 audio/coreaudio.c |   56 +++++++---------------------------------------------
 1 files changed, 8 insertions(+), 48 deletions(-)
audio/coreaudio.c +8 -48
index 5964c62..c34a593 100644
@@ -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
#15 lore raw

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 Andreas Färber <[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
index c34a593..1cb3fce 100644
@@ -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

author
#16 lore raw

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 Andreas Färber <[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
index c34a593..1cb3fce 100644
@@ -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