All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jan Kiszka <jan.kiszka@siemens.com>
To: Liu Ping Fan <qemulist@gmail.com>
Cc: Alex Bligh <alex@alex.org.uk>,
	Paolo Bonzini <pbonzini@redhat.com>,
	Kevin Wolf <kwolf@redhat.com>,
	qemu-devel@nongnu.org, Stefan Hajnoczi <stefanha@redhat.com>
Subject: Re: [Qemu-devel] [PATCH v4 2/4] timer: protect timers_state's clock with seqlock
Date: Mon, 23 Sep 2013 08:21:43 +0200	[thread overview]
Message-ID: <523FDDF7.300@siemens.com> (raw)
In-Reply-To: <1379837479-8419-4-git-send-email-pingfank@linux.vnet.ibm.com>

On 2013-09-22 10:11, Liu Ping Fan wrote:
> QEMU_CLOCK_VIRTUAL may be read outside BQL. This will make its
> foundation, i.e. timers_state exposed to race condition.
> Using private lock to protect it.
> 
> After this patch, reading QEMU_CLOCK_VIRTUAL is thread safe
> unless use_icount is true, in which case the existing callers
> still rely on the BQL
> 
> Lock rule: private lock innermost, ie BQL->"this lock"
> 
> Signed-off-by: Liu Ping Fan <pingfank@linux.vnet.ibm.com>
> ---
>  cpus.c | 36 ++++++++++++++++++++++++++++++------
>  1 file changed, 30 insertions(+), 6 deletions(-)
> 
> diff --git a/cpus.c b/cpus.c
> index e566297..870a832 100644
> --- a/cpus.c
> +++ b/cpus.c
> @@ -37,6 +37,7 @@
>  #include "sysemu/qtest.h"
>  #include "qemu/main-loop.h"
>  #include "qemu/bitmap.h"
> +#include "qemu/seqlock.h"
>  
>  #ifndef _WIN32
>  #include "qemu/compatfd.h"
> @@ -112,6 +113,13 @@ static int64_t qemu_icount;
>  typedef struct TimersState {
>      int64_t cpu_ticks_prev;
>      int64_t cpu_ticks_offset;
> +    /* cpu_clock_offset will be read out of BQL, so protect it with private
> +     * lock. As for cpu_ticks_*, no requirement to read it outside BQL yet.
> +     * Lock rule: innermost
> +     */
> +    QemuSeqLock clock_seqlock;
> +    /* mutex for seqlock */
> +    QemuMutex mutex;

If these locks only protect cpu_clock_offset, name them accordingly
(cpu_clock_offset_seqlock, cpu_clock_offset_mutex). But I think they
also protect cpu_ticks_enabled, no? Then you should adjust the comment.

>      int64_t cpu_clock_offset;
>      int32_t cpu_ticks_enabled;
>      int64_t dummy;
> @@ -137,6 +145,7 @@ int64_t cpu_get_icount(void)
>  }
>  
>  /* return the host CPU cycle counter and handle stop/restart */
> +/* cpu_ticks is safely if holding BQL */

"Caller must hold the BQL."

>  int64_t cpu_get_ticks(void)
>  {
>      if (use_icount) {
> @@ -161,33 +170,46 @@ int64_t cpu_get_ticks(void)
>  int64_t cpu_get_clock(void)
>  {
>      int64_t ti;
> -    if (!timers_state.cpu_ticks_enabled) {
> -        return timers_state.cpu_clock_offset;
> -    } else {
> -        ti = get_clock();
> -        return ti + timers_state.cpu_clock_offset;
> -    }
> +    unsigned start;
> +
> +    do {
> +        start = seqlock_read_begin(&timers_state.clock_seqlock);
> +        if (!timers_state.cpu_ticks_enabled) {
> +            ti = timers_state.cpu_clock_offset;
> +        } else {
> +            ti = get_clock();
> +            ti += timers_state.cpu_clock_offset;
> +        }
> +    } while (seqlock_read_retry(&timers_state.clock_seqlock, start));
> +
> +    return ti;
>  }
>  
>  /* enable cpu_get_ticks() */
>  void cpu_enable_ticks(void)
>  {
> +    /* Here, the really thing protected by seqlock is cpu_clock_offset. */
> +    seqlock_write_lock(&timers_state.clock_seqlock);
>      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;
>      }
> +    seqlock_write_unlock(&timers_state.clock_seqlock);
>  }
>  
>  /* disable cpu_get_ticks() : the clock is stopped. You must not call
>     cpu_get_ticks() after that.  */
>  void cpu_disable_ticks(void)
>  {
> +    /* Here, the really thing protected by seqlock is cpu_clock_offset. */
> +    seqlock_write_lock(&timers_state.clock_seqlock);
>      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;
>      }
> +    seqlock_write_unlock(&timers_state.clock_seqlock);
>  }
>  
>  /* Correlation between real and virtual time is always going to be
> @@ -371,6 +393,8 @@ static const VMStateDescription vmstate_timers = {
>  
>  void configure_icount(const char *option)
>  {
> +    qemu_mutex_init(&timers_state.mutex);
> +    seqlock_init(&timers_state.clock_seqlock, &timers_state.mutex);
>      vmstate_register(NULL, 0, &vmstate_timers, &timers_state);
>      if (!option) {
>          return;
> 

Jan

-- 
Siemens AG, Corporate Technology, CT RTC ITP SES-DE
Corporate Competence Center Embedded Linux

  reply	other threads:[~2013-09-23  6:22 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-09-22  8:11 [Qemu-devel] [PATCH v4 0/4] timers thread-safe stuff Liu Ping Fan
2013-09-22  8:11 ` [Qemu-devel] [PATCH v4 1/4] seqlock: introduce read-write seqlock Liu Ping Fan
2013-09-23  6:21   ` Jan Kiszka
2013-09-24  5:33     ` liu ping fan
2013-09-24  8:13       ` Paolo Bonzini
2013-09-22  8:11 ` Liu Ping Fan
2013-09-22  8:11 ` [Qemu-devel] [PATCH v4 2/4] timer: protect timers_state's clock with seqlock Liu Ping Fan
2013-09-23  6:21   ` Jan Kiszka [this message]
2013-09-24  6:15     ` liu ping fan
2013-09-22  8:11 ` [Qemu-devel] [PATCH v4 3/4] qemu-thread: add QemuEvent Liu Ping Fan
2013-09-23  6:23   ` Jan Kiszka
2013-09-22  8:11 ` [Qemu-devel] [PATCH v4 4/4] timer: make qemu_clock_enable sync between disable and timer's cb Liu Ping Fan
2013-09-23  6:26   ` Jan Kiszka
2013-09-24  5:40     ` liu ping fan

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=523FDDF7.300@siemens.com \
    --to=jan.kiszka@siemens.com \
    --cc=alex@alex.org.uk \
    --cc=kwolf@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=qemulist@gmail.com \
    --cc=stefanha@redhat.com \
    /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.