All of lore.kernel.org
 help / color / mirror / Atom feed
From: Paolo Bonzini <pbonzini@redhat.com>
To: qemu-devel@nongnu.org
Cc: Yury Kotov <yury-kotov@yandex-team.ru>
Subject: [Qemu-devel] [PULL 13/29] qemu-thread: Add qemu_cond_timedwait
Date: Mon, 16 Sep 2019 16:41:53 +0200	[thread overview]
Message-ID: <1568644929-9124-14-git-send-email-pbonzini@redhat.com> (raw)
In-Reply-To: <1568644929-9124-1-git-send-email-pbonzini@redhat.com>

From: Yury Kotov <yury-kotov@yandex-team.ru>

The new function is needed to implement conditional sleep for CPU
throttling. It's possible to reuse qemu_sem_timedwait, but it's more
difficult than just add qemu_cond_timedwait.

Also moved compute_abs_deadline function up the code to reuse it in
qemu_cond_timedwait_impl win32.

Signed-off-by: Yury Kotov <yury-kotov@yandex-team.ru>
Message-Id: <20190909131335.16848-2-yury-kotov@yandex-team.ru>
---
 include/qemu/thread.h    | 19 +++++++++++++++++++
 util/qemu-thread-posix.c | 41 +++++++++++++++++++++++++++++------------
 util/qemu-thread-win32.c | 17 +++++++++++++++++
 util/qsp.c               | 20 ++++++++++++++++++++
 4 files changed, 85 insertions(+), 12 deletions(-)

diff --git a/include/qemu/thread.h b/include/qemu/thread.h
index 55d83a9..047db03 100644
--- a/include/qemu/thread.h
+++ b/include/qemu/thread.h
@@ -34,6 +34,8 @@ typedef void (*QemuRecMutexLockFunc)(QemuRecMutex *m, const char *f, int l);
 typedef int (*QemuRecMutexTrylockFunc)(QemuRecMutex *m, const char *f, int l);
 typedef void (*QemuCondWaitFunc)(QemuCond *c, QemuMutex *m, const char *f,
                                  int l);
+typedef bool (*QemuCondTimedWaitFunc)(QemuCond *c, QemuMutex *m, int ms,
+                                      const char *f, int l);
 
 extern QemuMutexLockFunc qemu_bql_mutex_lock_func;
 extern QemuMutexLockFunc qemu_mutex_lock_func;
@@ -41,6 +43,7 @@ extern QemuMutexTrylockFunc qemu_mutex_trylock_func;
 extern QemuRecMutexLockFunc qemu_rec_mutex_lock_func;
 extern QemuRecMutexTrylockFunc qemu_rec_mutex_trylock_func;
 extern QemuCondWaitFunc qemu_cond_wait_func;
+extern QemuCondTimedWaitFunc qemu_cond_timedwait_func;
 
 /* convenience macros to bypass the profiler */
 #define qemu_mutex_lock__raw(m)                         \
@@ -63,6 +66,8 @@ extern QemuCondWaitFunc qemu_cond_wait_func;
             qemu_rec_mutex_trylock_impl(m, __FILE__, __LINE__);
 #define qemu_cond_wait(c, m)                                            \
             qemu_cond_wait_impl(c, m, __FILE__, __LINE__);
+#define qemu_cond_timedwait(c, m, ms)                                   \
+            qemu_cond_wait_impl(c, m, ms, __FILE__, __LINE__);
 #else
 #define qemu_mutex_lock(m) ({                                           \
             QemuMutexLockFunc _f = atomic_read(&qemu_mutex_lock_func);  \
@@ -89,6 +94,11 @@ extern QemuCondWaitFunc qemu_cond_wait_func;
             QemuCondWaitFunc _f = atomic_read(&qemu_cond_wait_func);    \
             _f(c, m, __FILE__, __LINE__);                               \
         })
+
+#define qemu_cond_timedwait(c, m, ms) ({                                       \
+            QemuCondTimedWaitFunc _f = atomic_read(&qemu_cond_timedwait_func); \
+            _f(c, m, ms, __FILE__, __LINE__);                                  \
+        })
 #endif
 
 #define qemu_mutex_unlock(mutex) \
@@ -134,12 +144,21 @@ void qemu_cond_signal(QemuCond *cond);
 void qemu_cond_broadcast(QemuCond *cond);
 void qemu_cond_wait_impl(QemuCond *cond, QemuMutex *mutex,
                          const char *file, const int line);
+bool qemu_cond_timedwait_impl(QemuCond *cond, QemuMutex *mutex, int ms,
+                              const char *file, const int line);
 
 static inline void (qemu_cond_wait)(QemuCond *cond, QemuMutex *mutex)
 {
     qemu_cond_wait(cond, mutex);
 }
 
+/* Returns true if timeout has not expired, and false otherwise */
+static inline bool (qemu_cond_timedwait)(QemuCond *cond, QemuMutex *mutex,
+                                         int ms)
+{
+    return qemu_cond_timedwait(cond, mutex, ms);
+}
+
 void qemu_sem_init(QemuSemaphore *sem, int init);
 void qemu_sem_post(QemuSemaphore *sem);
 void qemu_sem_wait(QemuSemaphore *sem);
diff --git a/util/qemu-thread-posix.c b/util/qemu-thread-posix.c
index 1bf5e65..838980a 100644
--- a/util/qemu-thread-posix.c
+++ b/util/qemu-thread-posix.c
@@ -36,6 +36,18 @@ static void error_exit(int err, const char *msg)
     abort();
 }
 
+static void compute_abs_deadline(struct timespec *ts, int ms)
+{
+    struct timeval tv;
+    gettimeofday(&tv, NULL);
+    ts->tv_nsec = tv.tv_usec * 1000 + (ms % 1000) * 1000000;
+    ts->tv_sec = tv.tv_sec + ms / 1000;
+    if (ts->tv_nsec >= 1000000000) {
+        ts->tv_sec++;
+        ts->tv_nsec -= 1000000000;
+    }
+}
+
 void qemu_mutex_init(QemuMutex *mutex)
 {
     int err;
@@ -164,6 +176,23 @@ void qemu_cond_wait_impl(QemuCond *cond, QemuMutex *mutex, const char *file, con
         error_exit(err, __func__);
 }
 
+bool qemu_cond_timedwait_impl(QemuCond *cond, QemuMutex *mutex, int ms,
+                              const char *file, const int line)
+{
+    int err;
+    struct timespec ts;
+
+    assert(cond->initialized);
+    trace_qemu_mutex_unlock(mutex, file, line);
+    compute_abs_deadline(&ts, ms);
+    err = pthread_cond_timedwait(&cond->cond, &mutex->lock, &ts);
+    trace_qemu_mutex_locked(mutex, file, line);
+    if (err && err != ETIMEDOUT) {
+        error_exit(err, __func__);
+    }
+    return err != ETIMEDOUT;
+}
+
 void qemu_sem_init(QemuSemaphore *sem, int init)
 {
     int rc;
@@ -238,18 +267,6 @@ void qemu_sem_post(QemuSemaphore *sem)
 #endif
 }
 
-static void compute_abs_deadline(struct timespec *ts, int ms)
-{
-    struct timeval tv;
-    gettimeofday(&tv, NULL);
-    ts->tv_nsec = tv.tv_usec * 1000 + (ms % 1000) * 1000000;
-    ts->tv_sec = tv.tv_sec + ms / 1000;
-    if (ts->tv_nsec >= 1000000000) {
-        ts->tv_sec++;
-        ts->tv_nsec -= 1000000000;
-    }
-}
-
 int qemu_sem_timedwait(QemuSemaphore *sem, int ms)
 {
     int rc;
diff --git a/util/qemu-thread-win32.c b/util/qemu-thread-win32.c
index 572f885..56a8333 100644
--- a/util/qemu-thread-win32.c
+++ b/util/qemu-thread-win32.c
@@ -145,6 +145,23 @@ void qemu_cond_wait_impl(QemuCond *cond, QemuMutex *mutex, const char *file, con
     qemu_mutex_post_lock(mutex, file, line);
 }
 
+bool qemu_cond_timedwait_impl(QemuCond *cond, QemuMutex *mutex, int ms,
+                              const char *file, const int line)
+{
+    int rc = 0;
+
+    assert(cond->initialized);
+    trace_qemu_mutex_unlock(mutex, file, line);
+    if (!SleepConditionVariableSRW(&cond->var, &mutex->lock, ms, 0)) {
+        rc = GetLastError();
+    }
+    trace_qemu_mutex_locked(mutex, file, line);
+    if (rc && rc != ERROR_TIMEOUT) {
+        error_exit(rc, __func__);
+    }
+    return rc != ERROR_TIMEOUT;
+}
+
 void qemu_sem_init(QemuSemaphore *sem, int init)
 {
     /* Manual reset.  */
diff --git a/util/qsp.c b/util/qsp.c
index 5264c97..6226541 100644
--- a/util/qsp.c
+++ b/util/qsp.c
@@ -131,6 +131,7 @@ QemuRecMutexLockFunc qemu_rec_mutex_lock_func = qemu_rec_mutex_lock_impl;
 QemuRecMutexTrylockFunc qemu_rec_mutex_trylock_func =
     qemu_rec_mutex_trylock_impl;
 QemuCondWaitFunc qemu_cond_wait_func = qemu_cond_wait_impl;
+QemuCondTimedWaitFunc qemu_cond_timedwait_func = qemu_cond_timedwait_impl;
 
 /*
  * It pays off to _not_ hash callsite->file; hashing a string is slow, and
@@ -412,6 +413,23 @@ qsp_cond_wait(QemuCond *cond, QemuMutex *mutex, const char *file, int line)
     qsp_entry_record(e, t1 - t0);
 }
 
+static bool
+qsp_cond_timedwait(QemuCond *cond, QemuMutex *mutex, int ms,
+                   const char *file, int line)
+{
+    QSPEntry *e;
+    int64_t t0, t1;
+    bool ret;
+
+    t0 = get_clock();
+    ret = qemu_cond_timedwait_impl(cond, mutex, ms, file, line);
+    t1 = get_clock();
+
+    e = qsp_entry_get(cond, file, line, QSP_CONDVAR);
+    qsp_entry_record(e, t1 - t0);
+    return ret;
+}
+
 bool qsp_is_enabled(void)
 {
     return atomic_read(&qemu_mutex_lock_func) == qsp_mutex_lock;
@@ -425,6 +443,7 @@ void qsp_enable(void)
     atomic_set(&qemu_rec_mutex_lock_func, qsp_rec_mutex_lock);
     atomic_set(&qemu_rec_mutex_trylock_func, qsp_rec_mutex_trylock);
     atomic_set(&qemu_cond_wait_func, qsp_cond_wait);
+    atomic_set(&qemu_cond_timedwait_func, qsp_cond_timedwait);
 }
 
 void qsp_disable(void)
@@ -435,6 +454,7 @@ void qsp_disable(void)
     atomic_set(&qemu_rec_mutex_lock_func, qemu_rec_mutex_lock_impl);
     atomic_set(&qemu_rec_mutex_trylock_func, qemu_rec_mutex_trylock_impl);
     atomic_set(&qemu_cond_wait_func, qemu_cond_wait_impl);
+    atomic_set(&qemu_cond_timedwait_func, qemu_cond_timedwait_impl);
 }
 
 static gint qsp_tree_cmp(gconstpointer ap, gconstpointer bp, gpointer up)
-- 
1.8.3.1




  parent reply	other threads:[~2019-09-16 15:19 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-09-16 14:41 [Qemu-devel] [PULL 00/29] Misc patches for 2019-09-16 Paolo Bonzini
2019-09-16 14:41 ` [Qemu-devel] [PULL 01/29] i386/kvm: support guest access CORE cstate Paolo Bonzini
2019-09-16 14:41 ` [Qemu-devel] [PULL 02/29] exec.c: replace hwaddr with uint64_t for better understanding Paolo Bonzini
2019-09-16 14:41 ` [Qemu-devel] [PULL 03/29] exec.c: get nodes_nb_alloc with one MAX calculation Paolo Bonzini
2019-09-16 14:41 ` [Qemu-devel] [PULL 04/29] exec.c: subpage->sub_section is already initialized to 0 Paolo Bonzini
2019-09-16 14:41 ` [Qemu-devel] [PULL 05/29] exec.c: correct the maximum skip value during compact Paolo Bonzini
2019-09-16 14:41 ` [Qemu-devel] [PULL 06/29] exec.c: add a check between constants to see whether we could skip Paolo Bonzini
2019-09-16 14:41 ` [Qemu-devel] [PULL 07/29] win32: fix README file in NSIS installer Paolo Bonzini
2019-09-16 14:41 ` [Qemu-devel] [PULL 08/29] test-char: fix AddressSanitizer failure Paolo Bonzini
2019-09-16 14:41 ` [Qemu-devel] [PULL 09/29] hw/i386: Move CONFIG_ACPI_PCI to CONFIG_PC Paolo Bonzini
2019-09-16 14:41 ` [Qemu-devel] [PULL 10/29] elf-ops.h: fix int overflow in load_elf() Paolo Bonzini
2019-09-16 14:41 ` [Qemu-devel] [PULL 11/29] memory: fetch pmem size in get_file_size() Paolo Bonzini
2019-09-16 14:41 ` [Qemu-devel] [PULL 12/29] memory: inline and optimize devend_memop Paolo Bonzini
2019-09-16 14:41 ` Paolo Bonzini [this message]
2019-09-16 14:41 ` [Qemu-devel] [PULL 14/29] cpus: Fix throttling during vm_stop Paolo Bonzini
2019-09-16 14:41 ` [Qemu-devel] [PULL 15/29] hw/i386/pc: Use e820_get_num_entries() to access e820_entries Paolo Bonzini
2019-09-16 14:41 ` [Qemu-devel] [PULL 16/29] hw/i386/pc: Extract e820 memory layout code Paolo Bonzini
2019-09-16 14:41 ` [Qemu-devel] [PULL 17/29] hw/i386/pc: Use address_space_memory in place Paolo Bonzini
2019-09-16 14:41 ` [Qemu-devel] [PULL 18/29] hw/i386/pc: Rename bochs_bios_init as more generic fw_cfg_arch_create Paolo Bonzini
2019-09-16 14:41 ` [Qemu-devel] [PULL 19/29] hw/i386/pc: Pass the boot_cpus value by argument Paolo Bonzini
2019-09-16 14:42 ` [Qemu-devel] [PULL 20/29] hw/i386/pc: Pass the apic_id_limit " Paolo Bonzini
2019-09-16 14:42 ` [Qemu-devel] [PULL 21/29] hw/i386/pc: Pass the CPUArchIdList array " Paolo Bonzini
2019-09-16 14:42 ` [Qemu-devel] [PULL 22/29] hw/i386/pc: Replace PCMachineState argument with MachineState in fw_cfg_arch_create Paolo Bonzini
2019-09-16 14:42 ` [Qemu-devel] [PULL 23/29] hw/i386/pc: Let pc_build_smbios() take a FWCfgState argument Paolo Bonzini
2019-09-16 14:42 ` [Qemu-devel] [PULL 24/29] hw/i386/pc: Let pc_build_smbios() take a generic MachineState argument Paolo Bonzini
2019-09-16 14:42 ` [Qemu-devel] [PULL 25/29] hw/i386/pc: Rename pc_build_smbios() as generic fw_cfg_build_smbios() Paolo Bonzini
2019-09-16 14:42 ` [Qemu-devel] [PULL 26/29] hw/i386/pc: Let pc_build_feature_control() take a FWCfgState argument Paolo Bonzini
2019-09-16 14:42 ` [Qemu-devel] [PULL 27/29] hw/i386/pc: Let pc_build_feature_control() take a MachineState argument Paolo Bonzini
2019-09-16 14:42 ` [Qemu-devel] [PULL 28/29] hw/i386/pc: Rename pc_build_feature_control() as generic fw_cfg_build_* Paolo Bonzini
2019-09-16 14:42 ` [Qemu-devel] [PULL 29/29] hw/i386/pc: Extract the x86 generic fw_cfg code Paolo Bonzini

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1568644929-9124-14-git-send-email-pbonzini@redhat.com \
    --to=pbonzini@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=yury-kotov@yandex-team.ru \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.