Optimization posted to upstream mailing list. Signed-off-by: Paolo Bonzini <pbonz...@redhat.com> --- rcu.c | 5 +++++ rcu.h | 22 ++++++++++++---------- 2 files changed, 17 insertions(+), 10 deletions(-)
diff --git a/rcu.c b/rcu.c index e2f347a..aaf53ad 100644 --- a/rcu.c +++ b/rcu.c @@ -91,6 +91,11 @@ static void update_counter_and_wait(void) * while we walk the list. */ qemu_event_reset(&rcu_gp_event); + QLIST_FOREACH(index, ®istry, node) { + ACCESS_ONCE(index->waiting) = true; + } + __sync_synchronize(); + QLIST_FOREACH_SAFE(index, ®istry, node, tmp) { if (!rcu_gp_ongoing(&index->ctr)) { QLIST_REMOVE(index, node); diff --git a/rcu.h b/rcu.h index 86a1fea..96ce9d3 100644 --- a/rcu.h +++ b/rcu.h @@ -74,6 +74,8 @@ extern QemuEvent rcu_gp_event; struct rcu_reader { /* Data used by both reader and synchronize_rcu() */ unsigned long ctr; + bool waiting; + /* Data used for registry */ QLIST_ENTRY(rcu_reader) node; }; @@ -93,24 +95,24 @@ static inline void rcu_quiescent_state(void) { smp_mb(); ACCESS_ONCE(rcu_reader.ctr) = ACCESS_ONCE(rcu_gp_ctr); -#if 0 - /* write rcu_reader.ctr before read futex. Included in - * qemu_event_set. */ + /* write rcu_reader.ctr before read waiting. */ smp_mb(); -#endif - qemu_event_set(&rcu_gp_event); + if (ACCESS_ONCE(rcu_reader.waiting)) { + ACCESS_ONCE(rcu_reader.waiting) = false; + qemu_event_set(&rcu_gp_event); + } } static inline void rcu_thread_offline(void) { smp_mb(); ACCESS_ONCE(rcu_reader.ctr) = 0; -#if 0 - /* write rcu_reader.ctr before read futex. Included in - * qemu_event_set. */ + /* write rcu_reader.ctr before read waiting. */ smp_mb(); -#endif - qemu_event_set(&rcu_gp_event); + if (ACCESS_ONCE(rcu_reader.waiting)) { + ACCESS_ONCE(rcu_reader.waiting) = false; + qemu_event_set(&rcu_gp_event); + } } static inline void rcu_thread_online(void) -- 1.7.6