Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

rcu: docs: Requirements.rst: Abide by conventions of kernel documentation

Here is a list of conventions applied here:

- Don't mark up function names, to be taken care of by the automarkup
extension. Just say func().
- Instead of ".. code-block:: none", just say "::".
- Mark inline literals by a pair of ``xxxx``. Don't use rust doc's
dialect of `yyyy`.
- Instead of emphasizing headings by **strong emphasis**, use sub-level
title adornments, in this case "^^^^^^^^^^" and make them proper
sub-sections under "Hotplug CPU".

Signed-off-by: Akira Yokosawa <akiyks@gmail.com>
Cc: Joel Fernandes <joelagnelf@nvidia.com>
Signed-off-by: Neeraj Upadhyay (AMD) <neeraj.upadhyay@kernel.org>
Signed-off-by: Paul E. McKenney <paulmck@kernel.org>

authored by

Akira Yokosawa and committed by
Paul E. McKenney
d33b01d7 820f8da7

+24 -28
+24 -28
Documentation/RCU/Design/Requirements/Requirements.rst
··· 1973 1973 Note that grace period initialization (rcu_gp_init()) must carefully sequence 1974 1974 CPU hotplug scanning with grace period state changes. For example, the 1975 1975 following race could occur in rcu_gp_init() if rcu_seq_start() were to happen 1976 - after the CPU hotplug scanning. 1977 - 1978 - .. code-block:: none 1976 + after the CPU hotplug scanning:: 1979 1977 1980 1978 CPU0 (rcu_gp_init) CPU1 CPU2 1981 1979 --------------------- ---- ---- ··· 2006 2008 kfree(r1); 2007 2009 r2 = *r0; // USE-AFTER-FREE! 2008 2010 2009 - By incrementing gp_seq first, CPU1's RCU read-side critical section 2011 + By incrementing ``gp_seq`` first, CPU1's RCU read-side critical section 2010 2012 is guaranteed to not be missed by CPU2. 2011 2013 2012 - **Concurrent Quiescent State Reporting for Offline CPUs** 2014 + Concurrent Quiescent State Reporting for Offline CPUs 2015 + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 2013 2016 2014 2017 RCU must ensure that CPUs going offline report quiescent states to avoid 2015 2018 blocking grace periods. This requires careful synchronization to handle 2016 2019 race conditions 2017 2020 2018 - **Race condition causing Offline CPU to hang GP** 2021 + Race condition causing Offline CPU to hang GP 2022 + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 2019 2023 2020 - A race between CPU offlining and new GP initialization (gp_init) may occur 2021 - because `rcu_report_qs_rnp()` in `rcutree_report_cpu_dead()` must temporarily 2022 - release the `rcu_node` lock to wake the RCU grace-period kthread: 2023 - 2024 - .. code-block:: none 2024 + A race between CPU offlining and new GP initialization (gp_init()) may occur 2025 + because rcu_report_qs_rnp() in rcutree_report_cpu_dead() must temporarily 2026 + release the ``rcu_node`` lock to wake the RCU grace-period kthread:: 2025 2027 2026 2028 CPU1 (going offline) CPU0 (GP kthread) 2027 2029 -------------------- ----------------- ··· 2042 2044 // Reacquire lock (but too late) 2043 2045 rnp->qsmaskinitnext &= ~mask // Finally clears bit 2044 2046 2045 - Without `ofl_lock`, the new grace period includes the offline CPU and waits 2047 + Without ``ofl_lock``, the new grace period includes the offline CPU and waits 2046 2048 forever for its quiescent state causing a GP hang. 2047 2049 2048 - **A solution with ofl_lock** 2050 + A solution with ofl_lock 2051 + ^^^^^^^^^^^^^^^^^^^^^^^^ 2049 2052 2050 - The `ofl_lock` (offline lock) prevents `rcu_gp_init()` from running during 2051 - the vulnerable window when `rcu_report_qs_rnp()` has released `rnp->lock`: 2052 - 2053 - .. code-block:: none 2053 + The ``ofl_lock`` (offline lock) prevents rcu_gp_init() from running during 2054 + the vulnerable window when rcu_report_qs_rnp() has released ``rnp->lock``:: 2054 2055 2055 2056 CPU0 (rcu_gp_init) CPU1 (rcutree_report_cpu_dead) 2056 2057 ------------------ ------------------------------ ··· 2062 2065 arch_spin_unlock(&ofl_lock) ---> // Now CPU1 can proceed 2063 2066 } // But snapshot already taken 2064 2067 2065 - **Another race causing GP hangs in rcu_gpu_init(): Reporting QS for Now-offline CPUs** 2068 + Another race causing GP hangs in rcu_gpu_init(): Reporting QS for Now-offline CPUs 2069 + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 2066 2070 2067 2071 After the first loop takes an atomic snapshot of online CPUs, as shown above, 2068 - the second loop in `rcu_gp_init()` detects CPUs that went offline between 2069 - releasing `ofl_lock` and acquiring the per-node `rnp->lock`. This detection is 2070 - crucial because: 2072 + the second loop in rcu_gp_init() detects CPUs that went offline between 2073 + releasing ``ofl_lock`` and acquiring the per-node ``rnp->lock``. 2074 + This detection is crucial because: 2071 2075 2072 2076 1. The CPU might have gone offline after the snapshot but before the second loop 2073 2077 2. The offline CPU cannot report its own QS if it's already dead 2074 2078 3. Without this detection, the grace period would wait forever for CPUs that 2075 2079 are now offline. 2076 2080 2077 - The second loop performs this detection safely: 2078 - 2079 - .. code-block:: none 2081 + The second loop performs this detection safely:: 2080 2082 2081 2083 rcu_for_each_node_breadth_first(rnp) { 2082 2084 raw_spin_lock_irqsave_rcu_node(rnp, flags); ··· 2089 2093 } 2090 2094 2091 2095 This approach ensures atomicity: quiescent state reporting for offline CPUs 2092 - happens either in `rcu_gp_init()` (second loop) or in `rcutree_report_cpu_dead()`, 2093 - never both and never neither. The `rnp->lock` held throughout the sequence 2094 - prevents races - `rcutree_report_cpu_dead()` also acquires this lock when 2095 - clearing `qsmaskinitnext`, ensuring mutual exclusion. 2096 + happens either in rcu_gp_init() (second loop) or in rcutree_report_cpu_dead(), 2097 + never both and never neither. The ``rnp->lock`` held throughout the sequence 2098 + prevents races - rcutree_report_cpu_dead() also acquires this lock when 2099 + clearing ``qsmaskinitnext``, ensuring mutual exclusion. 2096 2100 2097 2101 Scheduler and RCU 2098 2102 ~~~~~~~~~~~~~~~~~