Patchwork qemu-thread: Introduce qemu_cond_timedwait for POSIX

login
register
mail settings
Submitter Jan Kiszka
Date July 16, 2012, 12:01 p.m.
Message ID <50040293.1000005@siemens.com>
Download mbox | patch
Permalink /patch/171175/
State New
Headers show

Comments

Jan Kiszka - July 16, 2012, 12:01 p.m.
First user will be POSIX compat aio. Windows use cases aren't in sight,
so this remains a POSIX-only service for now.

This version uses CLOCK_MONOTONIC for the timeout to avoid jumps on wall
clock adjustments, provided the host support pthread_condattr_setclock.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 configure           |   21 +++++++++++++++++++++
 qemu-thread-posix.c |   46 +++++++++++++++++++++++++++++++++++++++++++++-
 qemu-thread-posix.h |    5 +++++
 3 files changed, 71 insertions(+), 1 deletions(-)

Patch

diff --git a/configure b/configure
index 0a3896e..dec39c8 100755
--- a/configure
+++ b/configure
@@ -2135,6 +2135,23 @@  if test "$mingw32" != yes -a "$pthread" = no; then
 fi
 
 ##########################################
+# pthread_condattr_setclock probe
+condattr_setclock="no"
+if test "pthread" != "no" ; then
+  cat > $TMPC << EOF
+#include <pthread.h>
+int main(void) {
+  pthread_condattr_t attr;
+  pthread_condattr_init(&attr);
+  return pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
+}
+EOF
+  if compile_prog "" "$LIBS" && $TMPE; then
+    condattr_setclock="yes"
+  fi
+fi
+
+##########################################
 # rbd probe
 if test "$rbd" != "no" ; then
   cat > $TMPC <<EOF
@@ -3040,6 +3057,7 @@  echo "preadv support    $preadv"
 echo "fdatasync         $fdatasync"
 echo "madvise           $madvise"
 echo "posix_madvise     $posix_madvise"
+echo "condattr_setclock $condattr_setclock"
 echo "uuid support      $uuid"
 echo "libcap-ng support $cap_ng"
 echo "vhost-net support $vhost_net"
@@ -3324,6 +3342,9 @@  fi
 if test "$posix_madvise" = "yes" ; then
   echo "CONFIG_POSIX_MADVISE=y" >> $config_host_mak
 fi
+if test "$condattr_setclock" = "yes" ; then
+  echo "CONFIG_CONDATTR_SETCLOCK=y" >> $config_host_mak
+fi
 
 if test "$spice" = "yes" ; then
   echo "CONFIG_SPICE=y" >> $config_host_mak
diff --git a/qemu-thread-posix.c b/qemu-thread-posix.c
index 9e1b5fb..ed6ab06 100644
--- a/qemu-thread-posix.c
+++ b/qemu-thread-posix.c
@@ -17,6 +17,8 @@ 
 #include <signal.h>
 #include <stdint.h>
 #include <string.h>
+#include <sys/time.h>
+#include "config-host.h"
 #include "qemu-thread.h"
 
 static void error_exit(int err, const char *msg)
@@ -73,8 +75,20 @@  void qemu_mutex_unlock(QemuMutex *mutex)
 void qemu_cond_init(QemuCond *cond)
 {
     int err;
+    pthread_condattr_t attr;
 
-    err = pthread_cond_init(&cond->cond, NULL);
+    err = pthread_condattr_init(&attr);
+    if (err) {
+        error_exit(err, __func__);
+    }
+#ifdef CONFIG_CONDATTR_SETCLOCK
+    err = pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
+    if (err) {
+        error_exit(err, __func__);
+    }
+#endif
+
+    err = pthread_cond_init(&cond->cond, &attr);
     if (err)
         error_exit(err, __func__);
 }
@@ -115,6 +129,36 @@  void qemu_cond_wait(QemuCond *cond, QemuMutex *mutex)
         error_exit(err, __func__);
 }
 
+/* Returns true if condition was signals, false if timed out. */
+bool qemu_cond_timedwait(QemuCond *cond, QemuMutex *mutex,
+                         unsigned int timeout_ms)
+{
+    struct timespec ts;
+    int err;
+
+#ifdef CONFIG_CONDATTR_SETCLOCK
+    clock_gettime(CLOCK_MONOTONIC, &ts);
+#else
+    struct timeval tv;
+
+    gettimeofday(&tv, NULL);
+    ts.tv_sec = tv.tv_sec;
+    ts.tv_nsec = tv.tv_usec * 1000;
+#endif
+
+    ts.tv_sec += timeout_ms / 1000;
+    ts.tv_nsec += (timeout_ms % 1000) * 1000000;
+    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 ee4618e..9f00524 100644
--- a/qemu-thread-posix.h
+++ b/qemu-thread-posix.h
@@ -1,5 +1,6 @@ 
 #ifndef __QEMU_THREAD_POSIX_H
 #define __QEMU_THREAD_POSIX_H 1
+#include <stdbool.h>
 #include "pthread.h"
 
 struct QemuMutex {
@@ -14,4 +15,8 @@  struct QemuThread {
     pthread_t thread;
 };
 
+/* only provided for posix so far */
+bool qemu_cond_timedwait(QemuCond *cond, QemuMutex *mutex,
+                         unsigned int timeout_ms);
+
 #endif