Skip to content

Commit 5a9be7c

Browse files
committed
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>
1 parent 72611ab commit 5a9be7c

7 files changed

Lines changed: 65 additions & 8 deletions

File tree

Documentation/kernel-parameters.txt

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3296,18 +3296,27 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
32963296
rcutorture.verbose= [KNL]
32973297
Enable additional printk() statements.
32983298

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+
32993305
rcupdate.rcu_expedited= [KNL]
33003306
Use expedited grace-period primitives, for
33013307
example, synchronize_rcu_expedited() instead
33023308
of synchronize_rcu(). This reduces latency,
33033309
but can increase CPU utilization, degrade
33043310
real-time latency, and degrade energy efficiency.
33053311

3306-
rcupdate.rcu_cpu_stall_suppress= [KNL]
3307-
Suppress RCU CPU stall warning messages.
3308-
3309-
rcupdate.rcu_cpu_stall_timeout= [KNL]
3310-
Set timeout for RCU CPU stall warning messages.
3312+
rcupdate.rcu_normal= [KNL]
3313+
Use only normal grace-period primitives,
3314+
for example, synchronize_rcu() instead of
3315+
synchronize_rcu_expedited(). This improves
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.
33113320

33123321
rcupdate.rcu_task_stall_timeout= [KNL]
33133322
Set timeout in jiffies for RCU task stall warning

include/linux/rcupdate.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,14 @@
4949
#include <asm/barrier.h>
5050

5151
extern int rcu_expedited; /* for sysctl */
52+
extern int rcu_normal; /* also for sysctl */
5253

5354
#ifdef CONFIG_TINY_RCU
5455
/* 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+
}
5560
static inline bool rcu_gp_is_expedited(void) /* Internal RCU use. */
5661
{
5762
return false;
@@ -65,6 +70,7 @@ static inline void rcu_unexpedite_gp(void)
6570
{
6671
}
6772
#else /* #ifdef CONFIG_TINY_RCU */
73+
bool rcu_gp_is_normal(void); /* Internal RCU use. */
6874
bool rcu_gp_is_expedited(void); /* Internal RCU use. */
6975
void rcu_expedite_gp(void);
7076
void rcu_unexpedite_gp(void);

kernel/ksysfs.c

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
#include <linux/capability.h>
2121
#include <linux/compiler.h>
2222

23-
#include <linux/rcupdate.h> /* rcu_expedited */
23+
#include <linux/rcupdate.h> /* rcu_expedited and rcu_normal */
2424

2525
#define KERNEL_ATTR_RO(_name) \
2626
static struct kobj_attribute _name##_attr = __ATTR_RO(_name)
@@ -148,7 +148,7 @@ int rcu_expedited;
148148
static ssize_t rcu_expedited_show(struct kobject *kobj,
149149
struct kobj_attribute *attr, char *buf)
150150
{
151-
return sprintf(buf, "%d\n", rcu_expedited);
151+
return sprintf(buf, "%d\n", READ_ONCE(rcu_expedited));
152152
}
153153
static ssize_t rcu_expedited_store(struct kobject *kobj,
154154
struct kobj_attribute *attr,
@@ -161,6 +161,23 @@ static ssize_t rcu_expedited_store(struct kobject *kobj,
161161
}
162162
KERNEL_ATTR_RW(rcu_expedited);
163163

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+
164181
/*
165182
* Make /sys/kernel/notes give the raw contents of our kernel .notes section.
166183
*/
@@ -203,6 +220,7 @@ static struct attribute * kernel_attrs[] = {
203220
&vmcoreinfo_attr.attr,
204221
#endif
205222
&rcu_expedited_attr.attr,
223+
&rcu_normal_attr.attr,
206224
NULL
207225
};
208226

kernel/rcu/srcu.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -489,7 +489,7 @@ static void __synchronize_srcu(struct srcu_struct *sp, int trycount)
489489
*/
490490
void synchronize_srcu(struct srcu_struct *sp)
491491
{
492-
__synchronize_srcu(sp, rcu_gp_is_expedited()
492+
__synchronize_srcu(sp, (rcu_gp_is_expedited() && !rcu_gp_is_normal())
493493
? SYNCHRONIZE_SRCU_EXP_TRYCOUNT
494494
: SYNCHRONIZE_SRCU_TRYCOUNT);
495495
}

kernel/rcu/tree.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3841,6 +3841,12 @@ void synchronize_sched_expedited(void)
38413841
if (rcu_blocking_is_gp())
38423842
return;
38433843

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+
38443850
/* Take a snapshot of the sequence number. */
38453851
s = rcu_exp_gp_seq_snap(rsp);
38463852

kernel/rcu/tree_plugin.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -746,6 +746,12 @@ void synchronize_rcu_expedited(void)
746746
struct rcu_state *rsp = rcu_state_p;
747747
unsigned long s;
748748

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+
749755
s = rcu_exp_gp_seq_snap(rsp);
750756

751757
rnp_unlock = exp_funnel_lock(rsp, s);

kernel/rcu/update.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ MODULE_ALIAS("rcupdate");
6161
#define MODULE_PARAM_PREFIX "rcupdate."
6262

6363
module_param(rcu_expedited, int, 0);
64+
module_param(rcu_normal, int, 0);
6465

6566
#if defined(CONFIG_DEBUG_LOCK_ALLOC) && defined(CONFIG_PREEMPT_COUNT)
6667
/**
@@ -113,6 +114,17 @@ EXPORT_SYMBOL(rcu_read_lock_sched_held);
113114

114115
#ifndef CONFIG_TINY_RCU
115116

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+
116128
static atomic_t rcu_expedited_nesting =
117129
ATOMIC_INIT(IS_ENABLED(CONFIG_RCU_EXPEDITE_BOOT) ? 1 : 0);
118130

0 commit comments

Comments
 (0)