lkml.org 
[lkml]   [2022]   [Apr]   [18]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH rcu 2/6] rcutorture: Suppress debugging grace period delays during flooding
    Date
    Tree RCU supports grace-period delays using the rcutree.gp_cleanup_delay,
    rcutree.gp_init_delay, and rcutree.gp_preinit_delay kernel boot
    parameters. These delays are strictly for debugging purposes, and have
    proven quite effective at exposing bugs involving race with CPU-hotplug
    operations. However, these delays can result in false positives when
    used in conjunction with callback flooding, for example, those generated
    by the rcutorture.fwd_progress kernel boot parameter.

    This commit therefore suppresses grace-period delays while callback
    flooding is in progress.

    Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
    ---
    kernel/rcu/rcu.h | 4 ++++
    kernel/rcu/rcutorture.c | 4 ++++
    kernel/rcu/tree.c | 32 +++++++++++++++++++++++++++++---
    3 files changed, 37 insertions(+), 3 deletions(-)

    diff --git a/kernel/rcu/rcu.h b/kernel/rcu/rcu.h
    index 24b5f2c2de87..7a221393fcdb 100644
    --- a/kernel/rcu/rcu.h
    +++ b/kernel/rcu/rcu.h
    @@ -523,6 +523,8 @@ static inline bool rcu_check_boost_fail(unsigned long gp_state, int *cpup) { ret
    static inline void show_rcu_gp_kthreads(void) { }
    static inline int rcu_get_gp_kthreads_prio(void) { return 0; }
    static inline void rcu_fwd_progress_check(unsigned long j) { }
    +static inline void rcu_gp_slow_register(atomic_t *rgssp) { }
    +static inline void rcu_gp_slow_unregister(atomic_t *rgssp) { }
    #else /* #ifdef CONFIG_TINY_RCU */
    bool rcu_dynticks_zero_in_eqs(int cpu, int *vp);
    unsigned long rcu_get_gp_seq(void);
    @@ -535,6 +537,8 @@ void rcu_fwd_progress_check(unsigned long j);
    void rcu_force_quiescent_state(void);
    extern struct workqueue_struct *rcu_gp_wq;
    extern struct workqueue_struct *rcu_par_gp_wq;
    +void rcu_gp_slow_register(atomic_t *rgssp);
    +void rcu_gp_slow_unregister(atomic_t *rgssp);
    #endif /* #else #ifdef CONFIG_TINY_RCU */

    #ifdef CONFIG_RCU_NOCB_CPU
    diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c
    index 55d049c39608..f37b7a01dcd0 100644
    --- a/kernel/rcu/rcutorture.c
    +++ b/kernel/rcu/rcutorture.c
    @@ -2916,10 +2916,12 @@ rcu_torture_cleanup(void)
    pr_info("%s: Invoking %pS().\n", __func__, cur_ops->cb_barrier);
    cur_ops->cb_barrier();
    }
    + rcu_gp_slow_unregister(NULL);
    return;
    }
    if (!cur_ops) {
    torture_cleanup_end();
    + rcu_gp_slow_unregister(NULL);
    return;
    }

    @@ -3016,6 +3018,7 @@ rcu_torture_cleanup(void)
    else
    rcu_torture_print_module_parms(cur_ops, "End of test: SUCCESS");
    torture_cleanup_end();
    + rcu_gp_slow_unregister(&rcu_fwd_cb_nodelay);
    }

    #ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD
    @@ -3320,6 +3323,7 @@ rcu_torture_init(void)
    if (object_debug)
    rcu_test_debug_objects();
    torture_init_end();
    + rcu_gp_slow_register(&rcu_fwd_cb_nodelay);
    return 0;

    unwind:
    diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
    index a4b8189455d5..db67dae8ed88 100644
    --- a/kernel/rcu/tree.c
    +++ b/kernel/rcu/tree.c
    @@ -1705,11 +1705,37 @@ static void note_gp_changes(struct rcu_data *rdp)
    rcu_gp_kthread_wake();
    }

    +static atomic_t *rcu_gp_slow_suppress;
    +
    +/* Register a counter to suppress debugging grace-period delays. */
    +void rcu_gp_slow_register(atomic_t *rgssp)
    +{
    + WARN_ON_ONCE(rcu_gp_slow_suppress);
    +
    + WRITE_ONCE(rcu_gp_slow_suppress, rgssp);
    +}
    +EXPORT_SYMBOL_GPL(rcu_gp_slow_register);
    +
    +/* Unregister a counter, with NULL for not caring which. */
    +void rcu_gp_slow_unregister(atomic_t *rgssp)
    +{
    + WARN_ON_ONCE(rgssp && rgssp != rcu_gp_slow_suppress);
    +
    + WRITE_ONCE(rcu_gp_slow_suppress, NULL);
    +}
    +EXPORT_SYMBOL_GPL(rcu_gp_slow_unregister);
    +
    +static bool rcu_gp_slow_is_suppressed(void)
    +{
    + atomic_t *rgssp = READ_ONCE(rcu_gp_slow_suppress);
    +
    + return rgssp && atomic_read(rgssp);
    +}
    +
    static void rcu_gp_slow(int delay)
    {
    - if (delay > 0 &&
    - !(rcu_seq_ctr(rcu_state.gp_seq) %
    - (rcu_num_nodes * PER_RCU_NODE_PERIOD * delay)))
    + if (!rcu_gp_slow_is_suppressed() && delay > 0 &&
    + !(rcu_seq_ctr(rcu_state.gp_seq) % (rcu_num_nodes * PER_RCU_NODE_PERIOD * delay)))
    schedule_timeout_idle(delay);
    }

    --
    2.31.1.189.g2e36527f23
    \
     
     \ /
      Last update: 2022-04-19 02:08    [W:4.207 / U:0.020 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site