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!