lkml.org 
[lkml]   [2021]   [Jan]   [28]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 15/16] rcu/nocb: Prepare for finegrained deferred wakeup
    Date
    Provide a way to tune the deferred wakeup level we want to perform from
    a safe wakeup point. Currently those sites are:

    * nocb_timer
    * user/idle/guest entry
    * CPU down
    * softirq/rcuc

    All of these sites perform the wake up for both RCU_NOCB_WAKE and
    RCU_NOCB_WAKE_FORCE.

    In order to merge nocb_timer and nocb_bypass_timer together, we plan to
    add a new RCU_NOCB_WAKE_BYPASS that really want to be deferred until
    a timer fires so that we don't wake up the NOCB-gp kthread too early.

    To prepare for that, integrate a wake up level/limit that a callsite is
    deemed to perform.

    Signed-off-by: Frederic Weisbecker <frederic@kernel.org>
    Cc: Josh Triplett <josh@joshtriplett.org>
    Cc: Lai Jiangshan <jiangshanlai@gmail.com>
    Cc: Joel Fernandes <joel@joelfernandes.org>
    Cc: Neeraj Upadhyay <neeraju@codeaurora.org>
    Cc: Boqun Feng <boqun.feng@gmail.com>
    ---
    kernel/rcu/tree.c | 2 +-
    kernel/rcu/tree.h | 2 +-
    kernel/rcu/tree_plugin.h | 15 ++++++++-------
    3 files changed, 10 insertions(+), 9 deletions(-)

    diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
    index f74a9ba62c12..e31b1d8fde93 100644
    --- a/kernel/rcu/tree.c
    +++ b/kernel/rcu/tree.c
    @@ -3813,7 +3813,7 @@ static int rcu_pending(int user)
    check_cpu_stall(rdp);

    /* Does this CPU need a deferred NOCB wakeup? */
    - if (rcu_nocb_need_deferred_wakeup(rdp))
    + if (rcu_nocb_need_deferred_wakeup(rdp, RCU_NOCB_WAKE))
    return 1;

    /* Is this a nohz_full CPU in userspace or idle? (Ignore RCU if so.) */
    diff --git a/kernel/rcu/tree.h b/kernel/rcu/tree.h
    index b280a843bd2c..2510e86265c1 100644
    --- a/kernel/rcu/tree.h
    +++ b/kernel/rcu/tree.h
    @@ -433,7 +433,7 @@ static bool rcu_nocb_try_bypass(struct rcu_data *rdp, struct rcu_head *rhp,
    bool *was_alldone, unsigned long flags);
    static void __call_rcu_nocb_wake(struct rcu_data *rdp, bool was_empty,
    unsigned long flags);
    -static int rcu_nocb_need_deferred_wakeup(struct rcu_data *rdp);
    +static int rcu_nocb_need_deferred_wakeup(struct rcu_data *rdp, int level);
    static bool do_nocb_deferred_wakeup(struct rcu_data *rdp);
    static void rcu_boot_init_nocb_percpu_data(struct rcu_data *rdp);
    static void rcu_spawn_cpu_nocb_kthread(int cpu);
    diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h
    index b1f76f341c66..162dda3714f1 100644
    --- a/kernel/rcu/tree_plugin.h
    +++ b/kernel/rcu/tree_plugin.h
    @@ -2354,13 +2354,14 @@ static int rcu_nocb_cb_kthread(void *arg)
    }

    /* Is a deferred wakeup of rcu_nocb_kthread() required? */
    -static int rcu_nocb_need_deferred_wakeup(struct rcu_data *rdp)
    +static int rcu_nocb_need_deferred_wakeup(struct rcu_data *rdp, int level)
    {
    - return READ_ONCE(rdp->nocb_defer_wakeup) > RCU_NOCB_WAKE_NOT;
    + return READ_ONCE(rdp->nocb_defer_wakeup) >= level;
    }

    /* Do a deferred wakeup of rcu_nocb_kthread(). */
    -static bool do_nocb_deferred_wakeup_common(struct rcu_data *rdp)
    +static bool do_nocb_deferred_wakeup_common(struct rcu_data *rdp,
    + int level)
    {
    unsigned long flags;
    int ndw;
    @@ -2369,7 +2370,7 @@ static bool do_nocb_deferred_wakeup_common(struct rcu_data *rdp)

    raw_spin_lock_irqsave(&rdp_gp->nocb_gp_lock, flags);

    - if (!rcu_nocb_need_deferred_wakeup(rdp_gp)) {
    + if (!rcu_nocb_need_deferred_wakeup(rdp_gp, level)) {
    raw_spin_unlock_irqrestore(&rdp_gp->nocb_gp_lock, flags);;
    return false;
    }
    @@ -2385,7 +2386,7 @@ static void do_nocb_deferred_wakeup_timer(struct timer_list *t)
    {
    struct rcu_data *rdp = from_timer(rdp, t, nocb_timer);

    - do_nocb_deferred_wakeup_common(rdp);
    + do_nocb_deferred_wakeup_common(rdp, RCU_NOCB_WAKE);
    }

    /*
    @@ -2398,8 +2399,8 @@ static bool do_nocb_deferred_wakeup(struct rcu_data *rdp)
    if (!rdp->nocb_gp_rdp)
    return false;

    - if (rcu_nocb_need_deferred_wakeup(rdp->nocb_gp_rdp))
    - return do_nocb_deferred_wakeup_common(rdp);
    + if (rcu_nocb_need_deferred_wakeup(rdp->nocb_gp_rdp, RCU_NOCB_WAKE))
    + return do_nocb_deferred_wakeup_common(rdp, RCU_NOCB_WAKE);
    return false;
    }

    --
    2.25.1
    \
     
     \ /
      Last update: 2021-01-28 18:22    [W:3.590 / U:0.212 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site