summaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorPaul E. McKenney <paulmck@linux.vnet.ibm.com>2015-11-24 18:44:06 -0500
committerPaul E. McKenney <paulmck@linux.vnet.ibm.com>2015-12-04 15:26:53 -0500
commit5a9be7c628c5273f84abacebf7faf2488376e0f0 (patch)
tree4d39aabecb8cc7542a053b3f9761f8e119f25450 /kernel
parent72611ab9f5d2d384a04e72d560c9c82463115cbf (diff)
rcu: Add rcu_normal kernel parameter to suppress expediting
Although expedited grace periods can be quite useful, and although their OS jitter has been greatly reduced, they can still pose problems for extreme real-time workloads. This commit therefore adds a rcu_normal kernel boot parameter (which can also be manipulated via sysfs) to suppress expedited grace periods, that is, to treat requests for expedited grace periods as if they were requests for normal grace periods. If both rcu_expedited and rcu_normal are specified, rcu_normal wins. This means that if you are relying on expedited grace periods to speed up boot, you will want to specify rcu_expedited on the kernel command line, and then specify rcu_normal via sysfs once boot completes. Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/ksysfs.c22
-rw-r--r--kernel/rcu/srcu.c2
-rw-r--r--kernel/rcu/tree.c6
-rw-r--r--kernel/rcu/tree_plugin.h6
-rw-r--r--kernel/rcu/update.c12
5 files changed, 45 insertions, 3 deletions
diff --git a/kernel/ksysfs.c b/kernel/ksysfs.c
index e83b26464061..b4e2fa52d8bc 100644
--- a/kernel/ksysfs.c
+++ b/kernel/ksysfs.c
@@ -20,7 +20,7 @@
20#include <linux/capability.h> 20#include <linux/capability.h>
21#include <linux/compiler.h> 21#include <linux/compiler.h>
22 22
23#include <linux/rcupdate.h> /* rcu_expedited */ 23#include <linux/rcupdate.h> /* rcu_expedited and rcu_normal */
24 24
25#define KERNEL_ATTR_RO(_name) \ 25#define KERNEL_ATTR_RO(_name) \
26static struct kobj_attribute _name##_attr = __ATTR_RO(_name) 26static struct kobj_attribute _name##_attr = __ATTR_RO(_name)
@@ -148,7 +148,7 @@ int rcu_expedited;
148static ssize_t rcu_expedited_show(struct kobject *kobj, 148static ssize_t rcu_expedited_show(struct kobject *kobj,
149 struct kobj_attribute *attr, char *buf) 149 struct kobj_attribute *attr, char *buf)
150{ 150{
151 return sprintf(buf, "%d\n", rcu_expedited); 151 return sprintf(buf, "%d\n", READ_ONCE(rcu_expedited));
152} 152}
153static ssize_t rcu_expedited_store(struct kobject *kobj, 153static ssize_t rcu_expedited_store(struct kobject *kobj,
154 struct kobj_attribute *attr, 154 struct kobj_attribute *attr,
@@ -161,6 +161,23 @@ static ssize_t rcu_expedited_store(struct kobject *kobj,
161} 161}
162KERNEL_ATTR_RW(rcu_expedited); 162KERNEL_ATTR_RW(rcu_expedited);
163 163
164int rcu_normal;
165static ssize_t rcu_normal_show(struct kobject *kobj,
166 struct kobj_attribute *attr, char *buf)
167{
168 return sprintf(buf, "%d\n", READ_ONCE(rcu_normal));
169}
170static ssize_t rcu_normal_store(struct kobject *kobj,
171 struct kobj_attribute *attr,
172 const char *buf, size_t count)
173{
174 if (kstrtoint(buf, 0, &rcu_normal))
175 return -EINVAL;
176
177 return count;
178}
179KERNEL_ATTR_RW(rcu_normal);
180
164/* 181/*
165 * Make /sys/kernel/notes give the raw contents of our kernel .notes section. 182 * Make /sys/kernel/notes give the raw contents of our kernel .notes section.
166 */ 183 */
@@ -203,6 +220,7 @@ static struct attribute * kernel_attrs[] = {
203 &vmcoreinfo_attr.attr, 220 &vmcoreinfo_attr.attr,
204#endif 221#endif
205 &rcu_expedited_attr.attr, 222 &rcu_expedited_attr.attr,
223 &rcu_normal_attr.attr,
206 NULL 224 NULL
207}; 225};
208 226
diff --git a/kernel/rcu/srcu.c b/kernel/rcu/srcu.c
index a63a1ea5a41b..9b9cdd549caa 100644
--- a/kernel/rcu/srcu.c
+++ b/kernel/rcu/srcu.c
@@ -489,7 +489,7 @@ static void __synchronize_srcu(struct srcu_struct *sp, int trycount)
489 */ 489 */
490void synchronize_srcu(struct srcu_struct *sp) 490void synchronize_srcu(struct srcu_struct *sp)
491{ 491{
492 __synchronize_srcu(sp, rcu_gp_is_expedited() 492 __synchronize_srcu(sp, (rcu_gp_is_expedited() && !rcu_gp_is_normal())
493 ? SYNCHRONIZE_SRCU_EXP_TRYCOUNT 493 ? SYNCHRONIZE_SRCU_EXP_TRYCOUNT
494 : SYNCHRONIZE_SRCU_TRYCOUNT); 494 : SYNCHRONIZE_SRCU_TRYCOUNT);
495} 495}
diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
index 6a652d1f3d7f..489992997c06 100644
--- a/kernel/rcu/tree.c
+++ b/kernel/rcu/tree.c
@@ -3841,6 +3841,12 @@ void synchronize_sched_expedited(void)
3841 if (rcu_blocking_is_gp()) 3841 if (rcu_blocking_is_gp())
3842 return; 3842 return;
3843 3843
3844 /* If expedited grace periods are prohibited, fall back to normal. */
3845 if (rcu_gp_is_normal()) {
3846 wait_rcu_gp(call_rcu_sched);
3847 return;
3848 }
3849
3844 /* Take a snapshot of the sequence number. */ 3850 /* Take a snapshot of the sequence number. */
3845 s = rcu_exp_gp_seq_snap(rsp); 3851 s = rcu_exp_gp_seq_snap(rsp);
3846 3852
diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h
index 57ba873d2f18..d45df3781551 100644
--- a/kernel/rcu/tree_plugin.h
+++ b/kernel/rcu/tree_plugin.h
@@ -746,6 +746,12 @@ void synchronize_rcu_expedited(void)
746 struct rcu_state *rsp = rcu_state_p; 746 struct rcu_state *rsp = rcu_state_p;
747 unsigned long s; 747 unsigned long s;
748 748
749 /* If expedited grace periods are prohibited, fall back to normal. */
750 if (rcu_gp_is_normal()) {
751 wait_rcu_gp(call_rcu);
752 return;
753 }
754
749 s = rcu_exp_gp_seq_snap(rsp); 755 s = rcu_exp_gp_seq_snap(rsp);
750 756
751 rnp_unlock = exp_funnel_lock(rsp, s); 757 rnp_unlock = exp_funnel_lock(rsp, s);
diff --git a/kernel/rcu/update.c b/kernel/rcu/update.c
index 5f748c5a40f0..8fccda3a794d 100644
--- a/kernel/rcu/update.c
+++ b/kernel/rcu/update.c
@@ -61,6 +61,7 @@ MODULE_ALIAS("rcupdate");
61#define MODULE_PARAM_PREFIX "rcupdate." 61#define MODULE_PARAM_PREFIX "rcupdate."
62 62
63module_param(rcu_expedited, int, 0); 63module_param(rcu_expedited, int, 0);
64module_param(rcu_normal, int, 0);
64 65
65#if defined(CONFIG_DEBUG_LOCK_ALLOC) && defined(CONFIG_PREEMPT_COUNT) 66#if defined(CONFIG_DEBUG_LOCK_ALLOC) && defined(CONFIG_PREEMPT_COUNT)
66/** 67/**
@@ -113,6 +114,17 @@ EXPORT_SYMBOL(rcu_read_lock_sched_held);
113 114
114#ifndef CONFIG_TINY_RCU 115#ifndef CONFIG_TINY_RCU
115 116
117/*
118 * Should expedited grace-period primitives always fall back to their
119 * non-expedited counterparts? Intended for use within RCU. Note
120 * that if the user specifies both rcu_expedited and rcu_normal, then
121 * rcu_normal wins.
122 */
123bool rcu_gp_is_normal(void)
124{
125 return READ_ONCE(rcu_normal);
126}
127
116static atomic_t rcu_expedited_nesting = 128static atomic_t rcu_expedited_nesting =
117 ATOMIC_INIT(IS_ENABLED(CONFIG_RCU_EXPEDITE_BOOT) ? 1 : 0); 129 ATOMIC_INIT(IS_ENABLED(CONFIG_RCU_EXPEDITE_BOOT) ? 1 : 0);
118 130