From: Paolo Bonzini <pbonzini@redhat.com>
To: Wen Congyang <wency@cn.fujitsu.com>, qemu-devl <qemu-devel@nongnu.org>
Subject: Re: [Qemu-devel] [PATCH v2 for-2.5] rcu: Allow calling rcu_(un)register_thread() during synchronize_rcu()
Date: Tue, 28 Jul 2015 11:59:20 +0200 [thread overview]
Message-ID: <55B75278.80909@redhat.com> (raw)
In-Reply-To: <55B6E854.9090600@cn.fujitsu.com>
On 28/07/2015 04:26, Wen Congyang wrote:
> If rcu_(un)register_thread() is called together with synchronize_rcu(),
> it will wait for the synchronize_rcu() to finish. But when synchronize_rcu()
> waits for some events, we can modify the list registry.
> We also use the lock rcu_gp_lock to assume that synchronize_rcu() isn't
> executed in more than one thread at the same time. Add a new mutex lock
> rcu_sync_lock to assume it and rename rcu_gp_lock to rcu_registry_lock.
> Release rcu_registry_lock when synchronize_rcu() waits for some events.
>
> Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
> ---
> util/rcu.c | 48 +++++++++++++++++++++++++++++++++++-------------
> 1 file changed, 35 insertions(+), 13 deletions(-)
>
> diff --git a/util/rcu.c b/util/rcu.c
> index cdcad67..4dd33df 100644
> --- a/util/rcu.c
> +++ b/util/rcu.c
> @@ -47,7 +47,8 @@
> unsigned long rcu_gp_ctr = RCU_GP_LOCKED;
>
> QemuEvent rcu_gp_event;
> -static QemuMutex rcu_gp_lock;
> +static QemuMutex rcu_registry_lock;
> +static QemuMutex rcu_sync_lock;
>
> /*
> * Check whether a quiescent state was crossed between the beginning of
> @@ -66,7 +67,7 @@ static inline int rcu_gp_ongoing(unsigned long *ctr)
> */
> __thread struct rcu_reader_data rcu_reader;
>
> -/* Protected by rcu_gp_lock. */
> +/* Protected by rcu_registry_lock. */
> typedef QLIST_HEAD(, rcu_reader_data) ThreadList;
> static ThreadList registry = QLIST_HEAD_INITIALIZER(registry);
>
> @@ -114,10 +115,26 @@ static void wait_for_readers(void)
> break;
> }
>
> - /* Wait for one thread to report a quiescent state and
> - * try again.
> + /* Wait for one thread to report a quiescent state and try again.
> + * Release rcu_registry_lock, so rcu_(un)register_thread() doesn't
> + * wait too much time.
> + *
> + * rcu_register_thread() may add nodes to ®istry; it will not
> + * wake up synchronize_rcu, but that is okay because at least another
> + * thread must exit its RCU read-side critical section before
> + * synchronize_rcu is done. The next iteration of the loop will
> + * move the new thread's rcu_reader from ®istry to &qsreaders,
> + * because rcu_gp_ongoing() will return false.
> + *
> + * rcu_unregister_thread() may remove nodes from &qsreaders instead
> + * of ®istry if it runs during qemu_event_wait. That's okay;
> + * the node then will not be added back to ®istry by QLIST_SWAP
> + * below. The invariant is that the node is part of one list when
> + * rcu_registry_lock is released.
> */
> + qemu_mutex_unlock(&rcu_registry_lock);
> qemu_event_wait(&rcu_gp_event);
> + qemu_mutex_lock(&rcu_registry_lock);
> }
>
> /* put back the reader list in the registry */
> @@ -126,7 +143,8 @@ static void wait_for_readers(void)
>
> void synchronize_rcu(void)
> {
> - qemu_mutex_lock(&rcu_gp_lock);
> + qemu_mutex_lock(&rcu_sync_lock);
> + qemu_mutex_lock(&rcu_registry_lock);
>
> if (!QLIST_EMPTY(®istry)) {
> /* In either case, the atomic_mb_set below blocks stores that free
> @@ -149,7 +167,8 @@ void synchronize_rcu(void)
> wait_for_readers();
> }
>
> - qemu_mutex_unlock(&rcu_gp_lock);
> + qemu_mutex_unlock(&rcu_registry_lock);
> + qemu_mutex_unlock(&rcu_sync_lock);
> }
>
>
> @@ -273,23 +292,24 @@ void call_rcu1(struct rcu_head *node, void (*func)(struct rcu_head *node))
> void rcu_register_thread(void)
> {
> assert(rcu_reader.ctr == 0);
> - qemu_mutex_lock(&rcu_gp_lock);
> + qemu_mutex_lock(&rcu_registry_lock);
> QLIST_INSERT_HEAD(®istry, &rcu_reader, node);
> - qemu_mutex_unlock(&rcu_gp_lock);
> + qemu_mutex_unlock(&rcu_registry_lock);
> }
>
> void rcu_unregister_thread(void)
> {
> - qemu_mutex_lock(&rcu_gp_lock);
> + qemu_mutex_lock(&rcu_registry_lock);
> QLIST_REMOVE(&rcu_reader, node);
> - qemu_mutex_unlock(&rcu_gp_lock);
> + qemu_mutex_unlock(&rcu_registry_lock);
> }
>
> static void rcu_init_complete(void)
> {
> QemuThread thread;
>
> - qemu_mutex_init(&rcu_gp_lock);
> + qemu_mutex_init(&rcu_registry_lock);
> + qemu_mutex_init(&rcu_sync_lock);
> qemu_event_init(&rcu_gp_event, true);
>
> qemu_event_init(&rcu_call_ready_event, false);
> @@ -306,12 +326,14 @@ static void rcu_init_complete(void)
> #ifdef CONFIG_POSIX
> static void rcu_init_lock(void)
> {
> - qemu_mutex_lock(&rcu_gp_lock);
> + qemu_mutex_lock(&rcu_sync_lock);
> + qemu_mutex_lock(&rcu_registry_lock);
> }
>
> static void rcu_init_unlock(void)
> {
> - qemu_mutex_unlock(&rcu_gp_lock);
> + qemu_mutex_unlock(&rcu_registry_lock);
> + qemu_mutex_unlock(&rcu_sync_lock);
> }
> #endif
>
>
Ok, thanks.
Paolo
next prev parent reply other threads:[~2015-07-28 9:59 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-07-28 2:26 [Qemu-devel] [PATCH v2 for-2.5] rcu: Allow calling rcu_(un)register_thread() during synchronize_rcu() Wen Congyang
2015-07-28 9:59 ` Paolo Bonzini [this message]
2015-07-28 10:02 ` Wen Congyang
2015-07-28 10:18 ` Paolo Bonzini
2015-07-28 10:33 ` Wen Congyang
2015-07-28 11:46 ` Paolo Bonzini
2015-07-28 13:29 ` Wen Congyang
2015-07-28 16:14 ` Paolo Bonzini
2015-07-29 1:11 ` Wen Congyang
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=55B75278.80909@redhat.com \
--to=pbonzini@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=wency@cn.fujitsu.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.