On Mon, Sep 21, 2015 at 03:03:58PM +0200, Petr Mladek wrote: > Kthreads are currently implemented as an infinite loop. Each > has its own variant of checks for terminating, freezing, > awakening. In many cases it is unclear to say in which state > it is and sometimes it is done a wrong way. > > The plan is to convert kthreads into kthread_worker or workqueues > API. It allows to split the functionality into separate operations. > It helps to make a better structure. Also it defines a clean state > where no locks are taken, IRQs blocked, the kthread might sleep > or even be safely migrated. > > The kthread worker API is useful when we want to have a dedicated > single kthread for the work. It helps to make sure that it is > available when needed. Also it allows a better control, e.g. > define a scheduling priority. > > This patch converts RCU gp threads into the kthread worker API. > They modify the scheduling, have their own logic to bind the process. > They provide functions that are critical for the system to work > and thus deserve a dedicated kthread. > > This patch tries to split start of the grace period and the quiescent > state handling into separate works. The motivation is to avoid > wait_events inside the work. Instead it queues the works when > appropriate which is more typical for this API. > > On one hand, it should reduce spurious wakeups where the condition > in the wait_event failed and the kthread went to sleep again. > > On the other hand, there is a small race window when the other > work might get queued. We could detect and fix this situation > at the beginning of the work but it is a bit ugly. > > The patch renames the functions kthread_wake() to kthread_worker_poke() > that sounds more appropriate. > > Otherwise, the logic should stay the same. I did a lot of torturing > and I did not see any problem with the current patch. But of course, > it would deserve much more testing and reviewing before applying. Suppose I later need to add helper kthreads to parallelize grace-period initialization. How would I implement that in a freeze-friendly way? Thanx, Paul > Signed-off-by: Petr Mladek <pmladek@xxxxxxxx> > --- > kernel/rcu/tree.c | 349 ++++++++++++++++++++++++++++++----------------- > kernel/rcu/tree.h | 8 +- > kernel/rcu/tree_plugin.h | 16 +-- > 3 files changed, 237 insertions(+), 136 deletions(-) > > diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c > index 08d1d3e63b9b..e115c3aee65d 100644 > --- a/kernel/rcu/tree.c > +++ b/kernel/rcu/tree.c > @@ -482,7 +482,7 @@ void show_rcu_gp_kthreads(void) > > for_each_rcu_flavor(rsp) { > pr_info("%s: wait state: %d ->state: %#lx\n", > - rsp->name, rsp->gp_state, rsp->gp_kthread->state); > + rsp->name, rsp->gp_state, rsp->gp_worker->task->state); > /* sched_show_task(rsp->gp_kthread); */ > } > } > @@ -1179,7 +1179,7 @@ static void rcu_check_gp_kthread_starvation(struct rcu_state *rsp) > rsp->name, j - gpa, > rsp->gpnum, rsp->completed, > rsp->gp_flags, rsp->gp_state, > - rsp->gp_kthread ? rsp->gp_kthread->state : 0); > + rsp->gp_worker ? rsp->gp_worker->task->state : 0); > } > > /* > @@ -1577,19 +1577,66 @@ static int rcu_future_gp_cleanup(struct rcu_state *rsp, struct rcu_node *rnp) > } > > /* > - * Awaken the grace-period kthread for the specified flavor of RCU. > - * Don't do a self-awaken, and don't bother awakening when there is > - * nothing for the grace-period kthread to do (as in several CPUs > - * raced to awaken, and we lost), and finally don't try to awaken > - * a kthread that has not yet been created. > + * Check if it makes sense to queue the kthread work that would > + * start a new grace period. > */ > -static void rcu_gp_kthread_wake(struct rcu_state *rsp) > +static bool rcu_gp_start_ready(struct rcu_state *rsp) > { > - if (current == rsp->gp_kthread || > - !READ_ONCE(rsp->gp_flags) || > - !rsp->gp_kthread) > + /* Someone like call_rcu() requested a new grace period. */ > + if (READ_ONCE(rsp->gp_flags) & RCU_GP_FLAG_INIT) > + return true; > + > + return false; > + > +} > + > +/* > + * Check if it makes sense to immediately queue the kthread work > + * that would handle quiescent state. > + * > + * It does not check the timeout for forcing the quiescent state > + * because the delayed kthread work should be scheduled at this > + * time. > + */ > +static bool rcu_gp_handle_qs_ready(struct rcu_state *rsp) > +{ > + struct rcu_node *rnp = rcu_get_root(rsp); > + > + /* Someone like call_rcu() requested a force-quiescent-state scan. */ > + if (READ_ONCE(rsp->gp_flags) & RCU_GP_FLAG_FQS) > + return true; > + > + /* The current grace period has completed. */ > + if (!READ_ONCE(rnp->qsmask) && !rcu_preempt_blocked_readers_cgp(rnp)) > + return true; > + > + return false; > +} > + > +/* > + * Poke the kthread worker that handles grace periods for the specified > + * flavor of RCU. Return when there is nothing for the grace-period kthread > + * worker to do (as in several CPUs raced to awaken, and we lost). Also > + * don't try to use the kthread worker that has not been created yet. > + * Finally, ignore requests from the kthread servicing the worker itself. > + */ > +static void rcu_gp_kthread_worker_poke(struct rcu_state *rsp) > +{ > + if (!READ_ONCE(rsp->gp_flags) || > + !rsp->gp_worker || > + rsp->gp_worker->task == current) > return; > - wake_up(&rsp->gp_wq); > + > + if (!rcu_gp_in_progress(rsp)) { > + if (rcu_gp_start_ready(rsp)) > + queue_kthread_work(rsp->gp_worker, &rsp->gp_start_work); > + return; > + } > + > + if (rcu_gp_handle_qs_ready(rsp)) > + mod_delayed_kthread_work(rsp->gp_worker, > + &rsp->gp_handle_qs_work, > + 0); > } > > /* > @@ -1756,7 +1803,7 @@ static bool __note_gp_changes(struct rcu_state *rsp, struct rcu_node *rnp, > static void note_gp_changes(struct rcu_state *rsp, struct rcu_data *rdp) > { > unsigned long flags; > - bool needwake; > + bool needpoke; > struct rcu_node *rnp; > > local_irq_save(flags); > @@ -1769,10 +1816,10 @@ static void note_gp_changes(struct rcu_state *rsp, struct rcu_data *rdp) > return; > } > smp_mb__after_unlock_lock(); > - needwake = __note_gp_changes(rsp, rnp, rdp); > + needpoke = __note_gp_changes(rsp, rnp, rdp); > raw_spin_unlock_irqrestore(&rnp->lock, flags); > - if (needwake) > - rcu_gp_kthread_wake(rsp); > + if (needpoke) > + rcu_gp_kthread_worker_poke(rsp); > } > > static void rcu_gp_slow(struct rcu_state *rsp, int delay) > @@ -1905,25 +1952,6 @@ static int rcu_gp_init(struct rcu_state *rsp) > } > > /* > - * Helper function for wait_event_interruptible_timeout() wakeup > - * at force-quiescent-state time. > - */ > -static bool rcu_gp_fqs_check_wake(struct rcu_state *rsp) > -{ > - struct rcu_node *rnp = rcu_get_root(rsp); > - > - /* Someone like call_rcu() requested a force-quiescent-state scan. */ > - if (READ_ONCE(rsp->gp_flags) & RCU_GP_FLAG_FQS) > - return true; > - > - /* The current grace period has completed. */ > - if (!READ_ONCE(rnp->qsmask) && !rcu_preempt_blocked_readers_cgp(rnp)) > - return true; > - > - return false; > -} > - > -/* > * Do one round of quiescent-state forcing. > */ > static void rcu_gp_fqs(struct rcu_state *rsp) > @@ -2067,94 +2095,157 @@ static unsigned long normalize_jiffies_till_next_fqs(void) > } > > /* > - * Body of kthread that handles grace periods. > + * Initialize kthread worker for handling grace periods. > */ > -static int __noreturn rcu_gp_kthread(void *arg) > +static void rcu_gp_init_func(struct kthread_work *work) > { > - unsigned long timeout, j; > - struct rcu_state *rsp = arg; > - struct rcu_node *rnp = rcu_get_root(rsp); > + struct rcu_state *rsp = container_of(work, struct rcu_state, > + gp_init_work); > > rcu_bind_gp_kthread(); > - for (;;) { > > - /* Handle grace-period start. */ > - for (;;) { > - trace_rcu_grace_period(rsp->name, > - READ_ONCE(rsp->gpnum), > - TPS("reqwait")); > - rsp->gp_state = RCU_GP_WAIT_GPS; > - wait_event_interruptible(rsp->gp_wq, > - READ_ONCE(rsp->gp_flags) & > - RCU_GP_FLAG_INIT); > - rsp->gp_state = RCU_GP_DONE_GPS; > - /* Locking provides needed memory barrier. */ > - if (rcu_gp_init(rsp)) > - break; > - cond_resched_rcu_qs(); > - WRITE_ONCE(rsp->gp_activity, jiffies); > - WARN_ON(signal_pending(current)); > - trace_rcu_grace_period(rsp->name, > - READ_ONCE(rsp->gpnum), > - TPS("reqwaitsig")); > + trace_rcu_grace_period(rsp->name, > + READ_ONCE(rsp->gpnum), > + TPS("reqwait")); > + rsp->gp_state = RCU_GP_WAIT_GPS; > +} > + > +/* > + * Function for RCU kthread work that starts a new grace period. > + */ > +static void rcu_gp_start_func(struct kthread_work *work) > +{ > + unsigned long timeout; > + struct rcu_state *rsp = container_of(work, struct rcu_state, > + gp_start_work); > + > + /* > + * There is a small race window in rcu_gp_kthread_worker_poke(). > + * Check if the grace period has already started and the quiescent > + * state should get handled instead. > + */ > + if (rcu_gp_in_progress(rsp)) { > + if (rcu_gp_handle_qs_ready(rsp)) { > + mod_delayed_kthread_work(rsp->gp_worker, > + &rsp->gp_handle_qs_work, > + 0); > } > + return; > + } > > + rsp->gp_state = RCU_GP_DONE_GPS; > + if (rcu_gp_init(rsp)) { > /* Handle quiescent-state forcing. */ > rsp->first_gp_fqs = true; > timeout = normalize_jiffies_till_first_fqs(); > rsp->jiffies_force_qs = jiffies + timeout; > - for (;;) { > - trace_rcu_grace_period(rsp->name, > - READ_ONCE(rsp->gpnum), > - TPS("fqswait")); > - rsp->gp_state = RCU_GP_WAIT_FQS; > - wait_event_interruptible_timeout(rsp->gp_wq, > - rcu_gp_fqs_check_wake(rsp), > - timeout); > - rsp->gp_state = RCU_GP_DOING_FQS; > -try_again: > - /* Locking provides needed memory barriers. */ > - /* If grace period done, leave loop. */ > - if (!READ_ONCE(rnp->qsmask) && > - !rcu_preempt_blocked_readers_cgp(rnp)) > - break; > - /* If time for quiescent-state forcing, do it. */ > - if (ULONG_CMP_GE(jiffies, rsp->jiffies_force_qs) || > - (READ_ONCE(rsp->gp_flags) & RCU_GP_FLAG_FQS)) { > - trace_rcu_grace_period(rsp->name, > - READ_ONCE(rsp->gpnum), > - TPS("fqsstart")); > - rcu_gp_fqs(rsp); > - timeout = normalize_jiffies_till_next_fqs(); > - rsp->jiffies_force_qs = jiffies + timeout; > - trace_rcu_grace_period(rsp->name, > - READ_ONCE(rsp->gpnum), > - TPS("fqsend")); > - } else { > - /* Deal with stray signal. */ > - WARN_ON(signal_pending(current)); > - trace_rcu_grace_period(rsp->name, > - READ_ONCE(rsp->gpnum), > - TPS("fqswaitsig")); > - } > - cond_resched_rcu_qs(); > - WRITE_ONCE(rsp->gp_activity, jiffies); > - /* > - * Count the remaining timeout when it was a spurious > - * wakeup. Well, it is useful also when we have slept > - * in the cond_resched(). > - */ > - j = jiffies; > - if (ULONG_CMP_GE(j, rsp->jiffies_force_qs)) > - goto try_again; > - timeout = rsp->jiffies_force_qs - j; > - } > + trace_rcu_grace_period(rsp->name, > + READ_ONCE(rsp->gpnum), > + TPS("fqswait")); > + rsp->gp_state = RCU_GP_WAIT_FQS; > + queue_delayed_kthread_work(rsp->gp_worker, > + &rsp->gp_handle_qs_work, > + timeout); > + return; > + } > + > + cond_resched_rcu_qs(); > + WRITE_ONCE(rsp->gp_activity, jiffies); > + WARN_ON(signal_pending(current)); > + trace_rcu_grace_period(rsp->name, > + READ_ONCE(rsp->gpnum), > + TPS("reqwaitsig")); > + trace_rcu_grace_period(rsp->name, > + READ_ONCE(rsp->gpnum), > + TPS("reqwait")); > +} > + > +/* > + * Function for RCU kthread work that handles a quiescent state > + * and closes the related grace period. > + */ > +static void rcu_gp_handle_qs_func(struct kthread_work *work) > +{ > + unsigned long timeout, j; > + struct rcu_state *rsp = container_of(work, struct rcu_state, > + gp_handle_qs_work.work); > + struct rcu_node *rnp = rcu_get_root(rsp); > + > > + /* > + * There is a small race window in rcu_gp_kthread_worker_poke() > + * when the work might be queued more times. First, check if > + * we are already waiting for the GP start instead. > + */ > + if (!rcu_gp_in_progress(rsp)) { > + if (rcu_gp_start_ready(rsp)) > + queue_kthread_work(rsp->gp_worker, &rsp->gp_start_work); > + return; > + } > + > + /* > + * Second, we might have been queued more times to force QS. > + * Just continue waiting if we have already forced it. > + */ > + if (!rcu_gp_handle_qs_ready(rsp) && > + ULONG_CMP_LT(jiffies, rsp->jiffies_force_qs)) > + goto wait_continue; > + > + rsp->gp_state = RCU_GP_DOING_FQS; > +try_again: > + /* Locking provides needed memory barriers. */ > + /* If grace period done, leave loop. */ > + if (!READ_ONCE(rnp->qsmask) && > + !rcu_preempt_blocked_readers_cgp(rnp)) { > /* Handle grace-period end. */ > rsp->gp_state = RCU_GP_CLEANUP; > rcu_gp_cleanup(rsp); > rsp->gp_state = RCU_GP_CLEANED; > + trace_rcu_grace_period(rsp->name, > + READ_ONCE(rsp->gpnum), > + TPS("reqwait")); > + rsp->gp_state = RCU_GP_WAIT_GPS; > + return; > + } > + > + /* If time for quiescent-state forcing, do it. */ > + if (ULONG_CMP_GE(jiffies, rsp->jiffies_force_qs) || > + (READ_ONCE(rsp->gp_flags) & RCU_GP_FLAG_FQS)) { > + trace_rcu_grace_period(rsp->name, > + READ_ONCE(rsp->gpnum), > + TPS("fqsstart")); > + rcu_gp_fqs(rsp); > + timeout = normalize_jiffies_till_next_fqs(); > + rsp->jiffies_force_qs = jiffies + timeout; > + trace_rcu_grace_period(rsp->name, > + READ_ONCE(rsp->gpnum), > + TPS("fqsend")); > + } else { > + /* Deal with stray signal. */ > + WARN_ON(signal_pending(current)); > + trace_rcu_grace_period(rsp->name, > + READ_ONCE(rsp->gpnum), > + TPS("fqswaitsig")); > } > +wait_continue: > + cond_resched_rcu_qs(); > + WRITE_ONCE(rsp->gp_activity, jiffies); > + /* > + * Count the remaining timeout when it was a spurious > + * wakeup. Well, it is useful also when we have slept > + * in the cond_resched(). > + */ > + j = jiffies; > + if (ULONG_CMP_GE(j, rsp->jiffies_force_qs)) > + goto try_again; > + timeout = rsp->jiffies_force_qs - j; > + > + trace_rcu_grace_period(rsp->name, > + READ_ONCE(rsp->gpnum), > + TPS("fqswait")); > + rsp->gp_state = RCU_GP_WAIT_FQS; > + queue_delayed_kthread_work(rsp->gp_worker, &rsp->gp_handle_qs_work, > + timeout); > } > > /* > @@ -2172,7 +2263,7 @@ static bool > rcu_start_gp_advanced(struct rcu_state *rsp, struct rcu_node *rnp, > struct rcu_data *rdp) > { > - if (!rsp->gp_kthread || !cpu_needs_another_gp(rsp, rdp)) { > + if (!rsp->gp_worker || !cpu_needs_another_gp(rsp, rdp)) { > /* > * Either we have not yet spawned the grace-period > * task, this CPU does not need another grace period, > @@ -2234,7 +2325,7 @@ static void rcu_report_qs_rsp(struct rcu_state *rsp, unsigned long flags) > WARN_ON_ONCE(!rcu_gp_in_progress(rsp)); > WRITE_ONCE(rsp->gp_flags, READ_ONCE(rsp->gp_flags) | RCU_GP_FLAG_FQS); > raw_spin_unlock_irqrestore(&rcu_get_root(rsp)->lock, flags); > - rcu_gp_kthread_wake(rsp); > + rcu_gp_kthread_worker_poke(rsp); > } > > /* > @@ -2355,7 +2446,7 @@ rcu_report_qs_rdp(int cpu, struct rcu_state *rsp, struct rcu_data *rdp) > { > unsigned long flags; > unsigned long mask; > - bool needwake; > + bool needpoke; > struct rcu_node *rnp; > > rnp = rdp->mynode; > @@ -2387,12 +2478,12 @@ rcu_report_qs_rdp(int cpu, struct rcu_state *rsp, struct rcu_data *rdp) > * This GP can't end until cpu checks in, so all of our > * callbacks can be processed during the next GP. > */ > - needwake = rcu_accelerate_cbs(rsp, rnp, rdp); > + needpoke = rcu_accelerate_cbs(rsp, rnp, rdp); > > rcu_report_qs_rnp(mask, rsp, rnp, rnp->gpnum, flags); > /* ^^^ Released rnp->lock */ > - if (needwake) > - rcu_gp_kthread_wake(rsp); > + if (needpoke) > + rcu_gp_kthread_worker_poke(rsp); > } > } > > @@ -2895,7 +2986,7 @@ static void force_quiescent_state(struct rcu_state *rsp) > } > WRITE_ONCE(rsp->gp_flags, READ_ONCE(rsp->gp_flags) | RCU_GP_FLAG_FQS); > raw_spin_unlock_irqrestore(&rnp_old->lock, flags); > - rcu_gp_kthread_wake(rsp); > + rcu_gp_kthread_worker_poke(rsp); > } > > /* > @@ -2907,7 +2998,7 @@ static void > __rcu_process_callbacks(struct rcu_state *rsp) > { > unsigned long flags; > - bool needwake; > + bool needpoke; > struct rcu_data *rdp = raw_cpu_ptr(rsp->rda); > > WARN_ON_ONCE(rdp->beenonline == 0); > @@ -2919,10 +3010,10 @@ __rcu_process_callbacks(struct rcu_state *rsp) > local_irq_save(flags); > if (cpu_needs_another_gp(rsp, rdp)) { > raw_spin_lock(&rcu_get_root(rsp)->lock); /* irqs disabled. */ > - needwake = rcu_start_gp(rsp); > + needpoke = rcu_start_gp(rsp); > raw_spin_unlock_irqrestore(&rcu_get_root(rsp)->lock, flags); > - if (needwake) > - rcu_gp_kthread_wake(rsp); > + if (needpoke) > + rcu_gp_kthread_worker_poke(rsp); > } else { > local_irq_restore(flags); > } > @@ -2980,7 +3071,7 @@ static void invoke_rcu_core(void) > static void __call_rcu_core(struct rcu_state *rsp, struct rcu_data *rdp, > struct rcu_head *head, unsigned long flags) > { > - bool needwake; > + bool needpoke; > > /* > * If called from an extended quiescent state, invoke the RCU > @@ -3011,10 +3102,10 @@ static void __call_rcu_core(struct rcu_state *rsp, struct rcu_data *rdp, > > raw_spin_lock(&rnp_root->lock); > smp_mb__after_unlock_lock(); > - needwake = rcu_start_gp(rsp); > + needpoke = rcu_start_gp(rsp); > raw_spin_unlock(&rnp_root->lock); > - if (needwake) > - rcu_gp_kthread_wake(rsp); > + if (needpoke) > + rcu_gp_kthread_worker_poke(rsp); > } else { > /* Give the grace period a kick. */ > rdp->blimit = LONG_MAX; > @@ -4044,7 +4135,7 @@ static int __init rcu_spawn_gp_kthread(void) > struct rcu_node *rnp; > struct rcu_state *rsp; > struct sched_param sp; > - struct task_struct *t; > + struct kthread_worker *w; > > /* Force priority into range. */ > if (IS_ENABLED(CONFIG_RCU_BOOST) && kthread_prio < 1) > @@ -4059,16 +4150,20 @@ static int __init rcu_spawn_gp_kthread(void) > > rcu_scheduler_fully_active = 1; > for_each_rcu_flavor(rsp) { > - t = kthread_create(rcu_gp_kthread, rsp, "%s", rsp->name); > - BUG_ON(IS_ERR(t)); > + init_kthread_work(&rsp->gp_init_work, rcu_gp_init_func); > + init_kthread_work(&rsp->gp_start_work, rcu_gp_start_func); > + init_delayed_kthread_work(&rsp->gp_handle_qs_work, > + rcu_gp_handle_qs_func); > + w = create_kthread_worker("%s", rsp->name); > + BUG_ON(IS_ERR(w)); > rnp = rcu_get_root(rsp); > raw_spin_lock_irqsave(&rnp->lock, flags); > - rsp->gp_kthread = t; > + rsp->gp_worker = w; > if (kthread_prio) { > sp.sched_priority = kthread_prio; > - sched_setscheduler_nocheck(t, SCHED_FIFO, &sp); > + sched_setscheduler_nocheck(w->task, SCHED_FIFO, &sp); > } > - wake_up_process(t); > + queue_kthread_work(w, &rsp->gp_init_work); > raw_spin_unlock_irqrestore(&rnp->lock, flags); > } > rcu_spawn_nocb_kthreads(); > diff --git a/kernel/rcu/tree.h b/kernel/rcu/tree.h > index f16578a5eefe..b9490e975dd7 100644 > --- a/kernel/rcu/tree.h > +++ b/kernel/rcu/tree.h > @@ -25,6 +25,7 @@ > #include <linux/cache.h> > #include <linux/spinlock.h> > #include <linux/threads.h> > +#include <linux/kthread.h> > #include <linux/cpumask.h> > #include <linux/seqlock.h> > #include <linux/stop_machine.h> > @@ -466,7 +467,12 @@ struct rcu_state { > /* Subject to priority boost. */ > unsigned long gpnum; /* Current gp number. */ > unsigned long completed; /* # of last completed gp. */ > - struct task_struct *gp_kthread; /* Task for grace periods. */ > + struct kthread_worker *gp_worker; /* Worker for grace periods */ > + struct kthread_work gp_init_work; /* Init work for handling gp */ > + struct kthread_work gp_start_work; /* Work for starting gp */ > + struct delayed_kthread_work > + gp_handle_qs_work; /* Work for QS state handling */ > + > wait_queue_head_t gp_wq; /* Where GP task waits. */ > short gp_flags; /* Commands for GP task. */ > short gp_state; /* GP kthread sleep state. */ > diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h > index b2bf3963a0ae..55ae68530b7a 100644 > --- a/kernel/rcu/tree_plugin.h > +++ b/kernel/rcu/tree_plugin.h > @@ -1476,7 +1476,7 @@ int rcu_needs_cpu(u64 basemono, u64 *nextevt) > */ > static void rcu_prepare_for_idle(void) > { > - bool needwake; > + bool needpoke; > struct rcu_data *rdp; > struct rcu_dynticks *rdtp = this_cpu_ptr(&rcu_dynticks); > struct rcu_node *rnp; > @@ -1528,10 +1528,10 @@ static void rcu_prepare_for_idle(void) > rnp = rdp->mynode; > raw_spin_lock(&rnp->lock); /* irqs already disabled. */ > smp_mb__after_unlock_lock(); > - needwake = rcu_accelerate_cbs(rsp, rnp, rdp); > + needpoke = rcu_accelerate_cbs(rsp, rnp, rdp); > raw_spin_unlock(&rnp->lock); /* irqs remain disabled. */ > - if (needwake) > - rcu_gp_kthread_wake(rsp); > + if (needpoke) > + rcu_gp_kthread_worker_poke(rsp); > } > } > > @@ -2020,15 +2020,15 @@ static void rcu_nocb_wait_gp(struct rcu_data *rdp) > unsigned long c; > bool d; > unsigned long flags; > - bool needwake; > + bool needpoke; > struct rcu_node *rnp = rdp->mynode; > > raw_spin_lock_irqsave(&rnp->lock, flags); > smp_mb__after_unlock_lock(); > - needwake = rcu_start_future_gp(rnp, rdp, &c); > + needpoke = rcu_start_future_gp(rnp, rdp, &c); > raw_spin_unlock_irqrestore(&rnp->lock, flags); > - if (needwake) > - rcu_gp_kthread_wake(rdp->rsp); > + if (needpoke) > + rcu_gp_kthread_worker_poke(rdp->rsp); > > /* > * Wait for the grace period. Do so interruptibly to avoid messing > -- > 1.8.5.6 > -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to majordomo@xxxxxxxxx. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"dont@xxxxxxxxx"> email@xxxxxxxxx </a>