diff options
-rw-r--r-- | Documentation/kernel-parameters.txt | 19 | ||||
-rw-r--r-- | include/linux/rcupdate.h | 6 | ||||
-rw-r--r-- | kernel/ksysfs.c | 22 | ||||
-rw-r--r-- | kernel/rcu/srcu.c | 2 | ||||
-rw-r--r-- | kernel/rcu/tree.c | 6 | ||||
-rw-r--r-- | kernel/rcu/tree_plugin.h | 6 | ||||
-rw-r--r-- | kernel/rcu/update.c | 12 |
7 files changed, 65 insertions, 8 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 742f69d18fc8..7673943d3085 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
@@ -3296,6 +3296,12 @@ bytes respectively. Such letter suffixes can also be entirely omitted. | |||
3296 | rcutorture.verbose= [KNL] | 3296 | rcutorture.verbose= [KNL] |
3297 | Enable additional printk() statements. | 3297 | Enable additional printk() statements. |
3298 | 3298 | ||
3299 | rcupdate.rcu_cpu_stall_suppress= [KNL] | ||
3300 | Suppress RCU CPU stall warning messages. | ||
3301 | |||
3302 | rcupdate.rcu_cpu_stall_timeout= [KNL] | ||
3303 | Set timeout for RCU CPU stall warning messages. | ||
3304 | |||
3299 | rcupdate.rcu_expedited= [KNL] | 3305 | rcupdate.rcu_expedited= [KNL] |
3300 | Use expedited grace-period primitives, for | 3306 | Use expedited grace-period primitives, for |
3301 | example, synchronize_rcu_expedited() instead | 3307 | example, synchronize_rcu_expedited() instead |
@@ -3303,11 +3309,14 @@ bytes respectively. Such letter suffixes can also be entirely omitted. | |||
3303 | but can increase CPU utilization, degrade | 3309 | but can increase CPU utilization, degrade |
3304 | real-time latency, and degrade energy efficiency. | 3310 | real-time latency, and degrade energy efficiency. |
3305 | 3311 | ||
3306 | rcupdate.rcu_cpu_stall_suppress= [KNL] | 3312 | rcupdate.rcu_normal= [KNL] |
3307 | Suppress RCU CPU stall warning messages. | 3313 | Use only normal grace-period primitives, |
3308 | 3314 | for example, synchronize_rcu() instead of | |
3309 | rcupdate.rcu_cpu_stall_timeout= [KNL] | 3315 | synchronize_rcu_expedited(). This improves |
3310 | Set timeout for RCU CPU stall warning messages. | 3316 | real-time latency, CPU utilization, and energy |
3317 | efficiency, but can expose users to increased | ||
3318 | grace-period latency. This parameter overrides | ||
3319 | rcupdate.rcu_expedited. | ||
3311 | 3320 | ||
3312 | rcupdate.rcu_task_stall_timeout= [KNL] | 3321 | rcupdate.rcu_task_stall_timeout= [KNL] |
3313 | Set timeout in jiffies for RCU task stall warning | 3322 | Set timeout in jiffies for RCU task stall warning |
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h index a0189ba67fde..98d9f30c02d4 100644 --- a/include/linux/rcupdate.h +++ b/include/linux/rcupdate.h | |||
@@ -49,9 +49,14 @@ | |||
49 | #include <asm/barrier.h> | 49 | #include <asm/barrier.h> |
50 | 50 | ||
51 | extern int rcu_expedited; /* for sysctl */ | 51 | extern int rcu_expedited; /* for sysctl */ |
52 | extern int rcu_normal; /* also for sysctl */ | ||
52 | 53 | ||
53 | #ifdef CONFIG_TINY_RCU | 54 | #ifdef CONFIG_TINY_RCU |
54 | /* Tiny RCU doesn't expedite, as its purpose in life is instead to be tiny. */ | 55 | /* Tiny RCU doesn't expedite, as its purpose in life is instead to be tiny. */ |
56 | static inline bool rcu_gp_is_normal(void) /* Internal RCU use. */ | ||
57 | { | ||
58 | return true; | ||
59 | } | ||
55 | static inline bool rcu_gp_is_expedited(void) /* Internal RCU use. */ | 60 | static inline bool rcu_gp_is_expedited(void) /* Internal RCU use. */ |
56 | { | 61 | { |
57 | return false; | 62 | return false; |
@@ -65,6 +70,7 @@ static inline void rcu_unexpedite_gp(void) | |||
65 | { | 70 | { |
66 | } | 71 | } |
67 | #else /* #ifdef CONFIG_TINY_RCU */ | 72 | #else /* #ifdef CONFIG_TINY_RCU */ |
73 | bool rcu_gp_is_normal(void); /* Internal RCU use. */ | ||
68 | bool rcu_gp_is_expedited(void); /* Internal RCU use. */ | 74 | bool rcu_gp_is_expedited(void); /* Internal RCU use. */ |
69 | void rcu_expedite_gp(void); | 75 | void rcu_expedite_gp(void); |
70 | void rcu_unexpedite_gp(void); | 76 | void rcu_unexpedite_gp(void); |
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) \ |
26 | static struct kobj_attribute _name##_attr = __ATTR_RO(_name) | 26 | static struct kobj_attribute _name##_attr = __ATTR_RO(_name) |
@@ -148,7 +148,7 @@ int rcu_expedited; | |||
148 | static ssize_t rcu_expedited_show(struct kobject *kobj, | 148 | static 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 | } |
153 | static ssize_t rcu_expedited_store(struct kobject *kobj, | 153 | static 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 | } |
162 | KERNEL_ATTR_RW(rcu_expedited); | 162 | KERNEL_ATTR_RW(rcu_expedited); |
163 | 163 | ||
164 | int rcu_normal; | ||
165 | static 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 | } | ||
170 | static 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 | } | ||
179 | KERNEL_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 | */ |
490 | void synchronize_srcu(struct srcu_struct *sp) | 490 | void 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 | ||
63 | module_param(rcu_expedited, int, 0); | 63 | module_param(rcu_expedited, int, 0); |
64 | module_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 | */ | ||
123 | bool rcu_gp_is_normal(void) | ||
124 | { | ||
125 | return READ_ONCE(rcu_normal); | ||
126 | } | ||
127 | |||
116 | static atomic_t rcu_expedited_nesting = | 128 | static 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 | ||