Re: [PATCH v3 1/2] rcu: Call rcu_nocb_rdp_deoffload() directly after rcuog/op kthreads spawn failed

From: Frederic Weisbecker
Date: Tue Mar 22 2022 - 08:30:42 EST


On Fri, Mar 18, 2022 at 04:07:18PM +0800, Zqiang wrote:
> @@ -1009,10 +1015,33 @@ static long rcu_nocb_rdp_deoffload(void *arg)
> */
> rcu_segcblist_set_flags(cblist, SEGCBLIST_RCU_CORE);
> invoke_rcu_core();
> - ret = rdp_offload_toggle(rdp, false, flags);
> - swait_event_exclusive(rdp->nocb_state_wq,
> - !rcu_segcblist_test_flags(cblist, SEGCBLIST_KTHREAD_CB |
> - SEGCBLIST_KTHREAD_GP));
> + wake_gp = rdp_offload_toggle(rdp, false, flags);
> +
> + mutex_lock(&rdp_gp->nocb_gp_kthread_mutex);
> + if (rdp_gp->nocb_gp_kthread) {
> + if (wake_gp)
> + wake_up_process(rdp_gp->nocb_gp_kthread);
> +
> + if (rdp->nocb_cb_kthread) {
> + condition = SEGCBLIST_KTHREAD_CB | SEGCBLIST_KTHREAD_GP;
> + } else {
> + /*
> + *If rcuop kthread spawn failed, direct remove SEGCBLIST_KTHREAD_CB
> + *just wait SEGCBLIST_KTHREAD_GP to be cleared.
> + */
> + condition = SEGCBLIST_KTHREAD_GP;
> + rcu_segcblist_clear_flags(&rdp->cblist,
> SEGCBLIST_KTHREAD_CB);

You may be running concurrently againt nocb_gp_wait() ->
nocb_gp_update_state_deoffloading() -> rcu_segcblist_clear_flags(cblist,
SEGCBLIST_KTHREAD_GP)

So you need to protect the flags clear with rcu_nocb lock.




> + }
> + swait_event_exclusive(rdp->nocb_state_wq,
> + !rcu_segcblist_test_flags(cblist, condition));
> + } else {
> + rcu_nocb_lock_irqsave(rdp, flags);
> + rcu_segcblist_clear_flags(&rdp->cblist,
> + SEGCBLIST_KTHREAD_CB | SEGCBLIST_KTHREAD_GP);
> + rcu_nocb_unlock_irqrestore(rdp, flags);

Like you're doing here.

Thanks!