]> Git Repo - J-linux.git/commitdiff
Merge branches 'docs.2022.04.20a', 'fixes.2022.04.20a', 'nocb.2022.04.11b', 'rcu...
authorPaul E. McKenney <[email protected]>
Tue, 3 May 2022 17:21:40 +0000 (10:21 -0700)
committerPaul E. McKenney <[email protected]>
Tue, 3 May 2022 17:21:40 +0000 (10:21 -0700)
docs.2022.04.20a: Documentation updates.
fixes.2022.04.20a: Miscellaneous fixes.
nocb.2022.04.11b: Callback-offloading updates.
rcu-tasks.2022.04.11b: RCU-tasks updates.
srcu.2022.05.03a: Put SRCU on a memory diet.
torture.2022.04.11b: Torture-test updates.
torture-tasks.2022.04.20a: Avoid torture testing changing RCU configuration.
torturescript.2022.04.20a: Torture-test scripting updates.

1  2  3  4  5  6  7  8 
Documentation/admin-guide/kernel-parameters.txt
kernel/rcu/rcu.h
kernel/rcu/rcutorture.c
kernel/rcu/tree.c
kernel/rcu/tree.h
kernel/rcu/tree_plugin.h
tools/testing/selftests/rcutorture/bin/torture.sh
tools/testing/selftests/rcutorture/configs/rcu/TRACE01

index 3f1cc5e317ed4a5ad001082c9c589b6008f68db9,645c4c001b16ba3e140f4af5ff6662b4158c1c03,3f1cc5e317ed4a5ad001082c9c589b6008f68db9,babc701d4864ad17e19b21ed774e0f0547395bc8,0a094bb2d72238d6193a21505947e153cbed25e9,3f1cc5e317ed4a5ad001082c9c589b6008f68db9,3f1cc5e317ed4a5ad001082c9c589b6008f68db9,3f1cc5e317ed4a5ad001082c9c589b6008f68db9..82dd253e5dbdcc2d348a8c034a585f3512d61f66
                                number avoids disturbing real-time workloads,
                                but lengthens grace periods.
        
+++ ++++        rcupdate.rcu_task_stall_info= [KNL]
+++ ++++                        Set initial timeout in jiffies for RCU task stall
+++ ++++                        informational messages, which give some indication
+++ ++++                        of the problem for those not patient enough to
+++ ++++                        wait for ten minutes.  Informational messages are
+++ ++++                        only printed prior to the stall-warning message
+++ ++++                        for a given grace period. Disable with a value
+++ ++++                        less than or equal to zero.  Defaults to ten
+++ ++++                        seconds.  A change in value does not take effect
+++ ++++                        until the beginning of the next grace period.
+++ ++++
+++ ++++        rcupdate.rcu_task_stall_info_mult= [KNL]
+++ ++++                        Multiplier for time interval between successive
+++ ++++                        RCU task stall informational messages for a given
+++ ++++                        RCU tasks grace period.  This value is clamped
+++ ++++                        to one through ten, inclusive.  It defaults to
+++ ++++                        the value three, so that the first informational
+++ ++++                        message is printed 10 seconds into the grace
+++ ++++                        period, the second at 40 seconds, the third at
+++ ++++                        160 seconds, and then the stall warning at 600
+++ ++++                        seconds would prevent a fourth at 640 seconds.
+++ ++++
                rcupdate.rcu_task_stall_timeout= [KNL]
--- ----                        Set timeout in jiffies for RCU task stall warning
--- ----                        messages.  Disable with a value less than or equal
--- ----                        to zero.
+++ ++++                        Set timeout in jiffies for RCU task stall
+++ ++++                        warning messages.  Disable with a value less
+++ ++++                        than or equal to zero.  Defaults to ten minutes.
+++ ++++                        A change in value does not take effect until
+++ ++++                        the beginning of the next grace period.
        
                rcupdate.rcu_self_test= [KNL]
                                Run the RCU early boot self tests
                smart2=         [HW]
                                Format: <io1>[,<io2>[,...,<io8>]]
        
+ ++++++        smp.csd_lock_timeout= [KNL]
+ ++++++                        Specify the period of time in milliseconds
+ ++++++                        that smp_call_function() and friends will wait
+ ++++++                        for a CPU to release the CSD lock.  This is
+ ++++++                        useful when diagnosing bugs involving CPUs
+ ++++++                        disabling interrupts for extended periods
+ ++++++                        of time.  Defaults to 5,000 milliseconds, and
+ ++++++                        setting a value of zero disables this feature.
+ ++++++                        This feature may be more efficiently disabled
+ ++++++                        using the csdlock_debug- kernel parameter.
+ ++++++
                smsc-ircc2.nopnp        [HW] Don't use PNP to discover SMC devices
                smsc-ircc2.ircc_cfg=    [HW] Device configuration I/O port
                smsc-ircc2.ircc_sir=    [HW] SIR base I/O port
                                off:    Disable mitigation and remove
                                        performance impact to RDRAND and RDSEED
        
++++ +++        srcutree.big_cpu_lim [KNL]
++++ +++                        Specifies the number of CPUs constituting a
++++ +++                        large system, such that srcu_struct structures
++++ +++                        should immediately allocate an srcu_node array.
++++ +++                        This kernel-boot parameter defaults to 128,
++++ +++                        but takes effect only when the low-order four
++++ +++                        bits of srcutree.convert_to_big is equal to 3
++++ +++                        (decide at boot).
++++ +++
++++ +++        srcutree.convert_to_big [KNL]
++++ +++                        Specifies under what conditions an SRCU tree
++++ +++                        srcu_struct structure will be converted to big
++++ +++                        form, that is, with an rcu_node tree:
++++ +++
++++ +++                                   0:  Never.
++++ +++                                   1:  At init_srcu_struct() time.
++++ +++                                   2:  When rcutorture decides to.
++++ +++                                   3:  Decide at boot time (default).
++++ +++                                0x1X:  Above plus if high contention.
++++ +++
++++ +++                        Either way, the srcu_node tree will be sized based
++++ +++                        on the actual runtime number of CPUs (nr_cpu_ids)
++++ +++                        instead of the compile-time CONFIG_NR_CPUS.
++++ +++
                srcutree.counter_wrap_check [KNL]
                                Specifies how frequently to check for
                                grace-period sequence counter wrap for the
                                expediting.  Set to zero to disable automatic
                                expediting.
        
++++ +++        srcutree.small_contention_lim [KNL]
++++ +++                        Specifies the number of update-side contention
++++ +++                        events per jiffy will be tolerated before
++++ +++                        initiating a conversion of an srcu_struct
++++ +++                        structure to big form.  Note that the value of
++++ +++                        srcutree.convert_to_big must have the 0x10 bit
++++ +++                        set for contention-based conversions to occur.
++++ +++
                ssbd=           [ARM64,HW]
                                Speculative Store Bypass Disable control
        
diff --combined kernel/rcu/rcu.h
index 24b5f2c2de87b4c37b0d3c52c3189f26d669b455,24b5f2c2de87b4c37b0d3c52c3189f26d669b455,4c53a2ccf7114adc2a1f044996d9aa2d4a1e1cc0,24b5f2c2de87b4c37b0d3c52c3189f26d669b455,24b5f2c2de87b4c37b0d3c52c3189f26d669b455,7a221393fcdbdd135582989c8991cb83bc656642,24b5f2c2de87b4c37b0d3c52c3189f26d669b455,24b5f2c2de87b4c37b0d3c52c3189f26d669b455..a985dfc2ce26e37b534510ab83615d44caf1631a
@@@@@@@@@ -523,6 -523,6 -523,6 -523,6 -523,6 -523,8 -523,6 -523,6 +523,8 @@@@@@@@@ static inline bool rcu_check_boost_fail
        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,13 -535,13 -535,11 -535,13 -535,13 -537,15 -535,13 -535,13 +537,13 @@@@@@@@@ void rcu_fwd_progress_check(unsigned lo
        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
-- -----bool rcu_is_nocb_cpu(int cpu);
        void rcu_bind_current_to_nocb(void);
        #else
-- -----static inline bool rcu_is_nocb_cpu(int cpu) { return false; }
        static inline void rcu_bind_current_to_nocb(void) { }
        #endif
        
diff --combined kernel/rcu/rcutorture.c
index 55d049c39608f581bc8157fc0fbb6264c2ba0bde,55d049c39608f581bc8157fc0fbb6264c2ba0bde,55d049c39608f581bc8157fc0fbb6264c2ba0bde,55d049c39608f581bc8157fc0fbb6264c2ba0bde,55d049c39608f581bc8157fc0fbb6264c2ba0bde,f1292d9e86b5a050ed6ce14dec56f2252e81cb33,d528245108c20b738866765d78b607f7b219e295,55d049c39608f581bc8157fc0fbb6264c2ba0bde..7120165a93426c282c7d9f6d3a87a4738ac52905
@@@@@@@@@ -737,6 -737,6 -737,6 -737,6 -737,6 -737,6 -737,50 -737,6 +737,50 @@@@@@@@@ static struct rcu_torture_ops busted_sr
                .name           = "busted_srcud"
        };
        
++++++ +/*
++++++ + * Definitions for trivial CONFIG_PREEMPT=n-only torture testing.
++++++ + * This implementation does not necessarily work well with CPU hotplug.
++++++ + */
++++++ +
++++++ +static void synchronize_rcu_trivial(void)
++++++ +{
++++++ +        int cpu;
++++++ +
++++++ +        for_each_online_cpu(cpu) {
++++++ +                rcutorture_sched_setaffinity(current->pid, cpumask_of(cpu));
++++++ +                WARN_ON_ONCE(raw_smp_processor_id() != cpu);
++++++ +        }
++++++ +}
++++++ +
++++++ +static int rcu_torture_read_lock_trivial(void) __acquires(RCU)
++++++ +{
++++++ +        preempt_disable();
++++++ +        return 0;
++++++ +}
++++++ +
++++++ +static void rcu_torture_read_unlock_trivial(int idx) __releases(RCU)
++++++ +{
++++++ +        preempt_enable();
++++++ +}
++++++ +
++++++ +static struct rcu_torture_ops trivial_ops = {
++++++ +        .ttype          = RCU_TRIVIAL_FLAVOR,
++++++ +        .init           = rcu_sync_torture_init,
++++++ +        .readlock       = rcu_torture_read_lock_trivial,
++++++ +        .read_delay     = rcu_read_delay,  /* just reuse rcu's version. */
++++++ +        .readunlock     = rcu_torture_read_unlock_trivial,
++++++ +        .readlock_held  = torture_readlock_not_held,
++++++ +        .get_gp_seq     = rcu_no_completed,
++++++ +        .sync           = synchronize_rcu_trivial,
++++++ +        .exp_sync       = synchronize_rcu_trivial,
++++++ +        .fqs            = NULL,
++++++ +        .stats          = NULL,
++++++ +        .irq_capable    = 1,
++++++ +        .name           = "trivial"
++++++ +};
++++++ +
++++++ +#ifdef CONFIG_TASKS_RCU
++++++ +
        /*
         * Definitions for RCU-tasks torture testing.
         */
@@@@@@@@@ -780,47 -780,47 -780,47 -780,47 -780,47 -780,47 -824,16 -780,47 +824,16 @@@@@@@@@ static struct rcu_torture_ops tasks_op
                .name           = "tasks"
        };
        
------ -/*
------ - * Definitions for trivial CONFIG_PREEMPT=n-only torture testing.
------ - * This implementation does not necessarily work well with CPU hotplug.
------ - */
++++++ +#define TASKS_OPS &tasks_ops,
        
------ -static void synchronize_rcu_trivial(void)
------ -{
------ -        int cpu;
++++++ +#else // #ifdef CONFIG_TASKS_RCU
        
------ -        for_each_online_cpu(cpu) {
------ -                rcutorture_sched_setaffinity(current->pid, cpumask_of(cpu));
------ -                WARN_ON_ONCE(raw_smp_processor_id() != cpu);
------ -        }
------ -}
++++++ +#define TASKS_OPS
        
------ -static int rcu_torture_read_lock_trivial(void) __acquires(RCU)
------ -{
------ -        preempt_disable();
------ -        return 0;
------ -}
++++++ +#endif // #else #ifdef CONFIG_TASKS_RCU
        
------ -static void rcu_torture_read_unlock_trivial(int idx) __releases(RCU)
------ -{
------ -        preempt_enable();
------ -}
        
------ -static struct rcu_torture_ops trivial_ops = {
------ -        .ttype          = RCU_TRIVIAL_FLAVOR,
------ -        .init           = rcu_sync_torture_init,
------ -        .readlock       = rcu_torture_read_lock_trivial,
------ -        .read_delay     = rcu_read_delay,  /* just reuse rcu's version. */
------ -        .readunlock     = rcu_torture_read_unlock_trivial,
------ -        .readlock_held  = torture_readlock_not_held,
------ -        .get_gp_seq     = rcu_no_completed,
------ -        .sync           = synchronize_rcu_trivial,
------ -        .exp_sync       = synchronize_rcu_trivial,
------ -        .fqs            = NULL,
------ -        .stats          = NULL,
------ -        .irq_capable    = 1,
------ -        .name           = "trivial"
------ -};
++++++ +#ifdef CONFIG_TASKS_RUDE_RCU
        
        /*
         * Definitions for rude RCU-tasks torture testing.
@@@@@@@@@ -851,6 -851,6 -851,6 -851,6 -851,6 -851,6 -864,17 -851,6 +864,17 @@@@@@@@@ static struct rcu_torture_ops tasks_rud
                .name           = "tasks-rude"
        };
        
++++++ +#define TASKS_RUDE_OPS &tasks_rude_ops,
++++++ +
++++++ +#else // #ifdef CONFIG_TASKS_RUDE_RCU
++++++ +
++++++ +#define TASKS_RUDE_OPS
++++++ +
++++++ +#endif // #else #ifdef CONFIG_TASKS_RUDE_RCU
++++++ +
++++++ +
++++++ +#ifdef CONFIG_TASKS_TRACE_RCU
++++++ +
        /*
         * Definitions for tracing RCU-tasks torture testing.
         */
@@@@@@@@@ -893,6 -893,6 -893,6 -893,6 -893,6 -893,6 -917,15 -893,6 +917,15 @@@@@@@@@ static struct rcu_torture_ops tasks_tra
                .name           = "tasks-tracing"
        };
        
++++++ +#define TASKS_TRACING_OPS &tasks_tracing_ops,
++++++ +
++++++ +#else // #ifdef CONFIG_TASKS_TRACE_RCU
++++++ +
++++++ +#define TASKS_TRACING_OPS
++++++ +
++++++ +#endif // #else #ifdef CONFIG_TASKS_TRACE_RCU
++++++ +
++++++ +
        static unsigned long rcutorture_seq_diff(unsigned long new, unsigned long old)
        {
                if (!cur_ops->gp_diff)
@@@@@@@@@ -1178,7 -1178,7 -1178,7 -1178,7 -1178,7 -1178,7 -1211,7 -1178,7 +1211,7 @@@@@@@@@ rcu_torture_writer(void *arg
                                 " GP expediting controlled from boot/sysfs for %s.\n",
                                 torture_type, cur_ops->name);
                if (WARN_ONCE(nsynctypes == 0,
----- --                      "rcu_torture_writer: No update-side primitives.\n")) {
+++++ ++                      "%s: No update-side primitives.\n", __func__)) {
                        /*
                         * No updates primitives, so don't try updating.
                         * The resulting test won't be testing much, hence the
                         */
                        rcu_torture_writer_state = RTWS_STOPPING;
                        torture_kthread_stopping("rcu_torture_writer");
+++++ ++                return 0;
                }
        
                do {
@@@@@@@@@ -1322,6 -1322,6 -1322,6 -1322,6 -1322,6 -1323,17 -1355,6 -1322,6 +1356,17 @@@@@@@@@ rcu_torture_fakewriter(void *arg
                VERBOSE_TOROUT_STRING("rcu_torture_fakewriter task started");
                set_user_nice(current, MAX_NICE);
        
+++++ ++        if (WARN_ONCE(nsynctypes == 0,
+++++ ++                      "%s: No update-side primitives.\n", __func__)) {
+++++ ++                /*
+++++ ++                 * No updates primitives, so don't try updating.
+++++ ++                 * The resulting test won't be testing much, hence the
+++++ ++                 * above WARN_ONCE().
+++++ ++                 */
+++++ ++                torture_kthread_stopping("rcu_torture_fakewriter");
+++++ ++                return 0;
+++++ ++        }
+++++ ++
                do {
                        torture_hrtimeout_jiffies(torture_random(&rand) % 10, &rand);
                        if (cur_ops->cb_barrier != NULL &&
@@@@@@@@@ -2916,10 -2916,10 -2916,10 -2916,10 -2916,10 -2928,12 -2949,10 -2916,10 +2961,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;
                }
        
                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
@@@@@@@@@ -3096,9 -3096,9 -3096,9 -3096,9 -3096,9 -3111,9 -3129,9 -3096,9 +3144,9 @@@@@@@@@ rcu_torture_init(void
                int flags = 0;
                unsigned long gp_seq = 0;
                static struct rcu_torture_ops *torture_ops[] = {
------ -                &rcu_ops, &rcu_busted_ops, &srcu_ops, &srcud_ops,
------ -                &busted_srcud_ops, &tasks_ops, &tasks_rude_ops,
------ -                &tasks_tracing_ops, &trivial_ops,
++++++ +                &rcu_ops, &rcu_busted_ops, &srcu_ops, &srcud_ops, &busted_srcud_ops,
++++++ +                TASKS_OPS TASKS_RUDE_OPS TASKS_TRACING_OPS
++++++ +                &trivial_ops,
                };
        
                if (!torture_init_begin(torture_type, verbose))
                if (object_debug)
                        rcu_test_debug_objects();
                torture_init_end();
+++++ ++        rcu_gp_slow_register(&rcu_fwd_cb_nodelay);
                return 0;
        
        unwind:
diff --combined kernel/rcu/tree.c
index a4b8189455d5eca9694101d779346a269597994b,d3caa82b9954e9ee462c911ce37134a85f96a843,9f7441a78f9045ff5635c0f23e98763f9cb12c0d,8dbfb63f039106410e2cbb6f7c4aa9425a69b4f4,a4b8189455d5eca9694101d779346a269597994b,db67dae8ed882b25573b449b72fcd13e15595910,a4b8189455d5eca9694101d779346a269597994b,a4b8189455d5eca9694101d779346a269597994b..75a35b7adbfa8e17514f706c946cc881a07beb9d
@@@@@@@@@ -1679,6 -1679,8 -1679,6 -1679,6 -1679,6 -1679,6 -1679,6 -1679,6 +1679,8 @@@@@@@@@ static bool __note_gp_changes(struct rc
                rdp->gp_seq = rnp->gp_seq;  /* Remember new grace-period state. */
                if (ULONG_CMP_LT(rdp->gp_seq_needed, rnp->gp_seq_needed) || rdp->gpwrap)
                        WRITE_ONCE(rdp->gp_seq_needed, rnp->gp_seq_needed);
+ ++++++        if (IS_ENABLED(CONFIG_PROVE_RCU) && READ_ONCE(rdp->gpwrap))
+ ++++++                WRITE_ONCE(rdp->last_sched_clock, jiffies);
                WRITE_ONCE(rdp->gpwrap, false);
                rcu_gpnum_ovf(rnp, rdp);
                return ret;
@@@@@@@@@ -1705,11 -1707,11 -1705,11 -1705,11 -1705,11 -1705,37 -1705,11 -1705,11 +1707,37 @@@@@@@@@ static void note_gp_changes(struct rcu_
                        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);
        }
        
@@@@@@@@@ -2096,14 -2098,29 -2096,14 -2096,14 -2096,14 -2122,14 -2096,14 -2096,14 +2124,29 @@@@@@@@@ static noinline void rcu_gp_cleanup(voi
                /* Advance CBs to reduce false positives below. */
                offloaded = rcu_rdp_is_offloaded(rdp);
                if ((offloaded || !rcu_accelerate_cbs(rnp, rdp)) && needgp) {
+ ++++++
+ ++++++                // We get here if a grace period was needed (“needgp”)
+ ++++++                // and the above call to rcu_accelerate_cbs() did not set
+ ++++++                // the RCU_GP_FLAG_INIT bit in ->gp_state (which records
+ ++++++                // the need for another grace period).  The purpose
+ ++++++                // of the “offloaded” check is to avoid invoking
+ ++++++                // rcu_accelerate_cbs() on an offloaded CPU because we do not
+ ++++++                // hold the ->nocb_lock needed to safely access an offloaded
+ ++++++                // ->cblist.  We do not want to acquire that lock because
+ ++++++                // it can be heavily contended during callback floods.
+ ++++++
                        WRITE_ONCE(rcu_state.gp_flags, RCU_GP_FLAG_INIT);
                        WRITE_ONCE(rcu_state.gp_req_activity, jiffies);
- ------                trace_rcu_grace_period(rcu_state.name,
- ------                                       rcu_state.gp_seq,
- ------                                       TPS("newreq"));
+ ++++++                trace_rcu_grace_period(rcu_state.name, rcu_state.gp_seq, TPS("newreq"));
                } else {
- ------                WRITE_ONCE(rcu_state.gp_flags,
- ------                           rcu_state.gp_flags & RCU_GP_FLAG_INIT);
+ ++++++
+ ++++++                // We get here either if there is no need for an
+ ++++++                // additional grace period or if rcu_accelerate_cbs() has
+ ++++++                // already set the RCU_GP_FLAG_INIT bit in ->gp_flags. 
+ ++++++                // So all we need to do is to clear all of the other
+ ++++++                // ->gp_flags bits.
+ ++++++
+ ++++++                WRITE_ONCE(rcu_state.gp_flags, rcu_state.gp_flags & RCU_GP_FLAG_INIT);
                }
                raw_spin_unlock_irq_rcu_node(rnp);
        
@@@@@@@@@ -2609,6 -2626,13 -2609,6 -2609,6 -2609,6 -2635,6 -2609,6 -2609,6 +2652,13 @@@@@@@@@ static void rcu_do_batch(struct rcu_dat
         */
        void rcu_sched_clock_irq(int user)
        {
+ ++++++        unsigned long j;
+ ++++++
+ ++++++        if (IS_ENABLED(CONFIG_PROVE_RCU)) {
+ ++++++                j = jiffies;
+ ++++++                WARN_ON_ONCE(time_before(j, __this_cpu_read(rcu_data.last_sched_clock)));
+ ++++++                __this_cpu_write(rcu_data.last_sched_clock, j);
+ ++++++        }
                trace_rcu_utilization(TPS("Start scheduler-tick"));
                lockdep_assert_irqs_disabled();
                raw_cpu_inc(rcu_data.ticks_this_gp);
                rcu_flavor_sched_clock_irq(user);
                if (rcu_pending(user))
                        invoke_rcu_core();
+++ ++++        if (user)
+++ ++++                rcu_tasks_classic_qs(current, false);
                lockdep_assert_irqs_disabled();
        
                trace_rcu_utilization(TPS("End scheduler-tick"));
@@@@@@@@@ -3717,7 -3741,9 -3717,7 -3719,7 -3717,7 -3743,7 -3717,7 -3717,7 +3769,9 @@@@@@@@@ static int rcu_blocking_is_gp(void
        {
                int ret;
        
- ------        if (IS_ENABLED(CONFIG_PREEMPTION))
+ ++++++        // Invoking preempt_model_*() too early gets a splat.
+ ++++++        if (rcu_scheduler_active == RCU_SCHEDULER_INACTIVE ||
+ ++++++            preempt_model_full() || preempt_model_rt())
                        return rcu_scheduler_active == RCU_SCHEDULER_INACTIVE;
                might_sleep();  /* Check for RCU read-side critical section. */
                preempt_disable();
@@@@@@@@@ -4179,6 -4205,7 -4179,6 -4181,6 -4179,6 -4205,6 -4179,6 -4179,6 +4233,7 @@@@@@@@@ rcu_boot_init_percpu_data(int cpu
                rdp->rcu_ofl_gp_flags = RCU_GP_CLEANED;
                rdp->rcu_onl_gp_seq = rcu_state.gp_seq;
                rdp->rcu_onl_gp_flags = RCU_GP_CLEANED;
+ ++++++        rdp->last_sched_clock = jiffies;
                rdp->cpu = cpu;
                rcu_boot_init_nocb_percpu_data(rdp);
        }
@@@@@@@@@ -4480,6 -4507,6 -4480,7 -4482,6 -4480,6 -4506,6 -4480,6 -4480,6 +4535,7 @@@@@@@@@ static int __init rcu_spawn_gp_kthread(
                struct rcu_node *rnp;
                struct sched_param sp;
                struct task_struct *t;
++ +++++        struct rcu_data *rdp = this_cpu_ptr(&rcu_data);
        
                rcu_scheduler_fully_active = 1;
                t = kthread_create(rcu_gp_kthread, NULL, "%s", rcu_state.name);
                smp_store_release(&rcu_state.gp_kthread, t);  /* ^^^ */
                raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
                wake_up_process(t);
-- -----        rcu_spawn_nocb_kthreads();
-- -----        rcu_spawn_boost_kthreads();
++ +++++        /* This is a pre-SMP initcall, we expect a single CPU */
++ +++++        WARN_ON(num_online_cpus() > 1);
++ +++++        /*
++ +++++         * Those kthreads couldn't be created on rcu_init() -> rcutree_prepare_cpu()
++ +++++         * due to rcu_scheduler_fully_active.
++ +++++         */
++ +++++        rcu_spawn_cpu_nocb_kthread(smp_processor_id());
++ +++++        rcu_spawn_one_boost_kthread(rdp->mynode);
                rcu_spawn_core_kthreads();
                return 0;
        }
@@@@@@@@@ -4782,7 -4809,7 -4789,7 -4784,7 -4782,7 -4808,7 -4782,7 -4782,7 +4844,7 @@@@@@@@@ static void __init kfree_rcu_batch_init
        
        void __init rcu_init(void)
        {
-- -----        int cpu;
++ +++++        int cpu = smp_processor_id();
        
                rcu_early_boot_tests();
        
                 * or the scheduler are operational.
                 */
                pm_notifier(rcu_pm_notify, 0);
-- -----        for_each_online_cpu(cpu) {
-- -----                rcutree_prepare_cpu(cpu);
-- -----                rcu_cpu_starting(cpu);
-- -----                rcutree_online_cpu(cpu);
-- -----        }
++ +++++        WARN_ON(num_online_cpus() > 1); // Only one CPU this early in boot.
++ +++++        rcutree_prepare_cpu(cpu);
++ +++++        rcu_cpu_starting(cpu);
++ +++++        rcutree_online_cpu(cpu);
        
                /* Create workqueue for Tree SRCU and for expedited GPs. */
                rcu_gp_wq = alloc_workqueue("rcu_gp", WQ_MEM_RECLAIM, 0);
diff --combined kernel/rcu/tree.h
index 926673ebe355f123c1b0a76d6aaed4c211f9dcd6,94b55f669915355d5fe067120774849391dac9bb,25dc4166f2185a8e2f4bbf21cdac94497baa4706,926673ebe355f123c1b0a76d6aaed4c211f9dcd6,926673ebe355f123c1b0a76d6aaed4c211f9dcd6,926673ebe355f123c1b0a76d6aaed4c211f9dcd6,926673ebe355f123c1b0a76d6aaed4c211f9dcd6,926673ebe355f123c1b0a76d6aaed4c211f9dcd6..8aa5bf74e796a19463cd8289037b102dba09c7d1
@@@@@@@@@ -254,6 -254,7 -254,6 -254,6 -254,6 -254,6 -254,6 -254,6 +254,7 @@@@@@@@@ struct rcu_data 
                unsigned long rcu_onl_gp_seq;   /* ->gp_seq at last online. */
                short rcu_onl_gp_flags;         /* ->gp_flags at last online. */
                unsigned long last_fqs_resched; /* Time of last rcu_resched(). */
+ ++++++        unsigned long last_sched_clock; /* Jiffies of last rcu_sched_clock_irq(). */
        
                int cpu;
        };
@@@@@@@@@ -364,6 -365,6 -364,7 -364,6 -364,6 -364,6 -364,6 -364,6 +365,7 @@@@@@@@@ struct rcu_state 
                arch_spinlock_t ofl_lock ____cacheline_internodealigned_in_smp;
                                                        /* Synchronize offline with */
                                                        /*  GP pre-initialization. */
++ +++++        int nocb_is_setup;                      /* nocb is setup from boot */
        };
        
        /* Values for rcu_state structure's gp_flags field. */
@@@@@@@@@ -421,7 -422,7 -422,6 -421,7 -421,7 -421,7 -421,7 -421,7 +423,6 @@@@@@@@@ static void rcu_preempt_boost_start_gp(
        static bool rcu_is_callbacks_kthread(void);
        static void rcu_cpu_kthread_setup(unsigned int cpu);
        static void rcu_spawn_one_boost_kthread(struct rcu_node *rnp);
-- -----static void __init rcu_spawn_boost_kthreads(void);
        static bool rcu_preempt_has_tasks(struct rcu_node *rnp);
        static bool rcu_preempt_need_deferred_qs(struct task_struct *t);
        static void rcu_preempt_deferred_qs(struct task_struct *t);
@@@@@@@@@ -439,7 -440,7 -439,6 -439,7 -439,7 -439,7 -439,7 -439,7 +440,6 @@@@@@@@@ static int rcu_nocb_need_deferred_wakeu
        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);
-- -----static void __init rcu_spawn_nocb_kthreads(void);
        static void show_rcu_nocb_state(struct rcu_data *rdp);
        static void rcu_nocb_lock(struct rcu_data *rdp);
        static void rcu_nocb_unlock(struct rcu_data *rdp);
diff --combined kernel/rcu/tree_plugin.h
index 8360d86db1c028b39ecb0fe40cf6462aefd12f41,2a371541907306877ceb42b68457cb200f7d13e5,b139635f33bd79132c44b7c8baeab1a7fc7ab633,8360d86db1c028b39ecb0fe40cf6462aefd12f41,8360d86db1c028b39ecb0fe40cf6462aefd12f41,8360d86db1c028b39ecb0fe40cf6462aefd12f41,8360d86db1c028b39ecb0fe40cf6462aefd12f41,8360d86db1c028b39ecb0fe40cf6462aefd12f41..c8ba0fe17267c1c0b68e438616c08a00877ea409
@@@@@@@@@ -486,6 -486,7 -486,6 -486,6 -486,6 -486,6 -486,6 -486,6 +486,7 @@@@@@@@@ rcu_preempt_deferred_qs_irqrestore(stru
                t->rcu_read_unlock_special.s = 0;
                if (special.b.need_qs) {
                        if (IS_ENABLED(CONFIG_RCU_STRICT_GRACE_PERIOD)) {
+ ++++++                        rdp->cpu_no_qs.b.norm = false;
                                rcu_report_qs_rdp(rdp);
                                udelay(rcu_unlock_delay);
                        } else {
@@@@@@@@@ -660,7 -661,13 -660,7 -660,7 -660,7 -660,7 -660,7 -660,7 +661,13 @@@@@@@@@ static void rcu_read_unlock_special(str
                                    expboost && !rdp->defer_qs_iw_pending && cpu_online(rdp->cpu)) {
                                        // Get scheduler to re-evaluate and call hooks.
                                        // If !IRQ_WORK, FQS scan will eventually IPI.
- ------                                init_irq_work(&rdp->defer_qs_iw, rcu_preempt_deferred_qs_handler);
+ ++++++                                if (IS_ENABLED(CONFIG_RCU_STRICT_GRACE_PERIOD) &&
+ ++++++                                    IS_ENABLED(CONFIG_PREEMPT_RT))
+ ++++++                                        rdp->defer_qs_iw = IRQ_WORK_INIT_HARD(
+ ++++++                                                                rcu_preempt_deferred_qs_handler);
+ ++++++                                else
+ ++++++                                        init_irq_work(&rdp->defer_qs_iw,
+ ++++++                                                      rcu_preempt_deferred_qs_handler);
                                        rdp->defer_qs_iw_pending = true;
                                        irq_work_queue_on(&rdp->defer_qs_iw, rdp->cpu);
                                }
@@@@@@@@@ -1124,7 -1131,8 -1124,7 -1124,7 -1124,7 -1124,7 -1124,7 -1124,7 +1131,8 @@@@@@@@@ static void rcu_initiate_boost(struct r
                __releases(rnp->lock)
        {
                raw_lockdep_assert_held_rcu_node(rnp);
- ------        if (!rcu_preempt_blocked_readers_cgp(rnp) && rnp->exp_tasks == NULL) {
+ ++++++        if (!rnp->boost_kthread_task ||
+ ++++++            (!rcu_preempt_blocked_readers_cgp(rnp) && !rnp->exp_tasks)) {
                        raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
                        return;
                }
@@@@@@@@@ -1226,18 -1234,18 -1226,6 -1226,18 -1226,18 -1226,18 -1226,18 -1226,18 +1234,6 @@@@@@@@@ static void rcu_boost_kthread_setaffini
                free_cpumask_var(cm);
        }
        
-- -----/*
-- ----- * Spawn boost kthreads -- called as soon as the scheduler is running.
-- ----- */
-- -----static void __init rcu_spawn_boost_kthreads(void)
-- -----{
-- -----        struct rcu_node *rnp;
-- -----
-- -----        rcu_for_each_leaf_node(rnp)
-- -----                if (rcu_rnp_online_cpus(rnp))
-- -----                        rcu_spawn_one_boost_kthread(rnp);
-- -----}
-- -----
        #else /* #ifdef CONFIG_RCU_BOOST */
        
        static void rcu_initiate_boost(struct rcu_node *rnp, unsigned long flags)
@@@@@@@@@ -1263,10 -1271,10 -1251,6 -1263,10 -1263,10 -1263,10 -1263,10 -1263,10 +1259,6 @@@@@@@@@ static void rcu_boost_kthread_setaffini
        {
        }
        
-- -----static void __init rcu_spawn_boost_kthreads(void)
-- -----{
-- -----}
-- -----
        #endif /* #else #ifdef CONFIG_RCU_BOOST */
        
        /*
index bfe09e2829c8d0f723e2455eca6faa3f2b19c117,bfe09e2829c8d0f723e2455eca6faa3f2b19c117,bfe09e2829c8d0f723e2455eca6faa3f2b19c117,bfe09e2829c8d0f723e2455eca6faa3f2b19c117,bfe09e2829c8d0f723e2455eca6faa3f2b19c117,e657a6e0641764120ecdf26daa0b4623d9c49a97,bfe09e2829c8d0f723e2455eca6faa3f2b19c117,3be9cfab93b5c1c23aa5bf22d7f796eb454034aa..d477618e7261df5a5ad430e5fea7e4f3bd73c48d
@@@@@@@@@ -54,6 -54,6 -54,6 -54,6 -54,6 -54,7 -54,6 -54,6 +54,7 @@@@@@@@@ do_kvfree=ye
        do_kasan=yes
        do_kcsan=no
        do_clocksourcewd=yes
+++++ ++do_rt=yes
        
        # doyesno - Helper function for yes/no arguments
        function doyesno () {
@@@@@@@@@ -82,6 -82,6 -82,6 -82,6 -82,6 -83,7 -82,6 -82,6 +83,7 @@@@@@@@@ usage () 
                echo "       --do-rcuscale / --do-no-rcuscale"
                echo "       --do-rcutorture / --do-no-rcutorture"
                echo "       --do-refscale / --do-no-refscale"
+++++ ++        echo "       --do-rt / --do-no-rt"
                echo "       --do-scftorture / --do-no-scftorture"
                echo "       --duration [ <minutes> | <hours>h | <days>d ]"
                echo "       --kcsan-kmake-arg kernel-make-arguments"
                        do_scftorture=yes
                        do_rcuscale=yes
                        do_refscale=yes
+++++ ++                do_rt=yes
                        do_kvfree=yes
                        do_kasan=yes
                        do_kcsan=yes
                        do_scftorture=no
                        do_rcuscale=no
                        do_refscale=no
+++++ ++                do_rt=no
                        do_kvfree=no
                        do_kasan=no
                        do_kcsan=no
                --do-refscale|--do-no-refscale)
                        do_refscale=`doyesno "$1" --do-refscale`
                        ;;
+++++ ++        --do-rt|--do-no-rt)
+++++ ++                do_rt=`doyesno "$1" --do-rt`
+++++ ++                ;;
                --do-scftorture|--do-no-scftorture)
                        do_scftorture=`doyesno "$1" --do-scftorture`
                        ;;
                echo " --- make clean" > "$amcdir/Make.out" 2>&1
                make -j$MAKE_ALLOTED_CPUS clean >> "$amcdir/Make.out" 2>&1
                echo " --- make allmodconfig" >> "$amcdir/Make.out" 2>&1
+++++++         cp .config $amcdir
                make -j$MAKE_ALLOTED_CPUS allmodconfig >> "$amcdir/Make.out" 2>&1
                echo " --- make " >> "$amcdir/Make.out" 2>&1
                make -j$MAKE_ALLOTED_CPUS >> "$amcdir/Make.out" 2>&1
        
        if test "$do_scftorture" = "yes"
        then
-------         torture_bootargs="scftorture.nthreads=$HALF_ALLOTED_CPUS torture.disable_onoff_at_boot"
-------         torture_set "scftorture" tools/testing/selftests/rcutorture/bin/kvm.sh --torture scf --allcpus --duration "$duration_scftorture" --configs "$configs_scftorture" --kconfig "CONFIG_NR_CPUS=$HALF_ALLOTED_CPUS" --memory 1G --trust-make
+++++++         torture_bootargs="scftorture.nthreads=$HALF_ALLOTED_CPUS torture.disable_onoff_at_boot csdlock_debug=1"
+++++++         torture_set "scftorture" tools/testing/selftests/rcutorture/bin/kvm.sh --torture scf --allcpus --duration "$duration_scftorture" --configs "$configs_scftorture" --kconfig "CONFIG_NR_CPUS=$HALF_ALLOTED_CPUS" --memory 2G --trust-make
+++++ + fi
+++++ + 
+++++ ++if test "$do_rt" = "yes"
+++++ ++then
+++++ ++        # With all post-boot grace periods forced to normal.
+++++ ++        torture_bootargs="rcupdate.rcu_cpu_stall_suppress_at_boot=1 torture.disable_onoff_at_boot rcupdate.rcu_task_stall_timeout=30000 rcupdate.rcu_normal=1"
+++++ ++        torture_set "rcurttorture" tools/testing/selftests/rcutorture/bin/kvm.sh --allcpus --duration "$duration_rcutorture" --configs "TREE03" --trust-make
+++++ ++
+++++ ++        # With all post-boot grace periods forced to expedited.
+++++ ++        torture_bootargs="rcupdate.rcu_cpu_stall_suppress_at_boot=1 torture.disable_onoff_at_boot rcupdate.rcu_task_stall_timeout=30000 rcupdate.rcu_expedited=1"
+++++ ++        torture_set "rcurttorture-exp" tools/testing/selftests/rcutorture/bin/kvm.sh --allcpus --duration "$duration_rcutorture" --configs "TREE03" --trust-make
       +fi
       +
        if test "$do_refscale" = yes
        then
                primlist="`grep '\.name[        ]*=' kernel/rcu/refscale.c | sed -e 's/^[^"]*"//' -e 's/".*$//'`"
        for prim in $primlist
        do
                torture_bootargs="refscale.scale_type="$prim" refscale.nreaders=$HALF_ALLOTED_CPUS refscale.loops=10000 refscale.holdoff=20 torture.disable_onoff_at_boot"
-------         torture_set "refscale-$prim" tools/testing/selftests/rcutorture/bin/kvm.sh --torture refscale --allcpus --duration 5 --kconfig "CONFIG_NR_CPUS=$HALF_ALLOTED_CPUS" --bootargs "verbose_batched=$VERBOSE_BATCH_CPUS torture.verbose_sleep_frequency=8 torture.verbose_sleep_duration=$VERBOSE_BATCH_CPUS" --trust-make
+++++++         torture_set "refscale-$prim" tools/testing/selftests/rcutorture/bin/kvm.sh --torture refscale --allcpus --duration 5 --kconfig "CONFIG_TASKS_TRACE_RCU=y CONFIG_NR_CPUS=$HALF_ALLOTED_CPUS" --bootargs "verbose_batched=$VERBOSE_BATCH_CPUS torture.verbose_sleep_frequency=8 torture.verbose_sleep_duration=$VERBOSE_BATCH_CPUS" --trust-make
        done
        
        if test "$do_rcuscale" = yes
        for prim in $primlist
        do
                torture_bootargs="rcuscale.scale_type="$prim" rcuscale.nwriters=$HALF_ALLOTED_CPUS rcuscale.holdoff=20 torture.disable_onoff_at_boot"
-------         torture_set "rcuscale-$prim" tools/testing/selftests/rcutorture/bin/kvm.sh --torture rcuscale --allcpus --duration 5 --kconfig "CONFIG_NR_CPUS=$HALF_ALLOTED_CPUS" --trust-make
+++++++         torture_set "rcuscale-$prim" tools/testing/selftests/rcutorture/bin/kvm.sh --torture rcuscale --allcpus --duration 5 --kconfig "CONFIG_TASKS_TRACE_RCU=y CONFIG_NR_CPUS=$HALF_ALLOTED_CPUS" --trust-make
        done
        
        if test "$do_kvfree" = "yes"
        then
                torture_bootargs="rcuscale.kfree_rcu_test=1 rcuscale.kfree_nthreads=16 rcuscale.holdoff=20 rcuscale.kfree_loops=10000 torture.disable_onoff_at_boot"
-------         torture_set "rcuscale-kvfree" tools/testing/selftests/rcutorture/bin/kvm.sh --torture rcuscale --allcpus --duration 10 --kconfig "CONFIG_NR_CPUS=$HALF_ALLOTED_CPUS" --memory 1G --trust-make
+++++++         torture_set "rcuscale-kvfree" tools/testing/selftests/rcutorture/bin/kvm.sh --torture rcuscale --allcpus --duration 10 --kconfig "CONFIG_NR_CPUS=$HALF_ALLOTED_CPUS" --memory 2G --trust-make
        fi
        
        if test "$do_clocksourcewd" = "yes"
index e4d74e5fc1d09bae1622a4f966458f253d14c034,e4d74e5fc1d09bae1622a4f966458f253d14c034,e4d74e5fc1d09bae1622a4f966458f253d14c034,e4d74e5fc1d09bae1622a4f966458f253d14c034,e4d74e5fc1d09bae1622a4f966458f253d14c034,e4d74e5fc1d09bae1622a4f966458f253d14c034,0f5605ed1e484fd183d9be180a3d44cfcd079c3e,b54cefde6e876ceeb58a7bde39ad112ac335eea8..85b407467454a2e98072ff234d9396e450ec01d1
@@@@@@@@@ -4,8 -4,8 -4,8 -4,8 -4,8 -4,8 -4,10 -4,9 +4,11 @@@@@@@@@ CONFIG_HOTPLUG_CPU=
        CONFIG_PREEMPT_NONE=y
        CONFIG_PREEMPT_VOLUNTARY=n
        CONFIG_PREEMPT=n
+++++++ CONFIG_PREEMPT_DYNAMIC=n
        CONFIG_DEBUG_LOCK_ALLOC=n
        CONFIG_PROVE_LOCKING=n
        #CHECK#CONFIG_PROVE_RCU=n
++++++ +CONFIG_FORCE_TASKS_TRACE_RCU=y
++++++ +#CHECK#CONFIG_TASKS_TRACE_RCU=y
        CONFIG_TASKS_TRACE_RCU_READ_MB=y
        CONFIG_RCU_EXPERT=y
This page took 0.128408 seconds and 4 git commands to generate.