Skip to content

Commit c342b42

Browse files
paulmckrcuurezki
authored andcommitted
rcu-tasks: Make Tasks RCU wait idly for grace-period delays
Currently, all waits for grace periods sleep at TASK_UNINTERRUPTIBLE, regardless of RCU flavor. This has worked well, but there have been cases where a longer-than-average Tasks RCU grace period has triggered softlockup splats, many of them, before the Tasks RCU CPU stall warning appears. These softlockup splats unnecessarily consume console bandwidth and complicate diagnosis of the underlying problem. Plus a long but not pathologically long Tasks RCU grace period might trigger a few softlockup splats before completing normally, which generates noise for no good reason. This commit therefore causes Tasks RCU grace periods to sleep at TASK_IDLE priority. If there really is a persistent problem, the eventual Tasks RCU CPU stall warning will flag it, and without the extra noise. Reported-by: Breno Leitao <[email protected]> Signed-off-by: Paul E. McKenney <[email protected]> Signed-off-by: Uladzislau Rezki (Sony) <[email protected]>
1 parent 39cd87c commit c342b42

File tree

3 files changed

+16
-12
lines changed

3 files changed

+16
-12
lines changed

include/linux/rcupdate_wait.h

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,18 @@ struct rcu_synchronize {
1919
};
2020
void wakeme_after_rcu(struct rcu_head *head);
2121

22-
void __wait_rcu_gp(bool checktiny, int n, call_rcu_func_t *crcu_array,
22+
void __wait_rcu_gp(bool checktiny, unsigned int state, int n, call_rcu_func_t *crcu_array,
2323
struct rcu_synchronize *rs_array);
2424

25-
#define _wait_rcu_gp(checktiny, ...) \
26-
do { \
27-
call_rcu_func_t __crcu_array[] = { __VA_ARGS__ }; \
28-
struct rcu_synchronize __rs_array[ARRAY_SIZE(__crcu_array)]; \
29-
__wait_rcu_gp(checktiny, ARRAY_SIZE(__crcu_array), \
30-
__crcu_array, __rs_array); \
25+
#define _wait_rcu_gp(checktiny, state, ...) \
26+
do { \
27+
call_rcu_func_t __crcu_array[] = { __VA_ARGS__ }; \
28+
struct rcu_synchronize __rs_array[ARRAY_SIZE(__crcu_array)]; \
29+
__wait_rcu_gp(checktiny, state, ARRAY_SIZE(__crcu_array), __crcu_array, __rs_array); \
3130
} while (0)
3231

33-
#define wait_rcu_gp(...) _wait_rcu_gp(false, __VA_ARGS__)
32+
#define wait_rcu_gp(...) _wait_rcu_gp(false, TASK_UNINTERRUPTIBLE, __VA_ARGS__)
33+
#define wait_rcu_gp_state(state, ...) _wait_rcu_gp(false, state, __VA_ARGS__)
3434

3535
/**
3636
* synchronize_rcu_mult - Wait concurrently for multiple grace periods
@@ -54,7 +54,7 @@ do { \
5454
* grace period.
5555
*/
5656
#define synchronize_rcu_mult(...) \
57-
_wait_rcu_gp(IS_ENABLED(CONFIG_TINY_RCU), __VA_ARGS__)
57+
_wait_rcu_gp(IS_ENABLED(CONFIG_TINY_RCU), TASK_UNINTERRUPTIBLE, __VA_ARGS__)
5858

5959
static inline void cond_resched_rcu(void)
6060
{

kernel/rcu/tasks.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ struct rcu_tasks_percpu {
7474
* @holdouts_func: This flavor's holdout-list scan function (optional).
7575
* @postgp_func: This flavor's post-grace-period function (optional).
7676
* @call_func: This flavor's call_rcu()-equivalent function.
77+
* @wait_state: Task state for synchronous grace-period waits (default TASK_UNINTERRUPTIBLE).
7778
* @rtpcpu: This flavor's rcu_tasks_percpu structure.
7879
* @percpu_enqueue_shift: Shift down CPU ID this much when enqueuing callbacks.
7980
* @percpu_enqueue_lim: Number of per-CPU callback queues in use for enqueuing.
@@ -107,6 +108,7 @@ struct rcu_tasks {
107108
holdouts_func_t holdouts_func;
108109
postgp_func_t postgp_func;
109110
call_rcu_func_t call_func;
111+
unsigned int wait_state;
110112
struct rcu_tasks_percpu __percpu *rtpcpu;
111113
int percpu_enqueue_shift;
112114
int percpu_enqueue_lim;
@@ -134,6 +136,7 @@ static struct rcu_tasks rt_name = \
134136
.tasks_gp_mutex = __MUTEX_INITIALIZER(rt_name.tasks_gp_mutex), \
135137
.gp_func = gp, \
136138
.call_func = call, \
139+
.wait_state = TASK_UNINTERRUPTIBLE, \
137140
.rtpcpu = &rt_name ## __percpu, \
138141
.lazy_jiffies = DIV_ROUND_UP(HZ, 4), \
139142
.name = n, \
@@ -638,7 +641,7 @@ static void synchronize_rcu_tasks_generic(struct rcu_tasks *rtp)
638641

639642
// If the grace-period kthread is running, use it.
640643
if (READ_ONCE(rtp->kthread_ptr)) {
641-
wait_rcu_gp(rtp->call_func);
644+
wait_rcu_gp_state(rtp->wait_state, rtp->call_func);
642645
return;
643646
}
644647
rcu_tasks_one_gp(rtp, true);
@@ -1160,6 +1163,7 @@ static int __init rcu_spawn_tasks_kthread(void)
11601163
rcu_tasks.postscan_func = rcu_tasks_postscan;
11611164
rcu_tasks.holdouts_func = check_all_holdout_tasks;
11621165
rcu_tasks.postgp_func = rcu_tasks_postgp;
1166+
rcu_tasks.wait_state = TASK_IDLE;
11631167
rcu_spawn_tasks_kthread_generic(&rcu_tasks);
11641168
return 0;
11651169
}

kernel/rcu/update.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,7 @@ void wakeme_after_rcu(struct rcu_head *head)
408408
}
409409
EXPORT_SYMBOL_GPL(wakeme_after_rcu);
410410

411-
void __wait_rcu_gp(bool checktiny, int n, call_rcu_func_t *crcu_array,
411+
void __wait_rcu_gp(bool checktiny, unsigned int state, int n, call_rcu_func_t *crcu_array,
412412
struct rcu_synchronize *rs_array)
413413
{
414414
int i;
@@ -440,7 +440,7 @@ void __wait_rcu_gp(bool checktiny, int n, call_rcu_func_t *crcu_array,
440440
if (crcu_array[j] == crcu_array[i])
441441
break;
442442
if (j == i) {
443-
wait_for_completion(&rs_array[i].completion);
443+
wait_for_completion_state(&rs_array[i].completion, state);
444444
destroy_rcu_head_on_stack(&rs_array[i].head);
445445
}
446446
}

0 commit comments

Comments
 (0)