Skip to content

Commit 6efdda8

Browse files
joelagnelpaulmckrcu
authored andcommitted
rcu: Track laziness during boot and suspend
Boot and suspend/resume should not be slowed down in kernels built with CONFIG_RCU_LAZY=y. In particular, suspend can sometimes fail in such kernels. This commit therefore adds rcu_async_hurry(), rcu_async_relax(), and rcu_async_should_hurry() functions that track whether or not either a boot or a suspend/resume operation is in progress. This will enable a later commit to refrain from laziness during those times. Export rcu_async_should_hurry(), rcu_async_hurry(), and rcu_async_relax() for later use by rcutorture. [ paulmck: Apply feedback from Steve Rostedt. ] Fixes: 3cb278e ("rcu: Make call_rcu() lazy to save power") Signed-off-by: Joel Fernandes (Google) <[email protected]> Signed-off-by: Paul E. McKenney <[email protected]>
1 parent ccfe1fe commit 6efdda8

File tree

3 files changed

+47
-1
lines changed

3 files changed

+47
-1
lines changed

kernel/rcu/rcu.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,14 +448,20 @@ do { \
448448
/* Tiny RCU doesn't expedite, as its purpose in life is instead to be tiny. */
449449
static inline bool rcu_gp_is_normal(void) { return true; }
450450
static inline bool rcu_gp_is_expedited(void) { return false; }
451+
static inline bool rcu_async_should_hurry(void) { return false; }
451452
static inline void rcu_expedite_gp(void) { }
452453
static inline void rcu_unexpedite_gp(void) { }
454+
static inline void rcu_async_hurry(void) { }
455+
static inline void rcu_async_relax(void) { }
453456
static inline void rcu_request_urgent_qs_task(struct task_struct *t) { }
454457
#else /* #ifdef CONFIG_TINY_RCU */
455458
bool rcu_gp_is_normal(void); /* Internal RCU use. */
456459
bool rcu_gp_is_expedited(void); /* Internal RCU use. */
460+
bool rcu_async_should_hurry(void); /* Internal RCU use. */
457461
void rcu_expedite_gp(void);
458462
void rcu_unexpedite_gp(void);
463+
void rcu_async_hurry(void);
464+
void rcu_async_relax(void);
459465
void rcupdate_announce_bootup_oddness(void);
460466
#ifdef CONFIG_TASKS_RCU_GENERIC
461467
void show_rcu_tasks_gp_kthreads(void);

kernel/rcu/tree.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4414,11 +4414,13 @@ static int rcu_pm_notify(struct notifier_block *self,
44144414
switch (action) {
44154415
case PM_HIBERNATION_PREPARE:
44164416
case PM_SUSPEND_PREPARE:
4417+
rcu_async_hurry();
44174418
rcu_expedite_gp();
44184419
break;
44194420
case PM_POST_HIBERNATION:
44204421
case PM_POST_SUSPEND:
44214422
rcu_unexpedite_gp();
4423+
rcu_async_relax();
44224424
break;
44234425
default:
44244426
break;

kernel/rcu/update.c

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,8 +144,45 @@ bool rcu_gp_is_normal(void)
144144
}
145145
EXPORT_SYMBOL_GPL(rcu_gp_is_normal);
146146

147-
static atomic_t rcu_expedited_nesting = ATOMIC_INIT(1);
147+
static atomic_t rcu_async_hurry_nesting = ATOMIC_INIT(1);
148+
/*
149+
* Should call_rcu() callbacks be processed with urgency or are
150+
* they OK being executed with arbitrary delays?
151+
*/
152+
bool rcu_async_should_hurry(void)
153+
{
154+
return !IS_ENABLED(CONFIG_RCU_LAZY) ||
155+
atomic_read(&rcu_async_hurry_nesting);
156+
}
157+
EXPORT_SYMBOL_GPL(rcu_async_should_hurry);
158+
159+
/**
160+
* rcu_async_hurry - Make future async RCU callbacks not lazy.
161+
*
162+
* After a call to this function, future calls to call_rcu()
163+
* will be processed in a timely fashion.
164+
*/
165+
void rcu_async_hurry(void)
166+
{
167+
if (IS_ENABLED(CONFIG_RCU_LAZY))
168+
atomic_inc(&rcu_async_hurry_nesting);
169+
}
170+
EXPORT_SYMBOL_GPL(rcu_async_hurry);
148171

172+
/**
173+
* rcu_async_relax - Make future async RCU callbacks lazy.
174+
*
175+
* After a call to this function, future calls to call_rcu()
176+
* will be processed in a lazy fashion.
177+
*/
178+
void rcu_async_relax(void)
179+
{
180+
if (IS_ENABLED(CONFIG_RCU_LAZY))
181+
atomic_dec(&rcu_async_hurry_nesting);
182+
}
183+
EXPORT_SYMBOL_GPL(rcu_async_relax);
184+
185+
static atomic_t rcu_expedited_nesting = ATOMIC_INIT(1);
149186
/*
150187
* Should normal grace-period primitives be expedited? Intended for
151188
* use within RCU. Note that this function takes the rcu_expedited
@@ -195,6 +232,7 @@ static bool rcu_boot_ended __read_mostly;
195232
void rcu_end_inkernel_boot(void)
196233
{
197234
rcu_unexpedite_gp();
235+
rcu_async_relax();
198236
if (rcu_normal_after_boot)
199237
WRITE_ONCE(rcu_normal, 1);
200238
rcu_boot_ended = true;

0 commit comments

Comments
 (0)