mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-01 02:36:02 +00:00
c342b42fa4
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 <leitao@debian.org> Signed-off-by: Paul E. McKenney <paulmck@kernel.org> Signed-off-by: Uladzislau Rezki (Sony) <urezki@gmail.com>
69 lines
2.3 KiB
C
69 lines
2.3 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
#ifndef _LINUX_SCHED_RCUPDATE_WAIT_H
|
|
#define _LINUX_SCHED_RCUPDATE_WAIT_H
|
|
|
|
/*
|
|
* RCU synchronization types and methods:
|
|
*/
|
|
|
|
#include <linux/rcupdate.h>
|
|
#include <linux/completion.h>
|
|
#include <linux/sched.h>
|
|
|
|
/*
|
|
* Structure allowing asynchronous waiting on RCU.
|
|
*/
|
|
struct rcu_synchronize {
|
|
struct rcu_head head;
|
|
struct completion completion;
|
|
};
|
|
void wakeme_after_rcu(struct rcu_head *head);
|
|
|
|
void __wait_rcu_gp(bool checktiny, unsigned int state, int n, call_rcu_func_t *crcu_array,
|
|
struct rcu_synchronize *rs_array);
|
|
|
|
#define _wait_rcu_gp(checktiny, state, ...) \
|
|
do { \
|
|
call_rcu_func_t __crcu_array[] = { __VA_ARGS__ }; \
|
|
struct rcu_synchronize __rs_array[ARRAY_SIZE(__crcu_array)]; \
|
|
__wait_rcu_gp(checktiny, state, ARRAY_SIZE(__crcu_array), __crcu_array, __rs_array); \
|
|
} while (0)
|
|
|
|
#define wait_rcu_gp(...) _wait_rcu_gp(false, TASK_UNINTERRUPTIBLE, __VA_ARGS__)
|
|
#define wait_rcu_gp_state(state, ...) _wait_rcu_gp(false, state, __VA_ARGS__)
|
|
|
|
/**
|
|
* synchronize_rcu_mult - Wait concurrently for multiple grace periods
|
|
* @...: List of call_rcu() functions for different grace periods to wait on
|
|
*
|
|
* This macro waits concurrently for multiple types of RCU grace periods.
|
|
* For example, synchronize_rcu_mult(call_rcu, call_rcu_tasks) would wait
|
|
* on concurrent RCU and RCU-tasks grace periods. Waiting on a given SRCU
|
|
* domain requires you to write a wrapper function for that SRCU domain's
|
|
* call_srcu() function, with this wrapper supplying the pointer to the
|
|
* corresponding srcu_struct.
|
|
*
|
|
* Note that call_rcu_hurry() should be used instead of call_rcu()
|
|
* because in kernels built with CONFIG_RCU_LAZY=y the delay between the
|
|
* invocation of call_rcu() and that of the corresponding RCU callback
|
|
* can be multiple seconds.
|
|
*
|
|
* The first argument tells Tiny RCU's _wait_rcu_gp() not to
|
|
* bother waiting for RCU. The reason for this is because anywhere
|
|
* synchronize_rcu_mult() can be called is automatically already a full
|
|
* grace period.
|
|
*/
|
|
#define synchronize_rcu_mult(...) \
|
|
_wait_rcu_gp(IS_ENABLED(CONFIG_TINY_RCU), TASK_UNINTERRUPTIBLE, __VA_ARGS__)
|
|
|
|
static inline void cond_resched_rcu(void)
|
|
{
|
|
#if defined(CONFIG_DEBUG_ATOMIC_SLEEP) || !defined(CONFIG_PREEMPT_RCU)
|
|
rcu_read_unlock();
|
|
cond_resched();
|
|
rcu_read_lock();
|
|
#endif
|
|
}
|
|
|
|
#endif /* _LINUX_SCHED_RCUPDATE_WAIT_H */
|