History

rcu: Expedite deboost in case of deferred quiescent state

Historically, a task that has been subjected to RCU priority boosting is deboosted at rcu_read_unlock() time. However, with the advent of deferred quiescent states, if the outermost rcu_read_unlock() was invoked with either bottom halves, interrupts, or preemption disabled, the deboosting will be delayed for some time. During this time, a low-priority process might be incorrectly running at a high real-time priority level. Fortunately, rcu_read_unlock_special() already provides mechanisms for forcing a minimal deferral of quiescent states, at least for kernels built with CONFIG_IRQ_WORK=y. These mechanisms are currently used when expedited grace periods are pending that might be blocked by the current task. This commit therefore causes those mechanisms to also be used in cases where the current task has been or might soon be subjected to RCU priority boosting. Note that this applies to all kernels built with CONFIG_RCU_BOOST=y, regardless of whether or not they are also built with CONFIG_PREEMPT_RT=y. This approach assumes that kernels build for use with aggressive real-time applications are built with CONFIG_IRQ_WORK=y. It is likely to be far simpler to enable CONFIG_IRQ_WORK=y than to implement a fast-deboosting scheme that works correctly in its absence. While in the area, alphabetize the rcu_preempt_deferred_qs_handler() function's local variables.

Paul E. McKenney committed 5 years ago

Commit 39bbfc61 parent a38fd871 file · +14 −12Browse files

Showing the changes to kernel (1 of 1 file). Show all

Unified · Split

kernel/rcu/tree_plugin.h+14−12
@@ -598,9 +598,9 @@ static void rcu_preempt_deferred_qs_handler(struct irq_work *iwp) · 597 unmodified lines
598static void rcu_read_unlock_special(struct task_struct *t)598static void rcu_read_unlock_special(struct task_struct *t)
599{599{
600 unsigned long flags;600 unsigned long flags;
601 bool irqs_were_disabled;
601 bool preempt_bh_were_disabled =602 bool preempt_bh_were_disabled =
602 !!(preempt_count() & (PREEMPT_MASK | SOFTIRQ_MASK));603 !!(preempt_count() & (PREEMPT_MASK | SOFTIRQ_MASK));
603 bool irqs_were_disabled;
604 604
605 /* NMI handlers cannot block and cannot safely manipulate state. */605 /* NMI handlers cannot block and cannot safely manipulate state. */
606 if (in_nmi())606 if (in_nmi())
@@ -609,30 +609,32 @@ static void rcu_read_unlock_special(struct task_struct *t) · 2 unmodified lines
609 local_irq_save(flags);609 local_irq_save(flags);
610 irqs_were_disabled = irqs_disabled_flags(flags);610 irqs_were_disabled = irqs_disabled_flags(flags);
611 if (preempt_bh_were_disabled || irqs_were_disabled) {611 if (preempt_bh_were_disabled || irqs_were_disabled) {
612 bool exp;612 bool expboost; // Expedited GP in flight or possible boosting.
613 struct rcu_data *rdp = this_cpu_ptr(&rcu_data);613 struct rcu_data *rdp = this_cpu_ptr(&rcu_data);
614 struct rcu_node *rnp = rdp->mynode;614 struct rcu_node *rnp = rdp->mynode;
615 615
616 exp = (t->rcu_blocked_node &&616 expboost = (t->rcu_blocked_node && READ_ONCE(t->rcu_blocked_node->exp_tasks)) ||
617 READ_ONCE(t->rcu_blocked_node->exp_tasks)) ||617 (rdp->grpmask & READ_ONCE(rnp->expmask)) ||
618 (rdp->grpmask & READ_ONCE(rnp->expmask));618 (IS_ENABLED(CONFIG_RCU_BOOST) && irqs_were_disabled &&
619 t->rcu_blocked_node);
619 // Need to defer quiescent state until everything is enabled.620 // Need to defer quiescent state until everything is enabled.
620 if (use_softirq && (in_irq() || (exp && !irqs_were_disabled))) {621 if (use_softirq && (in_irq() || (expboost && !irqs_were_disabled))) {
621 // Using softirq, safe to awaken, and either the622 // Using softirq, safe to awaken, and either the
622 // wakeup is free or there is an expedited GP.623 // wakeup is free or there is either an expedited
624 // GP in flight or a potential need to deboost.
623 raise_softirq_irqoff(RCU_SOFTIRQ);625 raise_softirq_irqoff(RCU_SOFTIRQ);
624 } else {626 } else {
625 // Enabling BH or preempt does reschedule, so...627 // Enabling BH or preempt does reschedule, so...
626 // Also if no expediting, slow is OK.628 // Also if no expediting and no possible deboosting,
627 // Plus nohz_full CPUs eventually get tick enabled.629 // slow is OK. Plus nohz_full CPUs eventually get
630 // tick enabled.
628 set_tsk_need_resched(current);631 set_tsk_need_resched(current);
629 set_preempt_need_resched();632 set_preempt_need_resched();
630 if (IS_ENABLED(CONFIG_IRQ_WORK) && irqs_were_disabled &&633 if (IS_ENABLED(CONFIG_IRQ_WORK) && irqs_were_disabled &&
631 !rdp->defer_qs_iw_pending && exp && cpu_online(rdp->cpu)) {634 expboost && !rdp->defer_qs_iw_pending && cpu_online(rdp->cpu)) {
632 // Get scheduler to re-evaluate and call hooks.635 // Get scheduler to re-evaluate and call hooks.
633 // If !IRQ_WORK, FQS scan will eventually IPI.636 // If !IRQ_WORK, FQS scan will eventually IPI.
634 init_irq_work(&rdp->defer_qs_iw,637 init_irq_work(&rdp->defer_qs_iw, rcu_preempt_deferred_qs_handler);
635 rcu_preempt_deferred_qs_handler);
636 rdp->defer_qs_iw_pending = true;638 rdp->defer_qs_iw_pending = true;
637 irq_work_queue_on(&rdp->defer_qs_iw, rdp->cpu);639 irq_work_queue_on(&rdp->defer_qs_iw, rdp->cpu);
638 }640 }

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t