aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul E. McKenney <paulmck@linux.vnet.ibm.com>2014-12-12 10:37:48 -0500
committerPaul E. McKenney <paulmck@linux.vnet.ibm.com>2015-01-16 02:25:04 -0500
commita94844b22a2e2b9155bbc0878c507850477221c2 (patch)
treea7a9504a509d05b7b793d629bb3116a811f0c4a9
parente3663b1024d1f94688e5233440ad67a9bc10b94e (diff)
rcu: Optionally run grace-period kthreads at real-time priority
Recent testing has shown that under heavy load, running RCU's grace-period kthreads at real-time priority can improve performance (according to 0day test robot) and reduce the incidence of RCU CPU stall warnings. However, most systems do just fine with the default non-realtime priorities for these kthreads, and it does not make sense to expose the entire user base to any risk stemming from this change, given that this change is of use only to a few users running extremely heavy workloads. Therefore, this commit allows users to specify realtime priorities for the grace-period kthreads, but leaves them running SCHED_OTHER by default. The realtime priority may be specified at build time via the RCU_KTHREAD_PRIO Kconfig parameter, or at boot time via the rcutree.kthread_prio parameter. Either way, 0 says to continue the default SCHED_OTHER behavior and values from 1-99 specify that priority of SCHED_FIFO behavior. Note that a value of 0 is not permitted when the RCU_BOOST Kconfig parameter is specified. Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
-rw-r--r--init/Kconfig7
-rw-r--r--kernel/rcu/tree.c24
-rw-r--r--kernel/rcu/tree_plugin.h4
3 files changed, 27 insertions, 8 deletions
diff --git a/init/Kconfig b/init/Kconfig
index 9afb971497f4..d3ee66a6990f 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -668,9 +668,10 @@ config RCU_BOOST
668 668
669config RCU_KTHREAD_PRIO 669config RCU_KTHREAD_PRIO
670 int "Real-time priority to use for RCU worker threads" 670 int "Real-time priority to use for RCU worker threads"
671 range 1 99 671 range 1 99 if RCU_BOOST
672 depends on RCU_BOOST 672 range 0 99 if !RCU_BOOST
673 default 1 673 default 1 if RCU_BOOST
674 default 0 if !RCU_BOOST
674 help 675 help
675 This option specifies the SCHED_FIFO priority value that will be 676 This option specifies the SCHED_FIFO priority value that will be
676 assigned to the rcuc/n and rcub/n threads and is also the value 677 assigned to the rcuc/n and rcub/n threads and is also the value
diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
index 5987fdc85fc4..75ce12316b4c 100644
--- a/kernel/rcu/tree.c
+++ b/kernel/rcu/tree.c
@@ -156,6 +156,10 @@ static void rcu_boost_kthread_setaffinity(struct rcu_node *rnp, int outgoingcpu)
156static void invoke_rcu_core(void); 156static void invoke_rcu_core(void);
157static void invoke_rcu_callbacks(struct rcu_state *rsp, struct rcu_data *rdp); 157static void invoke_rcu_callbacks(struct rcu_state *rsp, struct rcu_data *rdp);
158 158
159/* rcuc/rcub kthread realtime priority */
160static int kthread_prio = CONFIG_RCU_KTHREAD_PRIO;
161module_param(kthread_prio, int, 0644);
162
159/* 163/*
160 * Track the rcutorture test sequence number and the update version 164 * Track the rcutorture test sequence number and the update version
161 * number within a given test. The rcutorture_testseq is incremented 165 * number within a given test. The rcutorture_testseq is incremented
@@ -3597,17 +3601,35 @@ static int rcu_pm_notify(struct notifier_block *self,
3597static int __init rcu_spawn_gp_kthread(void) 3601static int __init rcu_spawn_gp_kthread(void)
3598{ 3602{
3599 unsigned long flags; 3603 unsigned long flags;
3604 int kthread_prio_in = kthread_prio;
3600 struct rcu_node *rnp; 3605 struct rcu_node *rnp;
3601 struct rcu_state *rsp; 3606 struct rcu_state *rsp;
3607 struct sched_param sp;
3602 struct task_struct *t; 3608 struct task_struct *t;
3603 3609
3610 /* Force priority into range. */
3611 if (IS_ENABLED(CONFIG_RCU_BOOST) && kthread_prio < 1)
3612 kthread_prio = 1;
3613 else if (kthread_prio < 0)
3614 kthread_prio = 0;
3615 else if (kthread_prio > 99)
3616 kthread_prio = 99;
3617 if (kthread_prio != kthread_prio_in)
3618 pr_alert("rcu_spawn_gp_kthread(): Limited prio to %d from %d\n",
3619 kthread_prio, kthread_prio_in);
3620
3604 rcu_scheduler_fully_active = 1; 3621 rcu_scheduler_fully_active = 1;
3605 for_each_rcu_flavor(rsp) { 3622 for_each_rcu_flavor(rsp) {
3606 t = kthread_run(rcu_gp_kthread, rsp, "%s", rsp->name); 3623 t = kthread_create(rcu_gp_kthread, rsp, "%s", rsp->name);
3607 BUG_ON(IS_ERR(t)); 3624 BUG_ON(IS_ERR(t));
3608 rnp = rcu_get_root(rsp); 3625 rnp = rcu_get_root(rsp);
3609 raw_spin_lock_irqsave(&rnp->lock, flags); 3626 raw_spin_lock_irqsave(&rnp->lock, flags);
3610 rsp->gp_kthread = t; 3627 rsp->gp_kthread = t;
3628 if (kthread_prio) {
3629 sp.sched_priority = kthread_prio;
3630 sched_setscheduler_nocheck(t, SCHED_FIFO, &sp);
3631 }
3632 wake_up_process(t);
3611 raw_spin_unlock_irqrestore(&rnp->lock, flags); 3633 raw_spin_unlock_irqrestore(&rnp->lock, flags);
3612 } 3634 }
3613 rcu_spawn_nocb_kthreads(); 3635 rcu_spawn_nocb_kthreads();
diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h
index 81ff8b9a5a39..dcb32638f88b 100644
--- a/kernel/rcu/tree_plugin.h
+++ b/kernel/rcu/tree_plugin.h
@@ -34,10 +34,6 @@
34 34
35#include "../locking/rtmutex_common.h" 35#include "../locking/rtmutex_common.h"
36 36
37/* rcuc/rcub kthread realtime priority */
38static int kthread_prio = CONFIG_RCU_KTHREAD_PRIO;
39module_param(kthread_prio, int, 0644);
40
41/* 37/*
42 * Control variables for per-CPU and per-rcu_node kthreads. These 38 * Control variables for per-CPU and per-rcu_node kthreads. These
43 * handle all flavors of RCU. 39 * handle all flavors of RCU.