diff options
-rw-r--r-- | kernel/rcutree.c | 10 | ||||
-rw-r--r-- | kernel/rcutree.h | 1 | ||||
-rw-r--r-- | kernel/rcutree_plugin.h | 18 |
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); | |||
539 | static void rcu_spawn_nocb_kthreads(struct rcu_state *rsp); | 539 | static void rcu_spawn_nocb_kthreads(struct rcu_state *rsp); |
540 | static void init_nocb_callback_list(struct rcu_data *rdp); | 540 | static void init_nocb_callback_list(struct rcu_data *rdp); |
541 | static void __init rcu_init_nocb(void); | 541 | static void __init rcu_init_nocb(void); |
542 | static 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 | */ | ||
2516 | static 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 | } | ||