17 Jun, 2011

1 commit

  • The commit "use softirq instead of kthreads except when RCU_BOOST=y"
    just applied #ifdef in place. This commit is a cleanup that moves
    the newly #ifdef'ed code to the header file kernel/rcutree_plugin.h.

    Signed-off-by: Paul E. McKenney
    Signed-off-by: Paul E. McKenney

    Paul E. McKenney
     

16 Jun, 2011

1 commit


15 Jun, 2011

1 commit

  • Commit a26ac2455ffcf3(rcu: move TREE_RCU from softirq to kthread)
    introduced performance regression. In an AIM7 test, this commit degraded
    performance by about 40%.

    The commit runs rcu callbacks in a kthread instead of softirq. We observed
    high rate of context switch which is caused by this. Out test system has
    64 CPUs and HZ is 1000, so we saw more than 64k context switch per second
    which is caused by RCU's per-CPU kthread. A trace showed that most of
    the time the RCU per-CPU kthread doesn't actually handle any callbacks,
    but instead just does a very small amount of work handling grace periods.
    This means that RCU's per-CPU kthreads are making the scheduler do quite
    a bit of work in order to allow a very small amount of RCU-related
    processing to be done.

    Alex Shi's analysis determined that this slowdown is due to lock
    contention within the scheduler. Unfortunately, as Peter Zijlstra points
    out, the scheduler's real-time semantics require global action, which
    means that this contention is inherent in real-time scheduling. (Yes,
    perhaps someone will come up with a workaround -- otherwise, -rt is not
    going to do well on large SMP systems -- but this patch will work around
    this issue in the meantime. And "the meantime" might well be forever.)

    This patch therefore re-introduces softirq processing to RCU, but only
    for core RCU work. RCU callbacks are still executed in kthread context,
    so that only a small amount of RCU work runs in softirq context in the
    common case. This should minimize ksoftirqd execution, allowing us to
    skip boosting of ksoftirqd for CONFIG_RCU_BOOST=y kernels.

    Signed-off-by: Shaohua Li
    Tested-by: "Alex,Shi"
    Signed-off-by: Paul E. McKenney

    Shaohua Li
     

28 May, 2011

2 commits

  • It is not necessary to use waitqueues for the RCU kthreads because
    we always know exactly which thread is to be awakened. In addition,
    wake_up() only issues an actual wakeup when there is a thread waiting on
    the queue, which was why there was an extra explicit wake_up_process()
    to get the RCU kthreads started.

    Eliminating the waitqueues (and wake_up()) in favor of wake_up_process()
    eliminates the need for the initial wake_up_process() and also shrinks
    the data structure size a bit. The wakeup logic is placed in a new
    rcu_wait() macro.

    Signed-off-by: Peter Zijlstra
    Signed-off-by: Paul E. McKenney
    Signed-off-by: Ingo Molnar

    Peter Zijlstra
     
  • This commit switches manipulations of the rcu_node ->wakemask field
    to atomic operations, which allows rcu_cpu_kthread_timer() to avoid
    acquiring the rcu_node lock. This should avoid the following lockdep
    splat reported by Valdis Kletnieks:

    [ 12.872150] usb 1-4: new high speed USB device number 3 using ehci_hcd
    [ 12.986667] usb 1-4: New USB device found, idVendor=413c, idProduct=2513
    [ 12.986679] usb 1-4: New USB device strings: Mfr=0, Product=0, SerialNumber=0
    [ 12.987691] hub 1-4:1.0: USB hub found
    [ 12.987877] hub 1-4:1.0: 3 ports detected
    [ 12.996372] input: PS/2 Generic Mouse as /devices/platform/i8042/serio1/input/input10
    [ 13.071471] udevadm used greatest stack depth: 3984 bytes left
    [ 13.172129]
    [ 13.172130] =======================================================
    [ 13.172425] [ INFO: possible circular locking dependency detected ]
    [ 13.172650] 2.6.39-rc6-mmotm0506 #1
    [ 13.172773] -------------------------------------------------------
    [ 13.172997] blkid/267 is trying to acquire lock:
    [ 13.173009] (&p->pi_lock){-.-.-.}, at: [] try_to_wake_up+0x29/0x1aa
    [ 13.173009]
    [ 13.173009] but task is already holding lock:
    [ 13.173009] (rcu_node_level_0){..-...}, at: [] rcu_cpu_kthread_timer+0x27/0x58
    [ 13.173009]
    [ 13.173009] which lock already depends on the new lock.
    [ 13.173009]
    [ 13.173009]
    [ 13.173009] the existing dependency chain (in reverse order) is:
    [ 13.173009]
    [ 13.173009] -> #2 (rcu_node_level_0){..-...}:
    [ 13.173009] [] check_prevs_add+0x8b/0x104
    [ 13.173009] [] validate_chain+0x36f/0x3ab
    [ 13.173009] [] __lock_acquire+0x369/0x3e2
    [ 13.173009] [] lock_acquire+0xfc/0x14c
    [ 13.173009] [] _raw_spin_lock+0x36/0x45
    [ 13.173009] [] rcu_read_unlock_special+0x8c/0x1d5
    [ 13.173009] [] __rcu_read_unlock+0x4f/0xd7
    [ 13.173009] [] rcu_read_unlock+0x21/0x23
    [ 13.173009] [] cpuacct_charge+0x6c/0x75
    [ 13.173009] [] update_curr+0x101/0x12e
    [ 13.173009] [] check_preempt_wakeup+0xf7/0x23b
    [ 13.173009] [] check_preempt_curr+0x2b/0x68
    [ 13.173009] [] ttwu_do_wakeup+0x76/0x128
    [ 13.173009] [] ttwu_do_activate.constprop.63+0x57/0x5c
    [ 13.173009] [] scheduler_ipi+0x48/0x5d
    [ 13.173009] [] smp_reschedule_interrupt+0x16/0x18
    [ 13.173009] [] reschedule_interrupt+0x13/0x20
    [ 13.173009] [] rcu_read_unlock+0x21/0x23
    [ 13.173009] [] find_get_page+0xa9/0xb9
    [ 13.173009] [] filemap_fault+0x6a/0x34d
    [ 13.173009] [] __do_fault+0x54/0x3e6
    [ 13.173009] [] handle_pte_fault+0x12c/0x1ed
    [ 13.173009] [] handle_mm_fault+0x1cd/0x1e0
    [ 13.173009] [] do_page_fault+0x42d/0x5de
    [ 13.173009] [] page_fault+0x1f/0x30
    [ 13.173009]
    [ 13.173009] -> #1 (&rq->lock){-.-.-.}:
    [ 13.173009] [] check_prevs_add+0x8b/0x104
    [ 13.173009] [] validate_chain+0x36f/0x3ab
    [ 13.173009] [] __lock_acquire+0x369/0x3e2
    [ 13.173009] [] lock_acquire+0xfc/0x14c
    [ 13.173009] [] _raw_spin_lock+0x36/0x45
    [ 13.173009] [] __task_rq_lock+0x8b/0xd3
    [ 13.173009] [] wake_up_new_task+0x41/0x108
    [ 13.173009] [] do_fork+0x265/0x33f
    [ 13.173009] [] kernel_thread+0x6b/0x6d
    [ 13.173009] [] rest_init+0x21/0xd2
    [ 13.173009] [] start_kernel+0x3bb/0x3c6
    [ 13.173009] [] x86_64_start_reservations+0xaf/0xb3
    [ 13.173009] [] x86_64_start_kernel+0xf0/0xf7
    [ 13.173009]
    [ 13.173009] -> #0 (&p->pi_lock){-.-.-.}:
    [ 13.173009] [] check_prev_add+0x68/0x20e
    [ 13.173009] [] check_prevs_add+0x8b/0x104
    [ 13.173009] [] validate_chain+0x36f/0x3ab
    [ 13.173009] [] __lock_acquire+0x369/0x3e2
    [ 13.173009] [] lock_acquire+0xfc/0x14c
    [ 13.173009] [] _raw_spin_lock_irqsave+0x44/0x57
    [ 13.173009] [] try_to_wake_up+0x29/0x1aa
    [ 13.173009] [] wake_up_process+0x10/0x12
    [ 13.173009] [] rcu_cpu_kthread_timer+0x44/0x58
    [ 13.173009] [] call_timer_fn+0xac/0x1e9
    [ 13.173009] [] run_timer_softirq+0x1aa/0x1f2
    [ 13.173009] [] __do_softirq+0x109/0x26a
    [ 13.173009] [] call_softirq+0x1c/0x30
    [ 13.173009] [] do_softirq+0x44/0xf1
    [ 13.173009] [] irq_exit+0x58/0xc8
    [ 13.173009] [] smp_apic_timer_interrupt+0x79/0x87
    [ 13.173009] [] apic_timer_interrupt+0x13/0x20
    [ 13.173009] [] get_page_from_freelist+0x2aa/0x310
    [ 13.173009] [] __alloc_pages_nodemask+0x178/0x243
    [ 13.173009] [] pte_alloc_one+0x1e/0x3a
    [ 13.173009] [] __pte_alloc+0x22/0x14b
    [ 13.173009] [] handle_mm_fault+0x17e/0x1e0
    [ 13.173009] [] do_page_fault+0x42d/0x5de
    [ 13.173009] [] page_fault+0x1f/0x30
    [ 13.173009]
    [ 13.173009] other info that might help us debug this:
    [ 13.173009]
    [ 13.173009] Chain exists of:
    [ 13.173009] &p->pi_lock --> &rq->lock --> rcu_node_level_0
    [ 13.173009]
    [ 13.173009] Possible unsafe locking scenario:
    [ 13.173009]
    [ 13.173009] CPU0 CPU1
    [ 13.173009] ---- ----
    [ 13.173009] lock(rcu_node_level_0);
    [ 13.173009] lock(&rq->lock);
    [ 13.173009] lock(rcu_node_level_0);
    [ 13.173009] lock(&p->pi_lock);
    [ 13.173009]
    [ 13.173009] *** DEADLOCK ***
    [ 13.173009]
    [ 13.173009] 3 locks held by blkid/267:
    [ 13.173009] #0: (&mm->mmap_sem){++++++}, at: [] do_page_fault+0x1f3/0x5de
    [ 13.173009] #1: (&yield_timer){+.-...}, at: [] call_timer_fn+0x0/0x1e9
    [ 13.173009] #2: (rcu_node_level_0){..-...}, at: [] rcu_cpu_kthread_timer+0x27/0x58
    [ 13.173009]
    [ 13.173009] stack backtrace:
    [ 13.173009] Pid: 267, comm: blkid Not tainted 2.6.39-rc6-mmotm0506 #1
    [ 13.173009] Call Trace:
    [ 13.173009] [] print_circular_bug+0xc8/0xd9
    [ 13.173009] [] check_prev_add+0x68/0x20e
    [ 13.173009] [] ? save_stack_trace+0x28/0x46
    [ 13.173009] [] check_prevs_add+0x8b/0x104
    [ 13.173009] [] validate_chain+0x36f/0x3ab
    [ 13.173009] [] __lock_acquire+0x369/0x3e2
    [ 13.173009] [] ? try_to_wake_up+0x29/0x1aa
    [ 13.173009] [] lock_acquire+0xfc/0x14c
    [ 13.173009] [] ? try_to_wake_up+0x29/0x1aa
    [ 13.173009] [] ? rcu_check_quiescent_state+0x82/0x82
    [ 13.173009] [] _raw_spin_lock_irqsave+0x44/0x57
    [ 13.173009] [] ? try_to_wake_up+0x29/0x1aa
    [ 13.173009] [] try_to_wake_up+0x29/0x1aa
    [ 13.173009] [] ? rcu_check_quiescent_state+0x82/0x82
    [ 13.173009] [] wake_up_process+0x10/0x12
    [ 13.173009] [] rcu_cpu_kthread_timer+0x44/0x58
    [ 13.173009] [] ? rcu_check_quiescent_state+0x82/0x82
    [ 13.173009] [] call_timer_fn+0xac/0x1e9
    [ 13.173009] [] ? del_timer+0x75/0x75
    [ 13.173009] [] ? rcu_check_quiescent_state+0x82/0x82
    [ 13.173009] [] run_timer_softirq+0x1aa/0x1f2
    [ 13.173009] [] __do_softirq+0x109/0x26a
    [ 13.173009] [] ? tick_dev_program_event+0x37/0xf6
    [ 13.173009] [] ? time_hardirqs_off+0x1b/0x2f
    [ 13.173009] [] call_softirq+0x1c/0x30
    [ 13.173009] [] do_softirq+0x44/0xf1
    [ 13.173009] [] irq_exit+0x58/0xc8
    [ 13.173009] [] smp_apic_timer_interrupt+0x79/0x87
    [ 13.173009] [] apic_timer_interrupt+0x13/0x20
    [ 13.173009] [] ? get_page_from_freelist+0x114/0x310
    [ 13.173009] [] ? get_page_from_freelist+0x2aa/0x310
    [ 13.173009] [] ? clear_page_c+0x7/0x10
    [ 13.173009] [] ? prep_new_page+0x14c/0x1cd
    [ 13.173009] [] get_page_from_freelist+0x2aa/0x310
    [ 13.173009] [] __alloc_pages_nodemask+0x178/0x243
    [ 13.173009] [] ? __pmd_alloc+0x87/0x99
    [ 13.173009] [] pte_alloc_one+0x1e/0x3a
    [ 13.173009] [] ? __pmd_alloc+0x87/0x99
    [ 13.173009] [] __pte_alloc+0x22/0x14b
    [ 13.173009] [] handle_mm_fault+0x17e/0x1e0
    [ 13.173009] [] do_page_fault+0x42d/0x5de
    [ 13.173009] [] ? sys_brk+0x32/0x10c
    [ 13.173009] [] ? time_hardirqs_off+0x1b/0x2f
    [ 13.173009] [] ? trace_hardirqs_off_caller+0x3f/0x9c
    [ 13.173009] [] ? trace_hardirqs_off_thunk+0x3a/0x3c
    [ 13.173009] [] page_fault+0x1f/0x30
    [ 14.010075] usb 5-1: new full speed USB device number 2 using uhci_hcd

    Reported-by: Valdis Kletnieks
    Signed-off-by: Paul E. McKenney
    Signed-off-by: Paul E. McKenney
    Signed-off-by: Ingo Molnar

    Paul E. McKenney
     

27 May, 2011

1 commit

  • (Note: this was reverted, and is now being re-applied in pieces, with
    this being the fifth and final piece. See below for the reason that
    it is now felt to be safe to re-apply this.)

    Commit d09b62d fixed grace-period synchronization, but left some smp_mb()
    invocations in rcu_process_callbacks() that are no longer needed, but
    sheer paranoia prevented them from being removed. This commit removes
    them and provides a proof of correctness in their absence. It also adds
    a memory barrier to rcu_report_qs_rsp() immediately before the update to
    rsp->completed in order to handle the theoretical possibility that the
    compiler or CPU might move massive quantities of code into a lock-based
    critical section. This also proves that the sheer paranoia was not
    entirely unjustified, at least from a theoretical point of view.

    In addition, the old dyntick-idle synchronization depended on the fact
    that grace periods were many milliseconds in duration, so that it could
    be assumed that no dyntick-idle CPU could reorder a memory reference
    across an entire grace period. Unfortunately for this design, the
    addition of expedited grace periods breaks this assumption, which has
    the unfortunate side-effect of requiring atomic operations in the
    functions that track dyntick-idle state for RCU. (There is some hope
    that the algorithms used in user-level RCU might be applied here, but
    some work is required to handle the NMIs that user-space applications
    can happily ignore. For the short term, better safe than sorry.)

    This proof assumes that neither compiler nor CPU will allow a lock
    acquisition and release to be reordered, as doing so can result in
    deadlock. The proof is as follows:

    1. A given CPU declares a quiescent state under the protection of
    its leaf rcu_node's lock.

    2. If there is more than one level of rcu_node hierarchy, the
    last CPU to declare a quiescent state will also acquire the
    ->lock of the next rcu_node up in the hierarchy, but only
    after releasing the lower level's lock. The acquisition of this
    lock clearly cannot occur prior to the acquisition of the leaf
    node's lock.

    3. Step 2 repeats until we reach the root rcu_node structure.
    Please note again that only one lock is held at a time through
    this process. The acquisition of the root rcu_node's ->lock
    must occur after the release of that of the leaf rcu_node.

    4. At this point, we set the ->completed field in the rcu_state
    structure in rcu_report_qs_rsp(). However, if the rcu_node
    hierarchy contains only one rcu_node, then in theory the code
    preceding the quiescent state could leak into the critical
    section. We therefore precede the update of ->completed with a
    memory barrier. All CPUs will therefore agree that any updates
    preceding any report of a quiescent state will have happened
    before the update of ->completed.

    5. Regardless of whether a new grace period is needed, rcu_start_gp()
    will propagate the new value of ->completed to all of the leaf
    rcu_node structures, under the protection of each rcu_node's ->lock.
    If a new grace period is needed immediately, this propagation
    will occur in the same critical section that ->completed was
    set in, but courtesy of the memory barrier in #4 above, is still
    seen to follow any pre-quiescent-state activity.

    6. When a given CPU invokes __rcu_process_gp_end(), it becomes
    aware of the end of the old grace period and therefore makes
    any RCU callbacks that were waiting on that grace period eligible
    for invocation.

    If this CPU is the same one that detected the end of the grace
    period, and if there is but a single rcu_node in the hierarchy,
    we will still be in the single critical section. In this case,
    the memory barrier in step #4 guarantees that all callbacks will
    be seen to execute after each CPU's quiescent state.

    On the other hand, if this is a different CPU, it will acquire
    the leaf rcu_node's ->lock, and will again be serialized after
    each CPU's quiescent state for the old grace period.

    On the strength of this proof, this commit therefore removes the memory
    barriers from rcu_process_callbacks() and adds one to rcu_report_qs_rsp().
    The effect is to reduce the number of memory barriers by one and to
    reduce the frequency of execution from about once per scheduling tick
    per CPU to once per grace period.

    This was reverted do to hangs found during testing by Yinghai Lu and
    Ingo Molnar. Frederic Weisbecker supplied Yinghai with tracing that
    located the underlying problem, and Frederic also provided the fix.

    The underlying problem was that the HARDIRQ_ENTER() macro from
    lib/locking-selftest.c invoked irq_enter(), which in turn invokes
    rcu_irq_enter(), but HARDIRQ_EXIT() invoked __irq_exit(), which
    does not invoke rcu_irq_exit(). This situation resulted in calls
    to rcu_irq_enter() that were not balanced by the required calls to
    rcu_irq_exit(). Therefore, after these locking selftests completed,
    RCU's dyntick-idle nesting count was a large number (for example,
    72), which caused RCU to to conclude that the affected CPU was not in
    dyntick-idle mode when in fact it was.

    RCU would therefore incorrectly wait for this dyntick-idle CPU, resulting
    in hangs.

    In contrast, with Frederic's patch, which replaces the irq_enter()
    in HARDIRQ_ENTER() with an __irq_enter(), these tests don't ever call
    either rcu_irq_enter() or rcu_irq_exit(), which works because the CPU
    running the test is already marked as not being in dyntick-idle mode.
    This means that the rcu_irq_enter() and rcu_irq_exit() calls and RCU
    then has no problem working out which CPUs are in dyntick-idle mode and
    which are not.

    The reason that the imbalance was not noticed before the barrier patch
    was applied is that the old implementation of rcu_enter_nohz() ignored
    the nesting depth. This could still result in delays, but much shorter
    ones. Whenever there was a delay, RCU would IPI the CPU with the
    unbalanced nesting level, which would eventually result in rcu_enter_nohz()
    being called, which in turn would force RCU to see that the CPU was in
    dyntick-idle mode.

    The reason that very few people noticed the problem is that the mismatched
    irq_enter() vs. __irq_exit() occured only when the kernel was built with
    CONFIG_DEBUG_LOCKING_API_SELFTESTS.

    Signed-off-by: Paul E. McKenney
    Reviewed-by: Josh Triplett

    Paul E. McKenney
     

20 May, 2011

1 commit


08 May, 2011

1 commit

  • Avoid calling into the scheduler while holding core RCU locks. This
    allows rcu_read_unlock() to be called while holding the runqueue locks,
    but only as long as there was no chance of the RCU read-side critical
    section having been preempted. (Otherwise, if RCU priority boosting
    is enabled, rcu_read_unlock() might call into the scheduler in order to
    unboost itself, which might allows self-deadlock on the runqueue locks
    within the scheduler.)

    Signed-off-by: Paul E. McKenney
    Signed-off-by: Paul E. McKenney

    Paul E. McKenney
     

06 May, 2011

9 commits

  • The "preemptible" spelling is preferable. May as well fix it.

    Signed-off-by: Paul E. McKenney
    Reviewed-by: Josh Triplett

    Paul E. McKenney
     
  • This commit adds the age in jiffies of the current grace period along
    with the duration in jiffies of the longest grace period since boot
    to the rcu/rcugp debugfs file. It also adds an additional "O" state
    to kthread tracing to differentiate between the kthread waiting due to
    having nothing to do on the one hand and waiting due to being on the
    wrong CPU on the other hand.

    Signed-off-by: Paul E. McKenney
    Signed-off-by: Paul E. McKenney

    Paul E. McKenney
     
  • Add tracing to help debugging situations when RCU's kthreads are not
    running but are supposed to be.

    Signed-off-by: Paul E. McKenney
    Signed-off-by: Paul E. McKenney
    Reviewed-by: Josh Triplett

    Paul E. McKenney
     
  • Includes total number of tasks boosted, number boosted on behalf of each
    of normal and expedited grace periods, and statistics on attempts to
    initiate boosting that failed for various reasons.

    Signed-off-by: Paul E. McKenney
    Signed-off-by: Paul E. McKenney
    Reviewed-by: Josh Triplett

    Paul E. McKenney
     
  • Add priority boosting for TREE_PREEMPT_RCU, similar to that for
    TINY_PREEMPT_RCU. This is enabled by the default-off RCU_BOOST
    kernel parameter. The priority to which to boost preempted
    RCU readers is controlled by the RCU_BOOST_PRIO kernel parameter
    (defaulting to real-time priority 1) and the time to wait before
    boosting the readers who are blocking a given grace period is
    controlled by the RCU_BOOST_DELAY kernel parameter (defaulting to
    500 milliseconds).

    Signed-off-by: Paul E. McKenney
    Signed-off-by: Paul E. McKenney
    Reviewed-by: Josh Triplett

    Paul E. McKenney
     
  • If RCU priority boosting is to be meaningful, callback invocation must
    be boosted in addition to preempted RCU readers. Otherwise, in presence
    of CPU real-time threads, the grace period ends, but the callbacks don't
    get invoked. If the callbacks don't get invoked, the associated memory
    doesn't get freed, so the system is still subject to OOM.

    But it is not reasonable to priority-boost RCU_SOFTIRQ, so this commit
    moves the callback invocations to a kthread, which can be boosted easily.

    Also add comments and properly synchronized all accesses to
    rcu_cpu_kthread_task, as suggested by Lai Jiangshan.

    Signed-off-by: Paul E. McKenney
    Signed-off-by: Paul E. McKenney
    Reviewed-by: Josh Triplett

    Paul E. McKenney
     
  • Combine the current TREE_PREEMPT_RCU ->blocked_tasks[] lists in the
    rcu_node structure into a single ->blkd_tasks list with ->gp_tasks
    and ->exp_tasks tail pointers. This is in preparation for RCU priority
    boosting, which will add a third dimension to the combinatorial explosion
    in the ->blocked_tasks[] case, but simply a third pointer in the new
    ->blkd_tasks case.

    Also update documentation to reflect blocked_tasks[] merge

    Signed-off-by: Paul E. McKenney
    Signed-off-by: Paul E. McKenney
    Reviewed-by: Josh Triplett

    Paul E. McKenney
     
  • Commit d09b62d fixed grace-period synchronization, but left some smp_mb()
    invocations in rcu_process_callbacks() that are no longer needed, but
    sheer paranoia prevented them from being removed. This commit removes
    them and provides a proof of correctness in their absence. It also adds
    a memory barrier to rcu_report_qs_rsp() immediately before the update to
    rsp->completed in order to handle the theoretical possibility that the
    compiler or CPU might move massive quantities of code into a lock-based
    critical section. This also proves that the sheer paranoia was not
    entirely unjustified, at least from a theoretical point of view.

    In addition, the old dyntick-idle synchronization depended on the fact
    that grace periods were many milliseconds in duration, so that it could
    be assumed that no dyntick-idle CPU could reorder a memory reference
    across an entire grace period. Unfortunately for this design, the
    addition of expedited grace periods breaks this assumption, which has
    the unfortunate side-effect of requiring atomic operations in the
    functions that track dyntick-idle state for RCU. (There is some hope
    that the algorithms used in user-level RCU might be applied here, but
    some work is required to handle the NMIs that user-space applications
    can happily ignore. For the short term, better safe than sorry.)

    This proof assumes that neither compiler nor CPU will allow a lock
    acquisition and release to be reordered, as doing so can result in
    deadlock. The proof is as follows:

    1. A given CPU declares a quiescent state under the protection of
    its leaf rcu_node's lock.

    2. If there is more than one level of rcu_node hierarchy, the
    last CPU to declare a quiescent state will also acquire the
    ->lock of the next rcu_node up in the hierarchy, but only
    after releasing the lower level's lock. The acquisition of this
    lock clearly cannot occur prior to the acquisition of the leaf
    node's lock.

    3. Step 2 repeats until we reach the root rcu_node structure.
    Please note again that only one lock is held at a time through
    this process. The acquisition of the root rcu_node's ->lock
    must occur after the release of that of the leaf rcu_node.

    4. At this point, we set the ->completed field in the rcu_state
    structure in rcu_report_qs_rsp(). However, if the rcu_node
    hierarchy contains only one rcu_node, then in theory the code
    preceding the quiescent state could leak into the critical
    section. We therefore precede the update of ->completed with a
    memory barrier. All CPUs will therefore agree that any updates
    preceding any report of a quiescent state will have happened
    before the update of ->completed.

    5. Regardless of whether a new grace period is needed, rcu_start_gp()
    will propagate the new value of ->completed to all of the leaf
    rcu_node structures, under the protection of each rcu_node's ->lock.
    If a new grace period is needed immediately, this propagation
    will occur in the same critical section that ->completed was
    set in, but courtesy of the memory barrier in #4 above, is still
    seen to follow any pre-quiescent-state activity.

    6. When a given CPU invokes __rcu_process_gp_end(), it becomes
    aware of the end of the old grace period and therefore makes
    any RCU callbacks that were waiting on that grace period eligible
    for invocation.

    If this CPU is the same one that detected the end of the grace
    period, and if there is but a single rcu_node in the hierarchy,
    we will still be in the single critical section. In this case,
    the memory barrier in step #4 guarantees that all callbacks will
    be seen to execute after each CPU's quiescent state.

    On the other hand, if this is a different CPU, it will acquire
    the leaf rcu_node's ->lock, and will again be serialized after
    each CPU's quiescent state for the old grace period.

    On the strength of this proof, this commit therefore removes the memory
    barriers from rcu_process_callbacks() and adds one to rcu_report_qs_rsp().
    The effect is to reduce the number of memory barriers by one and to
    reduce the frequency of execution from about once per scheduling tick
    per CPU to once per grace period.

    Signed-off-by: Paul E. McKenney
    Reviewed-by: Josh Triplett

    Paul E. McKenney
     
  • The RCU CPU stall warnings can now be controlled using the
    rcu_cpu_stall_suppress boot-time parameter or via the same parameter
    from sysfs. There is therefore no longer any reason to have
    kernel config parameters for this feature. This commit therefore
    removes the RCU_CPU_STALL_DETECTOR and RCU_CPU_STALL_DETECTOR_RUNNABLE
    kernel config parameters. The RCU_CPU_STALL_TIMEOUT parameter remains
    to allow the timeout to be tuned and the RCU_CPU_STALL_VERBOSE parameter
    remains to allow task-stall information to be suppressed if desired.

    Signed-off-by: Paul E. McKenney
    Reviewed-by: Josh Triplett

    Paul E. McKenney
     

18 Dec, 2010

1 commit

  • Some recent benchmarks have indicated possible lock contention on the
    leaf-level rcu_node locks. This commit therefore limits the number of
    CPUs per leaf-level rcu_node structure to 16, in other words, there
    can be at most 16 rcu_data structures fanning into a given rcu_node
    structure. Prior to this, the limit was 32 on 32-bit systems and 64 on
    64-bit systems.

    Note that the fanout of non-leaf rcu_node structures is unchanged. The
    organization of accesses to the rcu_node tree is such that references
    to non-leaf rcu_node structures are much less frequent than to the
    leaf structures.

    Signed-off-by: Paul E. McKenney

    Paul E. McKenney
     

30 Nov, 2010

1 commit

  • When we handle the CPU_DYING notifier, the whole system is stopped except
    for the current CPU. We therefore need no synchronization with the other
    CPUs. This allows us to move any orphaned RCU callbacks directly to the
    list of any online CPU without needing to run them through the global
    orphan lists. These global orphan lists can therefore be dispensed with.
    This commit makes thes changes, though currently victimizes CPU 0 @@@.

    Signed-off-by: Lai Jiangshan
    Signed-off-by: Paul E. McKenney

    Lai Jiangshan
     

24 Sep, 2010

1 commit

  • The current tracing data is not sufficient to deduce the average time
    that a callback spends waiting for a grace period to end. Add three
    per-CPU counters recording the number of callbacks invoked (ci), the
    number of callbacks orphaned (co), and the number of callbacks adopted
    (ca). Given the existing callback queue length (ql), the average wait
    time in absence of CPU hotplug operations is ql/ci. The units of wait
    time will be in terms of the duration over which ci was measured.

    In the presence of CPU hotplug operations, there is room for argument,
    but ql/(ci-co+ca) won't steer you too far wrong.

    Also fixes a typo called out by Lucas De Marchi .

    Signed-off-by: Paul E. McKenney

    Paul E. McKenney
     

21 Aug, 2010

2 commits

  • Combine the duplicate definitions of ULONG_CMP_GE(), ULONG_CMP_LT(),
    and rcu_preempt_depth() into include/linux/rcupdate.h.

    Signed-off-by: Paul E. McKenney

    Paul E. McKenney
     
  • When using a kernel debugger, a long sojourn in the debugger can get
    you lots of RCU CPU stall warnings once you resume. This might not be
    helpful, especially if you are using the system console. This patch
    therefore allows RCU CPU stall warnings to be suppressed, but only for
    the duration of the current set of grace periods.

    This differs from Jason's original patch in that it adds support for
    tiny RCU and preemptible RCU, and uses a slightly different method for
    suppressing the RCU CPU stall warning messages.

    Signed-off-by: Jason Wessel
    Signed-off-by: Paul E. McKenney
    Tested-by: Jason Wessel

    Paul E. McKenney
     

20 Aug, 2010

3 commits

  • Currently, if RCU CPU stall warnings are enabled, they are enabled
    immediately upon boot. They can be manually disabled via /sys (and
    also re-enabled via /sys), and are automatically disabled upon panic.
    However, some users need RCU CPU stalls to be disabled at boot time,
    but to be enabled without rebuilding/rebooting. For example, someone
    running a real-time application in production might not want the
    additional latency of RCU CPU stall detection in normal operation, but
    might need to enable it at any point for fault isolation purposes.

    This commit therefore provides a new CONFIG_RCU_CPU_STALL_DETECTOR_RUNNABLE
    kernel configuration parameter that maintains the current behavior
    (enable at boot) by default, but allows a kernel to be configured
    with RCU CPU stall detection built into the kernel, but disabled at
    boot time.

    Requested-by: Clark Williams
    Requested-by: John Kacur
    Signed-off-by: Paul E. McKenney

    Paul E. McKenney
     
  • Also set the default to 60 seconds, up from the previous hard-coded timeout
    of 10 seconds. This allows people who care to set short timeouts, while
    avoiding people with unusual configurations (make randconfig!!!) from being
    bothered with spurious CPU stall warnings.

    Signed-off-by: Paul E. McKenney
    Reviewed-by: Josh Triplett

    Paul E. McKenney
     
  • &percpu_data is compatible with allocated percpu data.

    And we use it and remove the "->rda[NR_CPUS]" array, saving significant
    storage on systems with large numbers of CPUs. This does add an additional
    level of indirection and thus an additional cache line referenced, but
    because ->rda is not used on the read side, this is OK.

    Signed-off-by: Lai Jiangshan
    Reviewed-by: Tejun Heo
    Signed-off-by: Paul E. McKenney
    Reviewed-by: Josh Triplett

    Lai Jiangshan
     

11 May, 2010

2 commits

  • Lai Jiangshan noted that up to 10% of the RCU_SOFTIRQ are spurious, and
    traced this down to the fact that the current grace-period machinery
    will uselessly raise RCU_SOFTIRQ when a given CPU needs to go through
    a quiescent state, but has not yet done so. In this situation, there
    might well be nothing that RCU_SOFTIRQ can do, and the overhead can be
    worth worrying about in the ksoftirqd case. This patch therefore avoids
    raising RCU_SOFTIRQ in this situation.

    Changes since v1 (http://lkml.org/lkml/2010/3/30/122 from Lai Jiangshan):

    o Omit the rcu_qs_pending() prechecks, as they aren't that
    much less expensive than the quiescent-state checks.

    o Merge with the set_need_resched() patch that reduces IPIs.

    o Add the new n_rp_report_qs field to the rcu_pending tracing output.

    o Update the tracing documentation accordingly.

    Signed-off-by: Lai Jiangshan
    Signed-off-by: Paul E. McKenney

    Paul E. McKenney
     
  • The existing RCU CPU stall-warning messages can be confusing, especially
    in the case where one CPU detects a single other stalled CPU. In addition,
    the console messages did not say which flavor of RCU detected the stall,
    which can make it difficult to work out exactly what is causing the stall.
    This commit improves these messages.

    Requested-by: Dhaval Giani
    Signed-off-by: Paul E. McKenney

    Paul E. McKenney
     

11 Mar, 2010

1 commit

  • CONFIG_PROVE_RCU imposes additional overhead on the kernel, so
    increase the RCU CPU stall timeouts in an attempt to allow for
    this effect.

    Signed-off-by: Paul E. McKenney
    Cc: laijs@cn.fujitsu.com
    Cc: dipankar@in.ibm.com
    Cc: mathieu.desnoyers@polymtl.ca
    Cc: josh@joshtriplett.org
    Cc: dvhltc@us.ibm.com
    Cc: niv@us.ibm.com
    Cc: peterz@infradead.org
    Cc: rostedt@goodmis.org
    Cc: Valdis.Kletnieks@vt.edu
    Cc: dhowells@redhat.com
    LKML-Reference:
    Signed-off-by: Ingo Molnar

    Paul E. McKenney
     

27 Feb, 2010

1 commit

  • It is invalid to invoke __rcu_process_callbacks() with irqs
    disabled, so do it indirectly via raise_softirq(). This
    requires a state-machine implementation to cycle through the
    grace-period machinery the required number of times.

    Located-by: Ingo Molnar
    Signed-off-by: Paul E. McKenney
    Cc: laijs@cn.fujitsu.com
    Cc: dipankar@in.ibm.com
    Cc: mathieu.desnoyers@polymtl.ca
    Cc: josh@joshtriplett.org
    Cc: dvhltc@us.ibm.com
    Cc: niv@us.ibm.com
    Cc: peterz@infradead.org
    Cc: rostedt@goodmis.org
    Cc: Valdis.Kletnieks@vt.edu
    Cc: dhowells@redhat.com
    LKML-Reference:
    Signed-off-by: Ingo Molnar

    Paul E. McKenney
     

25 Feb, 2010

3 commits

  • When RCU detects a grace-period stall, it currently just prints
    out the PID of any tasks doing the stalling. This patch adds
    RCU_CPU_STALL_VERBOSE, which enables the more-verbose reporting
    from sched_show_task().

    Suggested-by: Thomas Gleixner
    Signed-off-by: Paul E. McKenney
    Cc: laijs@cn.fujitsu.com
    Cc: dipankar@in.ibm.com
    Cc: mathieu.desnoyers@polymtl.ca
    Cc: josh@joshtriplett.org
    Cc: dvhltc@us.ibm.com
    Cc: niv@us.ibm.com
    Cc: peterz@infradead.org
    Cc: rostedt@goodmis.org
    Cc: Valdis.Kletnieks@vt.edu
    Cc: dhowells@redhat.com
    LKML-Reference:
    Signed-off-by: Ingo Molnar

    Paul E. McKenney
     
  • The spinlocks in rcutree need to be real spinlocks in
    preempt-rt. Convert them to raw_spinlocks.

    Signed-off-by: Thomas Gleixner
    Signed-off-by: Paul E. McKenney
    Cc: laijs@cn.fujitsu.com
    Cc: dipankar@in.ibm.com
    Cc: mathieu.desnoyers@polymtl.ca
    Cc: josh@joshtriplett.org
    Cc: dvhltc@us.ibm.com
    Cc: niv@us.ibm.com
    Cc: peterz@infradead.org
    Cc: rostedt@goodmis.org
    Cc: Valdis.Kletnieks@vt.edu
    Cc: dhowells@redhat.com
    LKML-Reference:
    Signed-off-by: Ingo Molnar

    Paul E. McKenney
     
  • The C standard does not specify the result of an operation that
    overflows a signed integer, so such operations need to be
    avoided. This patch changes the type of several fields from
    "long" to "unsigned long" and adjusts operations as needed.
    ULONG_CMP_GE() and ULONG_CMP_LT() macros are introduced to do
    the modular comparisons that are appropriate given that overflow
    is an expected event.

    Acked-by: Mathieu Desnoyers
    Signed-off-by: Paul E. McKenney
    Cc: laijs@cn.fujitsu.com
    Cc: dipankar@in.ibm.com
    Cc: mathieu.desnoyers@polymtl.ca
    Cc: josh@joshtriplett.org
    Cc: dvhltc@us.ibm.com
    Cc: niv@us.ibm.com
    Cc: peterz@infradead.org
    Cc: rostedt@goodmis.org
    Cc: Valdis.Kletnieks@vt.edu
    Cc: dhowells@redhat.com
    LKML-Reference:
    Signed-off-by: Ingo Molnar

    Paul E. McKenney
     

16 Jan, 2010

1 commit

  • Rename local variable "i" in rcu_init() to avoid conflict with
    RCU_INIT_FLAVOR(), restrict the scope of RCU_TREE_NONCORE, and
    make __synchronize_srcu() static.

    Signed-off-by: Paul E. McKenney
    Cc: laijs@cn.fujitsu.com
    Cc: dipankar@in.ibm.com
    Cc: mathieu.desnoyers@polymtl.ca
    Cc: josh@joshtriplett.org
    Cc: dvhltc@us.ibm.com
    Cc: niv@us.ibm.com
    Cc: peterz@infradead.org
    Cc: rostedt@goodmis.org
    Cc: Valdis.Kletnieks@vt.edu
    Cc: dhowells@redhat.com
    LKML-Reference:
    Signed-off-by: Ingo Molnar

    Paul E. McKenney
     

13 Jan, 2010

4 commits

  • Grace periods cannot be started while force_quiescent_state() is
    active. This is OK in that the affected CPUs will try again
    later, but it does induce needless grace-period delays. This
    patch causes rcu_start_gp() to record a failed attempt to start
    a grace period. When force_quiescent_state() prepares to return,
    it then starts the grace period if there was such a failed
    attempt.

    Signed-off-by: Paul E. McKenney
    Cc: laijs@cn.fujitsu.com
    Cc: dipankar@in.ibm.com
    Cc: mathieu.desnoyers@polymtl.ca
    Cc: josh@joshtriplett.org
    Cc: dvhltc@us.ibm.com
    Cc: niv@us.ibm.com
    Cc: peterz@infradead.org
    Cc: rostedt@goodmis.org
    Cc: Valdis.Kletnieks@vt.edu
    Cc: dhowells@redhat.com
    LKML-Reference:
    Signed-off-by: Ingo Molnar

    Paul E. McKenney
     
  • The comparisons of rsp->gpnum nad rsp->completed in
    rcu_process_dyntick() and force_quiescent_state() can be
    replaced by the much more clear rcu_gp_in_progress() predicate
    function. After doing this, it becomes clear that the
    RCU_SAVE_COMPLETED leg of the force_quiescent_state() function's
    switch statement is almost completely a no-op. A small change
    to the RCU_SAVE_DYNTICK leg renders it a complete no-op, after
    which it can be removed. Doing so also eliminates the forcenow
    local variable from force_quiescent_state().

    Signed-off-by: Paul E. McKenney
    Cc: laijs@cn.fujitsu.com
    Cc: dipankar@in.ibm.com
    Cc: mathieu.desnoyers@polymtl.ca
    Cc: josh@joshtriplett.org
    Cc: dvhltc@us.ibm.com
    Cc: niv@us.ibm.com
    Cc: peterz@infradead.org
    Cc: rostedt@goodmis.org
    Cc: Valdis.Kletnieks@vt.edu
    Cc: dhowells@redhat.com
    LKML-Reference:
    Signed-off-by: Ingo Molnar

    Paul E. McKenney
     
  • Because rsp->fqs_active is set to 1 across
    force_quiescent_state()'s switch statement, rcu_start_gp() will
    refrain from starting a new grace period during this time.
    Therefore, rsp->gpnum is constant, and can be propagated to all
    uses of lastcomp, eliminating this local variable.

    Signed-off-by: Paul E. McKenney
    Cc: laijs@cn.fujitsu.com
    Cc: dipankar@in.ibm.com
    Cc: mathieu.desnoyers@polymtl.ca
    Cc: josh@joshtriplett.org
    Cc: dvhltc@us.ibm.com
    Cc: niv@us.ibm.com
    Cc: peterz@infradead.org
    Cc: rostedt@goodmis.org
    Cc: Valdis.Kletnieks@vt.edu
    Cc: dhowells@redhat.com
    LKML-Reference:
    Signed-off-by: Ingo Molnar

    Paul E. McKenney
     
  • Reduce the number and variety of race conditions by prohibiting
    the start of a new grace period while force_quiescent_state() is
    active. A new fqs_active flag in the rcu_state structure is used
    to trace whether or not force_quiescent_state() is active, and
    this new flag is tested by rcu_start_gp(). If the CPU that
    closed out the last grace period needs another grace period,
    this new grace period may be delayed up to one scheduling-clock
    tick, but it will eventually get started.

    Signed-off-by: Paul E. McKenney
    Cc: laijs@cn.fujitsu.com
    Cc: dipankar@in.ibm.com
    Cc: mathieu.desnoyers@polymtl.ca
    Cc: josh@joshtriplett.org
    Cc: dvhltc@us.ibm.com
    Cc: niv@us.ibm.com
    Cc: peterz@infradead.org
    Cc: rostedt@goodmis.org
    Cc: Valdis.Kletnieks@vt.edu
    Cc: dhowells@redhat.com
    LKML-Reference:
    Signed-off-by: Ingo Molnar

    Paul E. McKenney
     

03 Dec, 2009

3 commits

  • Implement an synchronize_rcu_expedited() for preemptible RCU
    that actually is expedited. This uses
    synchronize_sched_expedited() to force all threads currently
    running in a preemptible-RCU read-side critical section onto the
    appropriate ->blocked_tasks[] list, then takes a snapshot of all
    of these lists and waits for them to drain.

    Signed-off-by: Paul E. McKenney
    Cc: laijs@cn.fujitsu.com
    Cc: dipankar@in.ibm.com
    Cc: mathieu.desnoyers@polymtl.ca
    Cc: josh@joshtriplett.org
    Cc: dvhltc@us.ibm.com
    Cc: niv@us.ibm.com
    Cc: peterz@infradead.org
    Cc: rostedt@goodmis.org
    Cc: Valdis.Kletnieks@vt.edu
    Cc: dhowells@redhat.com
    LKML-Reference:
    Signed-off-by: Ingo Molnar

    Paul E. McKenney
     
  • Enable a fourth level of rcu_node hierarchy for TREE_RCU and
    TREE_PREEMPT_RCU. This is for stress-testing and experiemental
    purposes only, although in theory this would enable 16,777,216
    CPUs on 64-bit systems, though only 1,048,576 CPUs on 32-bit
    systems. Normal experimental use of this fourth level will
    normally set CONFIG_RCU_FANOUT=2, requiring a 16-CPU system,
    though the more adventurous (and more fortunate) experimenters
    may wish to chose CONFIG_RCU_FANOUT=3 for 81-CPU systems or even
    CONFIG_RCU_FANOUT=4 for 256-CPU systems.

    Signed-off-by: Paul E. McKenney
    Acked-by: Josh Triplett
    Acked-by: Lai Jiangshan
    Cc: dipankar@in.ibm.com
    Cc: mathieu.desnoyers@polymtl.ca
    Cc: dvhltc@us.ibm.com
    Cc: niv@us.ibm.com
    Cc: peterz@infradead.org
    Cc: rostedt@goodmis.org
    Cc: Valdis.Kletnieks@vt.edu
    Cc: dhowells@redhat.com
    LKML-Reference:
    Signed-off-by: Ingo Molnar

    Paul E. McKenney
     
  • The number of "quiet" functions has grown recently, and the
    names are no longer very descriptive. The point of all of these
    functions is to do some portion of the task of reporting a
    quiescent state, so rename them accordingly:

    o cpu_quiet() becomes rcu_report_qs_rdp(), which reports a
    quiescent state to the per-CPU rcu_data structure. If this
    turns out to be a new quiescent state for this grace period,
    then rcu_report_qs_rnp() will be invoked to propagate the
    quiescent state up the rcu_node hierarchy.

    o cpu_quiet_msk() becomes rcu_report_qs_rnp(), which reports
    a quiescent state for a given CPU (or possibly a set of CPUs)
    up the rcu_node hierarchy.

    o cpu_quiet_msk_finish() becomes rcu_report_qs_rsp(), which
    reports a full set of quiescent states to the global rcu_state
    structure.

    o task_quiet() becomes rcu_report_unblock_qs_rnp(), which reports
    a quiescent state due to a task exiting an RCU read-side critical
    section that had previously blocked in that same critical section.
    As indicated by the new name, this type of quiescent state is
    reported up the rcu_node hierarchy (using rcu_report_qs_rnp()
    to do so).

    Signed-off-by: Paul E. McKenney
    Acked-by: Josh Triplett
    Acked-by: Lai Jiangshan
    Cc: dipankar@in.ibm.com
    Cc: mathieu.desnoyers@polymtl.ca
    Cc: dvhltc@us.ibm.com
    Cc: niv@us.ibm.com
    Cc: peterz@infradead.org
    Cc: rostedt@goodmis.org
    Cc: Valdis.Kletnieks@vt.edu
    Cc: dhowells@redhat.com
    LKML-Reference:
    Signed-off-by: Ingo Molnar

    Paul E. McKenney