qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Fam Zheng <famz@redhat.com>
To: Paolo Bonzini <pbonzini@redhat.com>
Cc: borntraeger@de.ibm.com, qemu-devel@nongnu.org, stefanha@redhat.com
Subject: Re: [Qemu-devel] [PATCH 06/15] memory: protect current_map by RCU
Date: Mon, 26 Jan 2015 14:16:25 +0800	[thread overview]
Message-ID: <20150126061625.GF2354@ad.nay.redhat.com> (raw)
In-Reply-To: <1421938053-10318-7-git-send-email-pbonzini@redhat.com>

On Thu, 01/22 15:47, Paolo Bonzini wrote:
> Replace the flat_view_mutex by RCU, avoiding futex contention for
> dataplane on large systems and many iothreads.
> 
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
>  include/exec/memory.h |  5 +++++
>  memory.c              | 54 ++++++++++++++++++++++-----------------------------
>  2 files changed, 28 insertions(+), 31 deletions(-)
> 
> diff --git a/include/exec/memory.h b/include/exec/memory.h
> index 0cd96b1..06ffa1d 100644
> --- a/include/exec/memory.h
> +++ b/include/exec/memory.h
> @@ -33,6 +33,7 @@
>  #include "qemu/notify.h"
>  #include "qapi/error.h"
>  #include "qom/object.h"
> +#include "qemu/rcu.h"
>  
>  #define MAX_PHYS_ADDR_SPACE_BITS 62
>  #define MAX_PHYS_ADDR            (((hwaddr)1 << MAX_PHYS_ADDR_SPACE_BITS) - 1)
> @@ -207,9 +208,13 @@ struct MemoryListener {
>   */
>  struct AddressSpace {
>      /* All fields are private. */
> +    struct rcu_head rcu;
>      char *name;
>      MemoryRegion *root;
> +
> +    /* Accessed via RCU.  */
>      struct FlatView *current_map;
> +
>      int ioeventfd_nb;
>      struct MemoryRegionIoeventfd *ioeventfds;
>      struct AddressSpaceDispatch *dispatch;
> diff --git a/memory.c b/memory.c
> index 8c3d8c0..a844ced 100644
> --- a/memory.c
> +++ b/memory.c
> @@ -33,26 +33,12 @@ static bool memory_region_update_pending;
>  static bool ioeventfd_update_pending;
>  static bool global_dirty_log = false;
>  
> -/* flat_view_mutex is taken around reading as->current_map; the critical
> - * section is extremely short, so I'm using a single mutex for every AS.
> - * We could also RCU for the read-side.
> - *
> - * The BQL is taken around transaction commits, hence both locks are taken
> - * while writing to as->current_map (with the BQL taken outside).
> - */
> -static QemuMutex flat_view_mutex;
> -
>  static QTAILQ_HEAD(memory_listeners, MemoryListener) memory_listeners
>      = QTAILQ_HEAD_INITIALIZER(memory_listeners);
>  
>  static QTAILQ_HEAD(, AddressSpace) address_spaces
>      = QTAILQ_HEAD_INITIALIZER(address_spaces);
>  
> -static void memory_init(void)
> -{
> -    qemu_mutex_init(&flat_view_mutex);
> -}
> -
>  typedef struct AddrRange AddrRange;
>  
>  /*
> @@ -242,6 +228,7 @@ struct FlatRange {
>   * order.
>   */
>  struct FlatView {
> +    struct rcu_head rcu;
>      unsigned ref;
>      FlatRange *ranges;
>      unsigned nr;
> @@ -654,10 +641,10 @@ static FlatView *address_space_get_flatview(AddressSpace *as)
>  {
>      FlatView *view;
>  
> -    qemu_mutex_lock(&flat_view_mutex);
> -    view = as->current_map;
> +    rcu_read_lock();
> +    view = atomic_rcu_read(&as->current_map);
>      flatview_ref(view);
> -    qemu_mutex_unlock(&flat_view_mutex);
> +    rcu_read_unlock();
>      return view;
>  }
>  
> @@ -766,10 +753,9 @@ static void address_space_update_topology(AddressSpace *as)
>      address_space_update_topology_pass(as, old_view, new_view, false);
>      address_space_update_topology_pass(as, old_view, new_view, true);
>  
> -    qemu_mutex_lock(&flat_view_mutex);
> -    flatview_unref(as->current_map);
> -    as->current_map = new_view;
> -    qemu_mutex_unlock(&flat_view_mutex);
> +    /* Writes are protected by the BQL.  */
> +    atomic_rcu_set(&as->current_map, new_view);
> +    call_rcu(old_view, flatview_unref, rcu);
>  
>      /* Note that all the old MemoryRegions are still alive up to this
>       * point.  This relieves most MemoryListeners from the need to
> @@ -1957,10 +1943,6 @@ void memory_listener_unregister(MemoryListener *listener)
>  
>  void address_space_init(AddressSpace *as, MemoryRegion *root, const char *name)
>  {
> -    if (QTAILQ_EMPTY(&address_spaces)) {
> -        memory_init();
> -    }
> -
>      memory_region_transaction_begin();
>      as->root = root;
>      as->current_map = g_new(FlatView, 1);
> @@ -1974,15 +1956,10 @@ void address_space_init(AddressSpace *as, MemoryRegion *root, const char *name)
>      memory_region_transaction_commit();
>  }
>  
> -void address_space_destroy(AddressSpace *as)
> +static void do_address_space_destroy(AddressSpace *as)
>  {
>      MemoryListener *listener;
>  
> -    /* Flush out anything from MemoryListeners listening in on this */
> -    memory_region_transaction_begin();
> -    as->root = NULL;
> -    memory_region_transaction_commit();
> -    QTAILQ_REMOVE(&address_spaces, as, address_spaces_link);
>      address_space_destroy_dispatch(as);
>  
>      QTAILQ_FOREACH(listener, &memory_listeners, link) {
> @@ -1994,6 +1971,21 @@ void address_space_destroy(AddressSpace *as)
>      g_free(as->ioeventfds);
>  }
>  
> +void address_space_destroy(AddressSpace *as)
> +{
> +    /* Flush out anything from MemoryListeners listening in on this */
> +    memory_region_transaction_begin();
> +    as->root = NULL;
> +    memory_region_transaction_commit();
> +    QTAILQ_REMOVE(&address_spaces, as, address_spaces_link);
> +
> +    /* At this point, as->dispatch and as->current_map are dummy
> +     * entries that the guest should never use.  Wait for the old
> +     * values to expire before freeing the data.
> +     */
> +    call_rcu(as, do_address_space_destroy, rcu);
> +}
> +
>  bool io_mem_read(MemoryRegion *mr, hwaddr addr, uint64_t *pval, unsigned size)
>  {
>      return memory_region_dispatch_read(mr, addr, pval, size);
> -- 
> 1.8.3.1
> 
> 
Reviewed-by: Fam Zheng <famz@redhat.com>

  reply	other threads:[~2015-01-26  6:16 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-01-22 14:47 [Qemu-devel] [PATCH v2 00/15] RCUification of the memory API, parts 1 and 2 Paolo Bonzini
2015-01-22 14:47 ` [Qemu-devel] [PATCH 01/15] rcu: add rcu library Paolo Bonzini
2015-01-26  3:13   ` Fam Zheng
2015-01-22 14:47 ` [Qemu-devel] [PATCH 02/15] rcu: add rcutorture Paolo Bonzini
2015-01-26  3:31   ` Fam Zheng
2015-01-22 14:47 ` [Qemu-devel] [PATCH 03/15] rcu: allow nesting of rcu_read_lock/rcu_read_unlock Paolo Bonzini
2015-01-26  3:32   ` Fam Zheng
2015-01-22 14:47 ` [Qemu-devel] [PATCH 04/15] rcu: add call_rcu Paolo Bonzini
2015-01-26  6:04   ` Fam Zheng
2015-01-22 14:47 ` [Qemu-devel] [PATCH 05/15] memory: remove assertion on memory_region_destroy Paolo Bonzini
2015-01-26  6:04   ` Fam Zheng
2015-01-22 14:47 ` [Qemu-devel] [PATCH 06/15] memory: protect current_map by RCU Paolo Bonzini
2015-01-26  6:16   ` Fam Zheng [this message]
2015-01-22 14:47 ` [Qemu-devel] [PATCH 07/15] memory: avoid ref/unref in memory_region_find Paolo Bonzini
2015-01-26  6:24   ` Fam Zheng
2015-01-26  9:19     ` Paolo Bonzini
2015-01-22 14:47 ` [Qemu-devel] [PATCH 08/15] exec: introduce cpu_reload_memory_map Paolo Bonzini
2015-01-22 14:47 ` [Qemu-devel] [PATCH 09/15] exec: make iotlb RCU-friendly Paolo Bonzini
2015-01-22 14:47 ` [Qemu-devel] [PATCH 10/15] exec: RCUify AddressSpaceDispatch Paolo Bonzini
2015-01-28  5:45   ` Fam Zheng
2015-01-28  9:44     ` Paolo Bonzini
2015-02-03 10:07     ` Paolo Bonzini
2015-01-22 14:47 ` [Qemu-devel] [PATCH 11/15] rcu: introduce RCU-enabled QLIST Paolo Bonzini
2015-01-22 14:47 ` [Qemu-devel] [PATCH 12/15] exec: protect mru_block with RCU Paolo Bonzini
2015-01-22 14:47 ` [Qemu-devel] [PATCH 13/15] cosmetic changes preparing for the following patches Paolo Bonzini
2015-01-22 14:47 ` [Qemu-devel] [PATCH 14/15] exec: convert ram_list to QLIST Paolo Bonzini
2015-01-22 14:47 ` [Qemu-devel] [PATCH 15/15] Convert ram_list to RCU 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=20150126061625.GF2354@ad.nay.redhat.com \
    --to=famz@redhat.com \
    --cc=borntraeger@de.ibm.com \
    --cc=pbonzini@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).