From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:45016) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1V3dy6-0001Q1-5X for qemu-devel@nongnu.org; Sun, 28 Jul 2013 23:18:03 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1V3dxx-0002Ld-Mw for qemu-devel@nongnu.org; Sun, 28 Jul 2013 23:17:54 -0400 Received: from mail-ob0-x22b.google.com ([2607:f8b0:4003:c01::22b]:39326) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1V3dxx-0002LZ-IS for qemu-devel@nongnu.org; Sun, 28 Jul 2013 23:17:45 -0400 Received: by mail-ob0-f171.google.com with SMTP id tb18so8379913obb.30 for ; Sun, 28 Jul 2013 20:17:45 -0700 (PDT) From: Liu Ping Fan Date: Mon, 29 Jul 2013 11:16:06 +0800 Message-Id: <1375067768-11342-4-git-send-email-pingfank@linux.vnet.ibm.com> In-Reply-To: <1375067768-11342-1-git-send-email-pingfank@linux.vnet.ibm.com> References: <1375067768-11342-1-git-send-email-pingfank@linux.vnet.ibm.com> Subject: [Qemu-devel] [RFC v2 3/5] timer: make qemu_clock_enable sync between disable and timer's cb List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Kevin Wolf , Stefan Hajnoczi , Jan Kiszka , Alex Bligh , Anthony Liguori , Paolo Bonzini 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 --- 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