• Paul E. McKenney's avatar
    rcu: Defer reporting RCU-preempt quiescent states when disabled · 3e310098
    Paul E. McKenney authored
    This commit defers reporting of RCU-preempt quiescent states at
    rcu_read_unlock_special() time when any of interrupts, softirq, or
    preemption are disabled.  These deferred quiescent states are reported
    at a later RCU_SOFTIRQ, context switch, idle entry, or CPU-hotplug
    offline operation.  Of course, if another RCU read-side critical
    section has started in the meantime, the reporting of the quiescent
    state will be further deferred.
    
    This also means that disabling preemption, interrupts, and/or
    softirqs will act as an RCU-preempt read-side critical section.
    This is enforced by checking preempt_count() as needed.
    
    Some special cases must be handled on an ad-hoc basis, for example,
    context switch is a quiescent state even though both the scheduler and
    do_exit() disable preemption.  In these cases, additional calls to
    rcu_preempt_deferred_qs() override the preemption disabling.  Similar
    logic overrides disabled interrupts in rcu_preempt_check_callbacks()
    because in this case the quiescent state happened just before the
    corresponding scheduling-clock interrupt.
    
    In theory, this change lifts a long-standing restriction that required
    that if interrupts were disabled across a call to rcu_read_unlock()
    that the matching rcu_read_lock() also be contained within that
    interrupts-disabled region of code.  Because the reporting of the
    corresponding RCU-preempt quiescent state is now deferred until
    after interrupts have been enabled, it is no longer possible for this
    situation to result in deadlocks involving the scheduler's runqueue and
    priority-inheritance locks.  This may allow some code simplification that
    might reduce interrupt latency a bit.  Unfortunately, in practice this
    would also defer deboosting a low-priority task that had been subjected
    to RCU priority boosting, so real-time-response considerations might
    well force this restriction to remain in place.
    
    Because RCU-preempt grace periods are now blocked not only by RCU
    read-side critical sections, but also by disabling of interrupts,
    preemption, and softirqs, it will be possible to eliminate RCU-bh and
    RCU-sched in favor of RCU-preempt in CONFIG_PREEMPT=y kernels.  This may
    require some additional plumbing to provide the network denial-of-service
    guarantees that have been traditionally provided by RCU-bh.  Once these
    are in place, CONFIG_PREEMPT=n kernels will be able to fold RCU-bh
    into RCU-sched.  This would mean that all kernels would have but
    one flavor of RCU, which would open the door to significant code
    cleanup.
    
    Moving to a single flavor of RCU would also have the beneficial effect
    of reducing the NOCB kthreads by at least a factor of two.
    Signed-off-by: default avatarPaul E. McKenney <paulmck@linux.vnet.ibm.com>
    [ paulmck: Apply rcu_read_unlock_special() preempt_count() feedback
      from Joel Fernandes. ]
    [ paulmck: Adjust rcu_eqs_enter() call to rcu_preempt_deferred_qs() in
      response to bug reports from kbuild test robot. ]
    [ paulmck: Fix bug located by kbuild test robot involving recursion
      via rcu_preempt_deferred_qs(). ]
    3e310098
tree_exp.h 26.1 KB