From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:49354) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1V0pM7-0003ek-NE for qemu-devel@nongnu.org; Sun, 21 Jul 2013 04:51:05 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1V0pM6-0007Fm-Ny for qemu-devel@nongnu.org; Sun, 21 Jul 2013 04:51:03 -0400 Received: from mail-pa0-x235.google.com ([2607:f8b0:400e:c03::235]:54128) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1V0pM6-0007Fc-G1 for qemu-devel@nongnu.org; Sun, 21 Jul 2013 04:51:02 -0400 Received: by mail-pa0-f53.google.com with SMTP id tj12so5966328pac.26 for ; Sun, 21 Jul 2013 01:51:01 -0700 (PDT) From: Liu Ping Fan Date: Sun, 21 Jul 2013 16:43:01 +0800 Message-Id: <1374396185-10870-5-git-send-email-pingfank@linux.vnet.ibm.com> In-Reply-To: <1374396185-10870-1-git-send-email-pingfank@linux.vnet.ibm.com> References: <1374396185-10870-1-git-send-email-pingfank@linux.vnet.ibm.com> Subject: [Qemu-devel] [RFC 4/8] timer: protect timers_state with lock 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 In kvm mode, vm_clock may be read on AioContexts outside BQL(next patch). This will make timers_state --the foundation of vm_clock exposed to race condition. Using private lock to protect it. Note in tcg mode, vm_clock still read inside BQL, so icount is left without change. Lock rule: private lock innermost, ie BQL->"this lock" Signed-off-by: Liu Ping Fan --- cpus.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/cpus.c b/cpus.c index 4254ca9..22df5fb 100644 --- a/cpus.c +++ b/cpus.c @@ -113,6 +113,8 @@ typedef struct TimersState { } TimersState; static TimersState timers_state; +/* lock rule: innermost */ +static QemuMutex timers_state_lock; /* Return the virtual CPU time, based on the instruction counter. */ int64_t cpu_get_icount(void) @@ -134,11 +136,15 @@ int64_t cpu_get_icount(void) /* return the host CPU cycle counter and handle stop/restart */ int64_t cpu_get_ticks(void) { + int64_t ret; + if (use_icount) { return cpu_get_icount(); } + qemu_mutex_lock(&timers_state_lock); if (!timers_state.cpu_ticks_enabled) { - return timers_state.cpu_ticks_offset; + ret = timers_state.cpu_ticks_offset; + goto out; } else { int64_t ticks; ticks = cpu_get_real_ticks(); @@ -148,41 +154,53 @@ int64_t cpu_get_ticks(void) timers_state.cpu_ticks_offset += timers_state.cpu_ticks_prev - ticks; } timers_state.cpu_ticks_prev = ticks; - return ticks + timers_state.cpu_ticks_offset; + ret = ticks + timers_state.cpu_ticks_offset; + goto out; } +out: + qemu_mutex_lock(&timers_state_lock); + return ret; } /* return the host CPU monotonic timer and handle stop/restart */ int64_t cpu_get_clock(void) { int64_t ti; + + qemu_mutex_lock(&timers_state_lock); if (!timers_state.cpu_ticks_enabled) { - return timers_state.cpu_clock_offset; + ti = timers_state.cpu_clock_offset; } else { ti = get_clock(); - return ti + timers_state.cpu_clock_offset; + ti += timers_state.cpu_clock_offset; } + qemu_mutex_unlock(&timers_state_lock); + return ti; } /* enable cpu_get_ticks() */ void cpu_enable_ticks(void) { + qemu_mutex_lock(&timers_state_lock); if (!timers_state.cpu_ticks_enabled) { timers_state.cpu_ticks_offset -= cpu_get_real_ticks(); timers_state.cpu_clock_offset -= get_clock(); timers_state.cpu_ticks_enabled = 1; } + qemu_mutex_unlock(&timers_state_lock); } /* disable cpu_get_ticks() : the clock is stopped. You must not call cpu_get_ticks() after that. */ void cpu_disable_ticks(void) { + qemu_mutex_lock(&timers_state_lock); if (timers_state.cpu_ticks_enabled) { timers_state.cpu_ticks_offset = cpu_get_ticks(); timers_state.cpu_clock_offset = cpu_get_clock(); timers_state.cpu_ticks_enabled = 0; } + qemu_mutex_unlock(&timers_state_lock); } /* Correlation between real and virtual time is always going to be @@ -353,6 +371,7 @@ static const VMStateDescription vmstate_timers = { void configure_icount(const char *option) { + qemu_mutex_init(&timers_state_lock); vmstate_register(NULL, 0, &vmstate_timers, &timers_state); if (!option) { return; -- 1.8.1.4