All of lore.kernel.org
 help / color / mirror / Atom feed
From: Frederic Weisbecker <frederic@kernel.org>
To: "Uladzislau Rezki (Sony)" <urezki@gmail.com>
Cc: "Paul E . McKenney" <paulmck@kernel.org>,
	RCU <rcu@vger.kernel.org>,
	Neeraj upadhyay <Neeraj.Upadhyay@amd.com>,
	Boqun Feng <boqun.feng@gmail.com>,
	Hillf Danton <hdanton@sina.com>,
	Joel Fernandes <joel@joelfernandes.org>,
	LKML <linux-kernel@vger.kernel.org>,
	Oleksiy Avramchenko <oleksiy.avramchenko@sony.com>
Subject: Re: [PATCH v5 2/4] rcu: Reduce synchronize_rcu() latency
Date: Tue, 27 Feb 2024 00:07:32 +0100	[thread overview]
Message-ID: <Zd0ZtNu+Rt0qXkfS@lothringen> (raw)
In-Reply-To: <20240220183115.74124-3-urezki@gmail.com>

On Tue, Feb 20, 2024 at 07:31:13PM +0100, Uladzislau Rezki (Sony) wrote:
> +static void rcu_sr_normal_gp_cleanup_work(struct work_struct *work)
> +{
> +	struct llist_node *done, *rcu, *next, *head;
> +
> +	/*
> +	 * This work execution can potentially execute
> +	 * while a new done tail is being updated by
> +	 * grace period kthread in rcu_sr_normal_gp_cleanup().
> +	 * So, read and updates of done tail need to
> +	 * follow acq-rel semantics.
> +	 *
> +	 * Given that wq semantics guarantees that a single work
> +	 * cannot execute concurrently by multiple kworkers,
> +	 * the done tail list manipulations are protected here.
> +	 */
> +	done = smp_load_acquire(&rcu_state.srs_done_tail);
> +	if (!done)
> +		return;
> +
> +	WARN_ON_ONCE(!rcu_sr_is_wait_head(done));
> +	head = done->next;
> +	done->next = NULL;

Can the following race happen?

CPU 0                                                   CPU 1
-----                                                   -----

// wait_tail == HEAD1
rcu_sr_normal_gp_cleanup() {
    // has passed SR_MAX_USERS_WAKE_FROM_GP
    wait_tail->next = next;
    // done_tail = HEAD1
    smp_store_release(&rcu_state.srs_done_tail, wait_tail);
    queue_work() {
        test_and_set_bit(WORK_STRUCT_PENDING_BIT, work_data_bits(work)
        __queue_work()
    }
}

                                                      set_work_pool_and_clear_pending()
                                                      rcu_sr_normal_gp_cleanup_work() {
// new GP, wait_tail == HEAD2
rcu_sr_normal_gp_cleanup() {
    // executes all completion, but stop at HEAD1
    wait_tail->next = HEAD1;
    // done_tail = HEAD2
    smp_store_release(&rcu_state.srs_done_tail, wait_tail);
    queue_work() {
        test_and_set_bit(WORK_STRUCT_PENDING_BIT, work_data_bits(work)
        __queue_work()
    }
}
                                                          // done = HEAD2
                                                          done = smp_load_acquire(&rcu_state.srs_done_tail);
                                                          // head = HEAD1
                                                          head = done->next;
                                                          done->next = NULL;
                                                          llist_for_each_safe() {
                                                              // completes all callbacks, release HEAD1
                                                          }
                                                      }
                                                      // Process second queue
                                                      set_work_pool_and_clear_pending()
                                                      rcu_sr_normal_gp_cleanup_work() {
                                                          // done = HEAD2
                                                          done = smp_load_acquire(&rcu_state.srs_done_tail);

// new GP, wait_tail == HEAD3
rcu_sr_normal_gp_cleanup() {
    // Finds HEAD2 with ->next == NULL at the end
    rcu_sr_put_wait_head(HEAD2)
    ...

// A few more GPs later
rcu_sr_normal_gp_init() {
     HEAD2 = rcu_sr_get_wait_head();
     llist_add(HEAD2, &rcu_state.srs_next);
                                                          // head == rcu_state.srs_next
                                                          head = done->next;
                                                          done->next = NULL;
                                                          llist_for_each_safe() {
                                                              // EXECUTE CALLBACKS TOO EARLY!!!
                                                          }
                                                      }

  reply	other threads:[~2024-02-26 23:07 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-02-20 18:31 [PATCH v5 0/4] Reduce synchronize_rcu() latency(v5) Uladzislau Rezki (Sony)
2024-02-20 18:31 ` [PATCH v5 1/4] rcu: Add data structures for synchronize_rcu() Uladzislau Rezki (Sony)
2024-02-20 18:31 ` [PATCH v5 2/4] rcu: Reduce synchronize_rcu() latency Uladzislau Rezki (Sony)
2024-02-26 23:07   ` Frederic Weisbecker [this message]
2024-02-27  6:39     ` Z qiang
2024-02-27 14:37       ` Frederic Weisbecker
2024-02-27 16:16         ` Frederic Weisbecker
2024-02-27 19:35     ` Uladzislau Rezki
2024-02-28 18:04     ` Uladzislau Rezki
2024-03-04 11:55       ` Frederic Weisbecker
2024-03-04 16:23         ` Uladzislau Rezki
2024-03-04 20:07           ` Paul E. McKenney
2024-03-05  9:35             ` Uladzislau Rezki
2024-03-04 22:56           ` Frederic Weisbecker
2024-03-05  9:38             ` Uladzislau Rezki
2024-03-05 11:36               ` Frederic Weisbecker
2024-02-27 16:15   ` Frederic Weisbecker
2024-02-27 17:03   ` Frederic Weisbecker
2024-02-27 20:51   ` Joel Fernandes
2024-02-28  9:28     ` Uladzislau Rezki
     [not found]   ` <4b932245-2825-4e53-87a4-44d2892e7c13@joelfernandes.org>
2024-02-27 22:50     ` Joel Fernandes
2024-02-27 22:53       ` Joel Fernandes
2024-02-28 14:32   ` Joel Fernandes
2024-02-28 16:44     ` Joel Fernandes
2024-02-20 18:31 ` [PATCH v5 3/4] rcu: Add a trace event for synchronize_rcu_normal() Uladzislau Rezki (Sony)
2024-02-20 18:31 ` [PATCH v5 4/4] rcu: Support direct wake-up of synchronize_rcu() users Uladzislau Rezki (Sony)
2024-02-21  1:53 ` [PATCH v5 0/4] Reduce synchronize_rcu() latency(v5) Paul E. McKenney

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=Zd0ZtNu+Rt0qXkfS@lothringen \
    --to=frederic@kernel.org \
    --cc=Neeraj.Upadhyay@amd.com \
    --cc=boqun.feng@gmail.com \
    --cc=hdanton@sina.com \
    --cc=joel@joelfernandes.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=oleksiy.avramchenko@sony.com \
    --cc=paulmck@kernel.org \
    --cc=rcu@vger.kernel.org \
    --cc=urezki@gmail.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.