qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [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).