aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/rcutree.c10
-rw-r--r--kernel/rcutree.h1
-rw-r--r--kernel/rcutree_plugin.h18
3 files changed, 29 insertions, 0 deletions
diff --git a/kernel/rcutree.c b/kernel/rcutree.c
index 5b8ad827fd86..f5ab50235cba 100644
--- a/kernel/rcutree.c
+++ b/kernel/rcutree.c
@@ -794,6 +794,16 @@ static int rcu_implicit_dynticks_qs(struct rcu_data *rdp)
794 rdp->offline_fqs++; 794 rdp->offline_fqs++;
795 return 1; 795 return 1;
796 } 796 }
797
798 /*
799 * There is a possibility that a CPU in adaptive-ticks state
800 * might run in the kernel with the scheduling-clock tick disabled
801 * for an extended time period. Invoke rcu_kick_nohz_cpu() to
802 * force the CPU to restart the scheduling-clock tick in this
803 * CPU is in this state.
804 */
805 rcu_kick_nohz_cpu(rdp->cpu);
806
797 return 0; 807 return 0;
798} 808}
799 809
diff --git a/kernel/rcutree.h b/kernel/rcutree.h
index c896b5045d9d..f993c0ac47db 100644
--- a/kernel/rcutree.h
+++ b/kernel/rcutree.h
@@ -539,6 +539,7 @@ static void rcu_boot_init_nocb_percpu_data(struct rcu_data *rdp);
539static void rcu_spawn_nocb_kthreads(struct rcu_state *rsp); 539static void rcu_spawn_nocb_kthreads(struct rcu_state *rsp);
540static void init_nocb_callback_list(struct rcu_data *rdp); 540static void init_nocb_callback_list(struct rcu_data *rdp);
541static void __init rcu_init_nocb(void); 541static void __init rcu_init_nocb(void);
542static void rcu_kick_nohz_cpu(int cpu);
542 543
543#endif /* #ifndef RCU_TREE_NONCORE */ 544#endif /* #ifndef RCU_TREE_NONCORE */
544 545
diff --git a/kernel/rcutree_plugin.h b/kernel/rcutree_plugin.h
index c1cc7e17ff9d..a5745e9b5d5a 100644
--- a/kernel/rcutree_plugin.h
+++ b/kernel/rcutree_plugin.h
@@ -28,6 +28,7 @@
28#include <linux/gfp.h> 28#include <linux/gfp.h>
29#include <linux/oom.h> 29#include <linux/oom.h>
30#include <linux/smpboot.h> 30#include <linux/smpboot.h>
31#include <linux/tick.h>
31 32
32#define RCU_KTHREAD_PRIO 1 33#define RCU_KTHREAD_PRIO 1
33 34
@@ -2502,3 +2503,20 @@ static void __init rcu_init_nocb(void)
2502} 2503}
2503 2504
2504#endif /* #else #ifdef CONFIG_RCU_NOCB_CPU */ 2505#endif /* #else #ifdef CONFIG_RCU_NOCB_CPU */
2506
2507/*
2508 * An adaptive-ticks CPU can potentially execute in kernel mode for an
2509 * arbitrarily long period of time with the scheduling-clock tick turned
2510 * off. RCU will be paying attention to this CPU because it is in the
2511 * kernel, but the CPU cannot be guaranteed to be executing the RCU state
2512 * machine because the scheduling-clock tick has been disabled. Therefore,
2513 * if an adaptive-ticks CPU is failing to respond to the current grace
2514 * period and has not be idle from an RCU perspective, kick it.
2515 */
2516static void rcu_kick_nohz_cpu(int cpu)
2517{
2518#ifdef CONFIG_NO_HZ_FULL
2519 if (tick_nohz_full_cpu(cpu))
2520 smp_send_reschedule(cpu);
2521#endif /* #ifdef CONFIG_NO_HZ_FULL */
2522}