aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/sched/core.c5
-rw-r--r--kernel/sched/fair.c48
-rw-r--r--kernel/sched/sched.h11
3 files changed, 40 insertions, 24 deletions
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 07f1e9935f21..7f1da77b83f3 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -575,7 +575,8 @@ void wake_up_idle_cpu(int cpu)
575 575
576static inline bool got_nohz_idle_kick(void) 576static inline bool got_nohz_idle_kick(void)
577{ 577{
578 return idle_cpu(smp_processor_id()) && this_rq()->nohz_balance_kick; 578 int cpu = smp_processor_id();
579 return idle_cpu(cpu) && test_bit(NOHZ_BALANCE_KICK, nohz_flags(cpu));
579} 580}
580 581
581#else /* CONFIG_NO_HZ */ 582#else /* CONFIG_NO_HZ */
@@ -6840,7 +6841,7 @@ void __init sched_init(void)
6840 rq->avg_idle = 2*sysctl_sched_migration_cost; 6841 rq->avg_idle = 2*sysctl_sched_migration_cost;
6841 rq_attach_root(rq, &def_root_domain); 6842 rq_attach_root(rq, &def_root_domain);
6842#ifdef CONFIG_NO_HZ 6843#ifdef CONFIG_NO_HZ
6843 rq->nohz_balance_kick = 0; 6844 rq->nohz_flags = 0;
6844#endif 6845#endif
6845#endif 6846#endif
6846 init_rq_hrtick(rq); 6847 init_rq_hrtick(rq);
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 81ccb811afb4..50c06b0e9fab 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -4889,18 +4889,15 @@ static void nohz_balancer_kick(int cpu)
4889 return; 4889 return;
4890 } 4890 }
4891 4891
4892 if (!cpu_rq(ilb_cpu)->nohz_balance_kick) { 4892 if (test_and_set_bit(NOHZ_BALANCE_KICK, nohz_flags(cpu)))
4893 cpu_rq(ilb_cpu)->nohz_balance_kick = 1; 4893 return;
4894 4894 /*
4895 smp_mb(); 4895 * Use smp_send_reschedule() instead of resched_cpu().
4896 /* 4896 * This way we generate a sched IPI on the target cpu which
4897 * Use smp_send_reschedule() instead of resched_cpu(). 4897 * is idle. And the softirq performing nohz idle load balance
4898 * This way we generate a sched IPI on the target cpu which 4898 * will be run before returning from the IPI.
4899 * is idle. And the softirq performing nohz idle load balance 4899 */
4900 * will be run before returning from the IPI. 4900 smp_send_reschedule(ilb_cpu);
4901 */
4902 smp_send_reschedule(ilb_cpu);
4903 }
4904 return; 4901 return;
4905} 4902}
4906 4903
@@ -4964,6 +4961,8 @@ void select_nohz_load_balancer(int stop_tick)
4964 } 4961 }
4965 return; 4962 return;
4966 } 4963 }
4964
4965 set_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu));
4967 } else { 4966 } else {
4968 if (!cpumask_test_cpu(cpu, nohz.idle_cpus_mask)) 4967 if (!cpumask_test_cpu(cpu, nohz.idle_cpus_mask))
4969 return; 4968 return;
@@ -5079,8 +5078,9 @@ static void nohz_idle_balance(int this_cpu, enum cpu_idle_type idle)
5079 struct rq *rq; 5078 struct rq *rq;
5080 int balance_cpu; 5079 int balance_cpu;
5081 5080
5082 if (idle != CPU_IDLE || !this_rq->nohz_balance_kick) 5081 if (idle != CPU_IDLE ||
5083 return; 5082 !test_bit(NOHZ_BALANCE_KICK, nohz_flags(this_cpu)))
5083 goto end;
5084 5084
5085 for_each_cpu(balance_cpu, nohz.idle_cpus_mask) { 5085 for_each_cpu(balance_cpu, nohz.idle_cpus_mask) {
5086 if (balance_cpu == this_cpu) 5086 if (balance_cpu == this_cpu)
@@ -5091,10 +5091,8 @@ static void nohz_idle_balance(int this_cpu, enum cpu_idle_type idle)
5091 * work being done for other cpus. Next load 5091 * work being done for other cpus. Next load
5092 * balancing owner will pick it up. 5092 * balancing owner will pick it up.
5093 */ 5093 */
5094 if (need_resched()) { 5094 if (need_resched())
5095 this_rq->nohz_balance_kick = 0;
5096 break; 5095 break;
5097 }
5098 5096
5099 raw_spin_lock_irq(&this_rq->lock); 5097 raw_spin_lock_irq(&this_rq->lock);
5100 update_rq_clock(this_rq); 5098 update_rq_clock(this_rq);
@@ -5108,7 +5106,8 @@ static void nohz_idle_balance(int this_cpu, enum cpu_idle_type idle)
5108 this_rq->next_balance = rq->next_balance; 5106 this_rq->next_balance = rq->next_balance;
5109 } 5107 }
5110 nohz.next_balance = this_rq->next_balance; 5108 nohz.next_balance = this_rq->next_balance;
5111 this_rq->nohz_balance_kick = 0; 5109end:
5110 clear_bit(NOHZ_BALANCE_KICK, nohz_flags(this_cpu));
5112} 5111}
5113 5112
5114/* 5113/*
@@ -5129,10 +5128,17 @@ static inline int nohz_kick_needed(struct rq *rq, int cpu)
5129 int ret; 5128 int ret;
5130 int first_pick_cpu, second_pick_cpu; 5129 int first_pick_cpu, second_pick_cpu;
5131 5130
5132 if (time_before(now, nohz.next_balance)) 5131 if (unlikely(idle_cpu(cpu)))
5133 return 0; 5132 return 0;
5134 5133
5135 if (idle_cpu(cpu)) 5134 /*
5135 * We may be recently in ticked or tickless idle mode. At the first
5136 * busy tick after returning from idle, we will update the busy stats.
5137 */
5138 if (unlikely(test_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu))))
5139 clear_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu));
5140
5141 if (time_before(now, nohz.next_balance))
5136 return 0; 5142 return 0;
5137 5143
5138 first_pick_cpu = atomic_read(&nohz.first_pick_cpu); 5144 first_pick_cpu = atomic_read(&nohz.first_pick_cpu);
@@ -5196,7 +5202,7 @@ void trigger_load_balance(struct rq *rq, int cpu)
5196 likely(!on_null_domain(cpu))) 5202 likely(!on_null_domain(cpu)))
5197 raise_softirq(SCHED_SOFTIRQ); 5203 raise_softirq(SCHED_SOFTIRQ);
5198#ifdef CONFIG_NO_HZ 5204#ifdef CONFIG_NO_HZ
5199 else if (nohz_kick_needed(rq, cpu) && likely(!on_null_domain(cpu))) 5205 if (nohz_kick_needed(rq, cpu) && likely(!on_null_domain(cpu)))
5200 nohz_balancer_kick(cpu); 5206 nohz_balancer_kick(cpu);
5201#endif 5207#endif
5202} 5208}
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index 8715055979d1..cf7d02662bc2 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -371,7 +371,7 @@ struct rq {
371 unsigned long last_load_update_tick; 371 unsigned long last_load_update_tick;
372#ifdef CONFIG_NO_HZ 372#ifdef CONFIG_NO_HZ
373 u64 nohz_stamp; 373 u64 nohz_stamp;
374 unsigned char nohz_balance_kick; 374 unsigned long nohz_flags;
375#endif 375#endif
376 int skip_clock_update; 376 int skip_clock_update;
377 377
@@ -1064,3 +1064,12 @@ extern void init_rt_rq(struct rt_rq *rt_rq, struct rq *rq);
1064extern void unthrottle_offline_cfs_rqs(struct rq *rq); 1064extern void unthrottle_offline_cfs_rqs(struct rq *rq);
1065 1065
1066extern void account_cfs_bandwidth_used(int enabled, int was_enabled); 1066extern void account_cfs_bandwidth_used(int enabled, int was_enabled);
1067
1068#ifdef CONFIG_NO_HZ
1069enum rq_nohz_flag_bits {
1070 NOHZ_TICK_STOPPED,
1071 NOHZ_BALANCE_KICK,
1072};
1073
1074#define nohz_flags(cpu) (&cpu_rq(cpu)->nohz_flags)
1075#endif