qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [RFC v2 3/5] timer: make qemu_clock_enable sync between dis


From: Liu Ping Fan
Subject: [Qemu-devel] [RFC v2 3/5] timer: make qemu_clock_enable sync between disable and timer's cb
Date: Mon, 29 Jul 2013 11:16:06 +0800

After disabling the QemuClock, we should make sure that no QemuTimers
are still in flight. To implement that, the caller of disabling will
wait until the last user's exit.

Note, the callers of qemu_clock_enable() should be sync by themselves,
not protected by this patch.

Signed-off-by: Liu Ping Fan <address@hidden>
---
 qemu-timer.c | 34 ++++++++++++++++++++++++++++++++--
 1 file changed, 32 insertions(+), 2 deletions(-)

diff --git a/qemu-timer.c b/qemu-timer.c
index 5a42035..d941a83 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -60,6 +60,14 @@ struct QEMUClock {
 
     int type;
     bool enabled;
+
+    /* rule: Innermost lock
+     * to protect the disable against timer's cb in flight.
+     */
+    QemuMutex lock;
+    /* reference by timer list */
+    int using;
+    QemuCond wait_using;
 };
 
 struct QEMUTimer {
@@ -274,6 +282,9 @@ static QEMUClock *qemu_new_clock(int type)
     clock->type = type;
     clock->enabled = true;
     clock->last = INT64_MIN;
+    clock->using = 0;
+    qemu_cond_init(&clock->wait_using);
+    qemu_mutex_init(&clock->lock);
     notifier_list_init(&clock->reset_notifiers);
     tlist = clock_to_timerlist(clock);
     timer_list_init(tlist);
@@ -287,6 +298,13 @@ void qemu_clock_enable(QEMUClock *clock, bool enabled)
     clock->enabled = enabled;
     if (enabled && !old) {
         qemu_rearm_alarm_timer(alarm_timer);
+    } else {
+        qemu_mutex_lock(&clock->lock);
+        /* Wait for cb in flight to terminate */
+        while (atomic_read(clock->using)) {
+            qemu_cond_wait(&clock->wait_using, &clock->lock);
+        }
+        qemu_mutex_unlock(&clock->lock);
     }
 }
 
@@ -440,8 +458,11 @@ void qemu_run_timers(QEMUClock *clock)
     int64_t current_time;
     TimerList *tlist;
 
-    if (!clock->enabled)
-        return;
+    atomic_inc(&clock->using);
+    if (unlikely(!clock->enabled)) {
+        goto exit;
+    }
+
 
     current_time = qemu_get_clock_ns(clock);
     tlist = clock_to_timerlist(clock);
@@ -461,6 +482,15 @@ void qemu_run_timers(QEMUClock *clock)
         /* run the callback (the timer list can be modified) */
         ts->cb(ts->opaque);
     }
+
+exit:
+    qemu_mutex_lock(&clock->lock);
+    if (atomic_fetch_dec(&clock->using) == 1) {
+        if (unlikely(!clock->enabled)) {
+            qemu_cond_signal(&clock->wait_using);
+        }
+    }
+    qemu_mutex_unlock(&clock->lock);
 }
 
 int64_t qemu_get_clock_ns(QEMUClock *clock)
-- 
1.8.1.4




reply via email to

[Prev in Thread] Current Thread [Next in Thread]