Loading Documentation/RCU/stallwarn.txt +24 −9 Original line number Original line Diff line number Diff line Loading @@ -56,8 +56,20 @@ RCU_STALL_RAT_DELAY two jiffies. (This is a cpp macro, not a kernel configuration two jiffies. (This is a cpp macro, not a kernel configuration parameter.) parameter.) When a CPU detects that it is stalling, it will print a message similar rcupdate.rcu_task_stall_timeout to the following: This boot/sysfs parameter controls the RCU-tasks stall warning interval. A value of zero or less suppresses RCU-tasks stall warnings. A positive value sets the stall-warning interval in jiffies. An RCU-tasks stall warning starts wtih the line: INFO: rcu_tasks detected stalls on tasks: And continues with the output of sched_show_task() for each task stalling the current RCU-tasks grace period. For non-RCU-tasks flavors of RCU, when a CPU detects that it is stalling, it will print a message similar to the following: INFO: rcu_sched_state detected stall on CPU 5 (t=2500 jiffies) INFO: rcu_sched_state detected stall on CPU 5 (t=2500 jiffies) Loading Loading @@ -174,8 +186,12 @@ o A CPU looping with preemption disabled. This condition can o A CPU looping with bottom halves disabled. This condition can o A CPU looping with bottom halves disabled. This condition can result in RCU-sched and RCU-bh stalls. result in RCU-sched and RCU-bh stalls. o For !CONFIG_PREEMPT kernels, a CPU looping anywhere in the kernel o For !CONFIG_PREEMPT kernels, a CPU looping anywhere in the without invoking schedule(). kernel without invoking schedule(). Note that cond_resched() does not necessarily prevent RCU CPU stall warnings. Therefore, if the looping in the kernel is really expected and desirable behavior, you might need to replace some of the cond_resched() calls with calls to cond_resched_rcu_qs(). o A CPU-bound real-time task in a CONFIG_PREEMPT kernel, which might o A CPU-bound real-time task in a CONFIG_PREEMPT kernel, which might happen to preempt a low-priority task in the middle of an RCU happen to preempt a low-priority task in the middle of an RCU Loading Loading @@ -208,11 +224,10 @@ o A hardware failure. This is quite unlikely, but has occurred This resulted in a series of RCU CPU stall warnings, eventually This resulted in a series of RCU CPU stall warnings, eventually leading the realization that the CPU had failed. leading the realization that the CPU had failed. The RCU, RCU-sched, and RCU-bh implementations have CPU stall warning. The RCU, RCU-sched, RCU-bh, and RCU-tasks implementations have CPU stall SRCU does not have its own CPU stall warnings, but its calls to warning. Note that SRCU does -not- have CPU stall warnings. Please note synchronize_sched() will result in RCU-sched detecting RCU-sched-related that RCU only detects CPU stalls when there is a grace period in progress. CPU stalls. Please note that RCU only detects CPU stalls when there is No grace period, no CPU stall warnings. a grace period in progress. No grace period, no CPU stall warnings. To diagnose the cause of the stall, inspect the stack traces. To diagnose the cause of the stall, inspect the stack traces. The offending function will usually be near the top of the stack. The offending function will usually be near the top of the stack. Loading Documentation/kernel-parameters.txt +5 −0 Original line number Original line Diff line number Diff line Loading @@ -3000,6 +3000,11 @@ bytes respectively. Such letter suffixes can also be entirely omitted. rcupdate.rcu_cpu_stall_timeout= [KNL] rcupdate.rcu_cpu_stall_timeout= [KNL] Set timeout for RCU CPU stall warning messages. Set timeout for RCU CPU stall warning messages. rcupdate.rcu_task_stall_timeout= [KNL] Set timeout in jiffies for RCU task stall warning messages. Disable with a value less than or equal to zero. rdinit= [KNL] rdinit= [KNL] Format: <full_path> Format: <full_path> Run specified binary instead of /init from the ramdisk, Run specified binary instead of /init from the ramdisk, Loading fs/file.c +1 −1 Original line number Original line Diff line number Diff line Loading @@ -367,7 +367,7 @@ static struct fdtable *close_files(struct files_struct * files) struct file * file = xchg(&fdt->fd[i], NULL); struct file * file = xchg(&fdt->fd[i], NULL); if (file) { if (file) { filp_close(file, files); filp_close(file, files); cond_resched(); cond_resched_rcu_qs(); } } } } i++; i++; Loading include/linux/init_task.h +11 −1 Original line number Original line Diff line number Diff line Loading @@ -111,12 +111,21 @@ extern struct group_info init_groups; #ifdef CONFIG_PREEMPT_RCU #ifdef CONFIG_PREEMPT_RCU #define INIT_TASK_RCU_PREEMPT(tsk) \ #define INIT_TASK_RCU_PREEMPT(tsk) \ .rcu_read_lock_nesting = 0, \ .rcu_read_lock_nesting = 0, \ .rcu_read_unlock_special = 0, \ .rcu_read_unlock_special.s = 0, \ .rcu_node_entry = LIST_HEAD_INIT(tsk.rcu_node_entry), \ .rcu_node_entry = LIST_HEAD_INIT(tsk.rcu_node_entry), \ INIT_TASK_RCU_TREE_PREEMPT() INIT_TASK_RCU_TREE_PREEMPT() #else #else #define INIT_TASK_RCU_PREEMPT(tsk) #define INIT_TASK_RCU_PREEMPT(tsk) #endif #endif #ifdef CONFIG_TASKS_RCU #define INIT_TASK_RCU_TASKS(tsk) \ .rcu_tasks_holdout = false, \ .rcu_tasks_holdout_list = \ LIST_HEAD_INIT(tsk.rcu_tasks_holdout_list), \ .rcu_tasks_idle_cpu = -1, #else #define INIT_TASK_RCU_TASKS(tsk) #endif extern struct cred init_cred; extern struct cred init_cred; Loading Loading @@ -224,6 +233,7 @@ extern struct task_group root_task_group; INIT_FTRACE_GRAPH \ INIT_FTRACE_GRAPH \ INIT_TRACE_RECURSION \ INIT_TRACE_RECURSION \ INIT_TASK_RCU_PREEMPT(tsk) \ INIT_TASK_RCU_PREEMPT(tsk) \ INIT_TASK_RCU_TASKS(tsk) \ INIT_CPUSET_SEQ(tsk) \ INIT_CPUSET_SEQ(tsk) \ INIT_RT_MUTEXES(tsk) \ INIT_RT_MUTEXES(tsk) \ INIT_VTIME(tsk) \ INIT_VTIME(tsk) \ Loading include/linux/rcupdate.h +55 −2 Original line number Original line Diff line number Diff line Loading @@ -55,6 +55,7 @@ enum rcutorture_type { RCU_FLAVOR, RCU_FLAVOR, RCU_BH_FLAVOR, RCU_BH_FLAVOR, RCU_SCHED_FLAVOR, RCU_SCHED_FLAVOR, RCU_TASKS_FLAVOR, SRCU_FLAVOR, SRCU_FLAVOR, INVALID_RCU_FLAVOR INVALID_RCU_FLAVOR }; }; Loading Loading @@ -197,6 +198,28 @@ void call_rcu_sched(struct rcu_head *head, void synchronize_sched(void); void synchronize_sched(void); /** * call_rcu_tasks() - Queue an RCU for invocation task-based grace period * @head: structure to be used for queueing the RCU updates. * @func: actual callback function to be invoked after the grace period * * The callback function will be invoked some time after a full grace * period elapses, in other words after all currently executing RCU * read-side critical sections have completed. call_rcu_tasks() assumes * that the read-side critical sections end at a voluntary context * switch (not a preemption!), entry into idle, or transition to usermode * execution. As such, there are no read-side primitives analogous to * rcu_read_lock() and rcu_read_unlock() because this primitive is intended * to determine that all tasks have passed through a safe state, not so * much for data-strcuture synchronization. * * See the description of call_rcu() for more detailed information on * memory ordering guarantees. */ void call_rcu_tasks(struct rcu_head *head, void (*func)(struct rcu_head *head)); void synchronize_rcu_tasks(void); void rcu_barrier_tasks(void); #ifdef CONFIG_PREEMPT_RCU #ifdef CONFIG_PREEMPT_RCU void __rcu_read_lock(void); void __rcu_read_lock(void); Loading Loading @@ -238,8 +261,8 @@ static inline int rcu_preempt_depth(void) /* Internal to kernel */ /* Internal to kernel */ void rcu_init(void); void rcu_init(void); void rcu_sched_qs(int cpu); void rcu_sched_qs(void); void rcu_bh_qs(int cpu); void rcu_bh_qs(void); void rcu_check_callbacks(int cpu, int user); void rcu_check_callbacks(int cpu, int user); struct notifier_block; struct notifier_block; void rcu_idle_enter(void); void rcu_idle_enter(void); Loading Loading @@ -302,6 +325,36 @@ static inline void rcu_init_nohz(void) rcu_irq_exit(); \ rcu_irq_exit(); \ } while (0) } while (0) /* * Note a voluntary context switch for RCU-tasks benefit. This is a * macro rather than an inline function to avoid #include hell. */ #ifdef CONFIG_TASKS_RCU #define TASKS_RCU(x) x extern struct srcu_struct tasks_rcu_exit_srcu; #define rcu_note_voluntary_context_switch(t) \ do { \ if (ACCESS_ONCE((t)->rcu_tasks_holdout)) \ ACCESS_ONCE((t)->rcu_tasks_holdout) = false; \ } while (0) #else /* #ifdef CONFIG_TASKS_RCU */ #define TASKS_RCU(x) do { } while (0) #define rcu_note_voluntary_context_switch(t) do { } while (0) #endif /* #else #ifdef CONFIG_TASKS_RCU */ /** * cond_resched_rcu_qs - Report potential quiescent states to RCU * * This macro resembles cond_resched(), except that it is defined to * report potential quiescent states to RCU-tasks even if the cond_resched() * machinery were to be shut off, as some advocate for PREEMPT kernels. */ #define cond_resched_rcu_qs() \ do { \ rcu_note_voluntary_context_switch(current); \ cond_resched(); \ } while (0) #if defined(CONFIG_DEBUG_LOCK_ALLOC) || defined(CONFIG_RCU_TRACE) || defined(CONFIG_SMP) #if defined(CONFIG_DEBUG_LOCK_ALLOC) || defined(CONFIG_RCU_TRACE) || defined(CONFIG_SMP) bool __rcu_is_watching(void); bool __rcu_is_watching(void); #endif /* #if defined(CONFIG_DEBUG_LOCK_ALLOC) || defined(CONFIG_RCU_TRACE) || defined(CONFIG_SMP) */ #endif /* #if defined(CONFIG_DEBUG_LOCK_ALLOC) || defined(CONFIG_RCU_TRACE) || defined(CONFIG_SMP) */ Loading Loading
Documentation/RCU/stallwarn.txt +24 −9 Original line number Original line Diff line number Diff line Loading @@ -56,8 +56,20 @@ RCU_STALL_RAT_DELAY two jiffies. (This is a cpp macro, not a kernel configuration two jiffies. (This is a cpp macro, not a kernel configuration parameter.) parameter.) When a CPU detects that it is stalling, it will print a message similar rcupdate.rcu_task_stall_timeout to the following: This boot/sysfs parameter controls the RCU-tasks stall warning interval. A value of zero or less suppresses RCU-tasks stall warnings. A positive value sets the stall-warning interval in jiffies. An RCU-tasks stall warning starts wtih the line: INFO: rcu_tasks detected stalls on tasks: And continues with the output of sched_show_task() for each task stalling the current RCU-tasks grace period. For non-RCU-tasks flavors of RCU, when a CPU detects that it is stalling, it will print a message similar to the following: INFO: rcu_sched_state detected stall on CPU 5 (t=2500 jiffies) INFO: rcu_sched_state detected stall on CPU 5 (t=2500 jiffies) Loading Loading @@ -174,8 +186,12 @@ o A CPU looping with preemption disabled. This condition can o A CPU looping with bottom halves disabled. This condition can o A CPU looping with bottom halves disabled. This condition can result in RCU-sched and RCU-bh stalls. result in RCU-sched and RCU-bh stalls. o For !CONFIG_PREEMPT kernels, a CPU looping anywhere in the kernel o For !CONFIG_PREEMPT kernels, a CPU looping anywhere in the without invoking schedule(). kernel without invoking schedule(). Note that cond_resched() does not necessarily prevent RCU CPU stall warnings. Therefore, if the looping in the kernel is really expected and desirable behavior, you might need to replace some of the cond_resched() calls with calls to cond_resched_rcu_qs(). o A CPU-bound real-time task in a CONFIG_PREEMPT kernel, which might o A CPU-bound real-time task in a CONFIG_PREEMPT kernel, which might happen to preempt a low-priority task in the middle of an RCU happen to preempt a low-priority task in the middle of an RCU Loading Loading @@ -208,11 +224,10 @@ o A hardware failure. This is quite unlikely, but has occurred This resulted in a series of RCU CPU stall warnings, eventually This resulted in a series of RCU CPU stall warnings, eventually leading the realization that the CPU had failed. leading the realization that the CPU had failed. The RCU, RCU-sched, and RCU-bh implementations have CPU stall warning. The RCU, RCU-sched, RCU-bh, and RCU-tasks implementations have CPU stall SRCU does not have its own CPU stall warnings, but its calls to warning. Note that SRCU does -not- have CPU stall warnings. Please note synchronize_sched() will result in RCU-sched detecting RCU-sched-related that RCU only detects CPU stalls when there is a grace period in progress. CPU stalls. Please note that RCU only detects CPU stalls when there is No grace period, no CPU stall warnings. a grace period in progress. No grace period, no CPU stall warnings. To diagnose the cause of the stall, inspect the stack traces. To diagnose the cause of the stall, inspect the stack traces. The offending function will usually be near the top of the stack. The offending function will usually be near the top of the stack. Loading
Documentation/kernel-parameters.txt +5 −0 Original line number Original line Diff line number Diff line Loading @@ -3000,6 +3000,11 @@ bytes respectively. Such letter suffixes can also be entirely omitted. rcupdate.rcu_cpu_stall_timeout= [KNL] rcupdate.rcu_cpu_stall_timeout= [KNL] Set timeout for RCU CPU stall warning messages. Set timeout for RCU CPU stall warning messages. rcupdate.rcu_task_stall_timeout= [KNL] Set timeout in jiffies for RCU task stall warning messages. Disable with a value less than or equal to zero. rdinit= [KNL] rdinit= [KNL] Format: <full_path> Format: <full_path> Run specified binary instead of /init from the ramdisk, Run specified binary instead of /init from the ramdisk, Loading
fs/file.c +1 −1 Original line number Original line Diff line number Diff line Loading @@ -367,7 +367,7 @@ static struct fdtable *close_files(struct files_struct * files) struct file * file = xchg(&fdt->fd[i], NULL); struct file * file = xchg(&fdt->fd[i], NULL); if (file) { if (file) { filp_close(file, files); filp_close(file, files); cond_resched(); cond_resched_rcu_qs(); } } } } i++; i++; Loading
include/linux/init_task.h +11 −1 Original line number Original line Diff line number Diff line Loading @@ -111,12 +111,21 @@ extern struct group_info init_groups; #ifdef CONFIG_PREEMPT_RCU #ifdef CONFIG_PREEMPT_RCU #define INIT_TASK_RCU_PREEMPT(tsk) \ #define INIT_TASK_RCU_PREEMPT(tsk) \ .rcu_read_lock_nesting = 0, \ .rcu_read_lock_nesting = 0, \ .rcu_read_unlock_special = 0, \ .rcu_read_unlock_special.s = 0, \ .rcu_node_entry = LIST_HEAD_INIT(tsk.rcu_node_entry), \ .rcu_node_entry = LIST_HEAD_INIT(tsk.rcu_node_entry), \ INIT_TASK_RCU_TREE_PREEMPT() INIT_TASK_RCU_TREE_PREEMPT() #else #else #define INIT_TASK_RCU_PREEMPT(tsk) #define INIT_TASK_RCU_PREEMPT(tsk) #endif #endif #ifdef CONFIG_TASKS_RCU #define INIT_TASK_RCU_TASKS(tsk) \ .rcu_tasks_holdout = false, \ .rcu_tasks_holdout_list = \ LIST_HEAD_INIT(tsk.rcu_tasks_holdout_list), \ .rcu_tasks_idle_cpu = -1, #else #define INIT_TASK_RCU_TASKS(tsk) #endif extern struct cred init_cred; extern struct cred init_cred; Loading Loading @@ -224,6 +233,7 @@ extern struct task_group root_task_group; INIT_FTRACE_GRAPH \ INIT_FTRACE_GRAPH \ INIT_TRACE_RECURSION \ INIT_TRACE_RECURSION \ INIT_TASK_RCU_PREEMPT(tsk) \ INIT_TASK_RCU_PREEMPT(tsk) \ INIT_TASK_RCU_TASKS(tsk) \ INIT_CPUSET_SEQ(tsk) \ INIT_CPUSET_SEQ(tsk) \ INIT_RT_MUTEXES(tsk) \ INIT_RT_MUTEXES(tsk) \ INIT_VTIME(tsk) \ INIT_VTIME(tsk) \ Loading
include/linux/rcupdate.h +55 −2 Original line number Original line Diff line number Diff line Loading @@ -55,6 +55,7 @@ enum rcutorture_type { RCU_FLAVOR, RCU_FLAVOR, RCU_BH_FLAVOR, RCU_BH_FLAVOR, RCU_SCHED_FLAVOR, RCU_SCHED_FLAVOR, RCU_TASKS_FLAVOR, SRCU_FLAVOR, SRCU_FLAVOR, INVALID_RCU_FLAVOR INVALID_RCU_FLAVOR }; }; Loading Loading @@ -197,6 +198,28 @@ void call_rcu_sched(struct rcu_head *head, void synchronize_sched(void); void synchronize_sched(void); /** * call_rcu_tasks() - Queue an RCU for invocation task-based grace period * @head: structure to be used for queueing the RCU updates. * @func: actual callback function to be invoked after the grace period * * The callback function will be invoked some time after a full grace * period elapses, in other words after all currently executing RCU * read-side critical sections have completed. call_rcu_tasks() assumes * that the read-side critical sections end at a voluntary context * switch (not a preemption!), entry into idle, or transition to usermode * execution. As such, there are no read-side primitives analogous to * rcu_read_lock() and rcu_read_unlock() because this primitive is intended * to determine that all tasks have passed through a safe state, not so * much for data-strcuture synchronization. * * See the description of call_rcu() for more detailed information on * memory ordering guarantees. */ void call_rcu_tasks(struct rcu_head *head, void (*func)(struct rcu_head *head)); void synchronize_rcu_tasks(void); void rcu_barrier_tasks(void); #ifdef CONFIG_PREEMPT_RCU #ifdef CONFIG_PREEMPT_RCU void __rcu_read_lock(void); void __rcu_read_lock(void); Loading Loading @@ -238,8 +261,8 @@ static inline int rcu_preempt_depth(void) /* Internal to kernel */ /* Internal to kernel */ void rcu_init(void); void rcu_init(void); void rcu_sched_qs(int cpu); void rcu_sched_qs(void); void rcu_bh_qs(int cpu); void rcu_bh_qs(void); void rcu_check_callbacks(int cpu, int user); void rcu_check_callbacks(int cpu, int user); struct notifier_block; struct notifier_block; void rcu_idle_enter(void); void rcu_idle_enter(void); Loading Loading @@ -302,6 +325,36 @@ static inline void rcu_init_nohz(void) rcu_irq_exit(); \ rcu_irq_exit(); \ } while (0) } while (0) /* * Note a voluntary context switch for RCU-tasks benefit. This is a * macro rather than an inline function to avoid #include hell. */ #ifdef CONFIG_TASKS_RCU #define TASKS_RCU(x) x extern struct srcu_struct tasks_rcu_exit_srcu; #define rcu_note_voluntary_context_switch(t) \ do { \ if (ACCESS_ONCE((t)->rcu_tasks_holdout)) \ ACCESS_ONCE((t)->rcu_tasks_holdout) = false; \ } while (0) #else /* #ifdef CONFIG_TASKS_RCU */ #define TASKS_RCU(x) do { } while (0) #define rcu_note_voluntary_context_switch(t) do { } while (0) #endif /* #else #ifdef CONFIG_TASKS_RCU */ /** * cond_resched_rcu_qs - Report potential quiescent states to RCU * * This macro resembles cond_resched(), except that it is defined to * report potential quiescent states to RCU-tasks even if the cond_resched() * machinery were to be shut off, as some advocate for PREEMPT kernels. */ #define cond_resched_rcu_qs() \ do { \ rcu_note_voluntary_context_switch(current); \ cond_resched(); \ } while (0) #if defined(CONFIG_DEBUG_LOCK_ALLOC) || defined(CONFIG_RCU_TRACE) || defined(CONFIG_SMP) #if defined(CONFIG_DEBUG_LOCK_ALLOC) || defined(CONFIG_RCU_TRACE) || defined(CONFIG_SMP) bool __rcu_is_watching(void); bool __rcu_is_watching(void); #endif /* #if defined(CONFIG_DEBUG_LOCK_ALLOC) || defined(CONFIG_RCU_TRACE) || defined(CONFIG_SMP) */ #endif /* #if defined(CONFIG_DEBUG_LOCK_ALLOC) || defined(CONFIG_RCU_TRACE) || defined(CONFIG_SMP) */ Loading