diff options
Diffstat (limited to 'kernel/sched')
-rw-r--r-- | kernel/sched/core.c | 11 | ||||
-rw-r--r-- | kernel/sched/cpufreq_schedutil.c | 19 | ||||
-rw-r--r-- | kernel/sched/fair.c | 2 | ||||
-rw-r--r-- | kernel/sched/features.h | 5 | ||||
-rw-r--r-- | kernel/sched/wait.c | 39 |
5 files changed, 62 insertions, 14 deletions
diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 956383844116..3b31fc05a0f1 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c | |||
@@ -3287,10 +3287,15 @@ pick_next_task(struct rq *rq, struct task_struct *prev, struct rq_flags *rf) | |||
3287 | struct task_struct *p; | 3287 | struct task_struct *p; |
3288 | 3288 | ||
3289 | /* | 3289 | /* |
3290 | * Optimization: we know that if all tasks are in | 3290 | * Optimization: we know that if all tasks are in the fair class we can |
3291 | * the fair class we can call that function directly: | 3291 | * call that function directly, but only if the @prev task wasn't of a |
3292 | * higher scheduling class, because otherwise those loose the | ||
3293 | * opportunity to pull in more work from other CPUs. | ||
3292 | */ | 3294 | */ |
3293 | if (likely(rq->nr_running == rq->cfs.h_nr_running)) { | 3295 | if (likely((prev->sched_class == &idle_sched_class || |
3296 | prev->sched_class == &fair_sched_class) && | ||
3297 | rq->nr_running == rq->cfs.h_nr_running)) { | ||
3298 | |||
3294 | p = fair_sched_class.pick_next_task(rq, prev, rf); | 3299 | p = fair_sched_class.pick_next_task(rq, prev, rf); |
3295 | if (unlikely(p == RETRY_TASK)) | 3300 | if (unlikely(p == RETRY_TASK)) |
3296 | goto again; | 3301 | goto again; |
diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c index 8f8de3d4d6b7..cd7cd489f739 100644 --- a/kernel/sched/cpufreq_schedutil.c +++ b/kernel/sched/cpufreq_schedutil.c | |||
@@ -36,6 +36,7 @@ struct sugov_policy { | |||
36 | u64 last_freq_update_time; | 36 | u64 last_freq_update_time; |
37 | s64 freq_update_delay_ns; | 37 | s64 freq_update_delay_ns; |
38 | unsigned int next_freq; | 38 | unsigned int next_freq; |
39 | unsigned int cached_raw_freq; | ||
39 | 40 | ||
40 | /* The next fields are only needed if fast switch cannot be used. */ | 41 | /* The next fields are only needed if fast switch cannot be used. */ |
41 | struct irq_work irq_work; | 42 | struct irq_work irq_work; |
@@ -52,7 +53,6 @@ struct sugov_cpu { | |||
52 | struct update_util_data update_util; | 53 | struct update_util_data update_util; |
53 | struct sugov_policy *sg_policy; | 54 | struct sugov_policy *sg_policy; |
54 | 55 | ||
55 | unsigned int cached_raw_freq; | ||
56 | unsigned long iowait_boost; | 56 | unsigned long iowait_boost; |
57 | unsigned long iowait_boost_max; | 57 | unsigned long iowait_boost_max; |
58 | u64 last_update; | 58 | u64 last_update; |
@@ -116,7 +116,7 @@ static void sugov_update_commit(struct sugov_policy *sg_policy, u64 time, | |||
116 | 116 | ||
117 | /** | 117 | /** |
118 | * get_next_freq - Compute a new frequency for a given cpufreq policy. | 118 | * get_next_freq - Compute a new frequency for a given cpufreq policy. |
119 | * @sg_cpu: schedutil cpu object to compute the new frequency for. | 119 | * @sg_policy: schedutil policy object to compute the new frequency for. |
120 | * @util: Current CPU utilization. | 120 | * @util: Current CPU utilization. |
121 | * @max: CPU capacity. | 121 | * @max: CPU capacity. |
122 | * | 122 | * |
@@ -136,19 +136,18 @@ static void sugov_update_commit(struct sugov_policy *sg_policy, u64 time, | |||
136 | * next_freq (as calculated above) is returned, subject to policy min/max and | 136 | * next_freq (as calculated above) is returned, subject to policy min/max and |
137 | * cpufreq driver limitations. | 137 | * cpufreq driver limitations. |
138 | */ | 138 | */ |
139 | static unsigned int get_next_freq(struct sugov_cpu *sg_cpu, unsigned long util, | 139 | static unsigned int get_next_freq(struct sugov_policy *sg_policy, |
140 | unsigned long max) | 140 | unsigned long util, unsigned long max) |
141 | { | 141 | { |
142 | struct sugov_policy *sg_policy = sg_cpu->sg_policy; | ||
143 | struct cpufreq_policy *policy = sg_policy->policy; | 142 | struct cpufreq_policy *policy = sg_policy->policy; |
144 | unsigned int freq = arch_scale_freq_invariant() ? | 143 | unsigned int freq = arch_scale_freq_invariant() ? |
145 | policy->cpuinfo.max_freq : policy->cur; | 144 | policy->cpuinfo.max_freq : policy->cur; |
146 | 145 | ||
147 | freq = (freq + (freq >> 2)) * util / max; | 146 | freq = (freq + (freq >> 2)) * util / max; |
148 | 147 | ||
149 | if (freq == sg_cpu->cached_raw_freq && sg_policy->next_freq != UINT_MAX) | 148 | if (freq == sg_policy->cached_raw_freq && sg_policy->next_freq != UINT_MAX) |
150 | return sg_policy->next_freq; | 149 | return sg_policy->next_freq; |
151 | sg_cpu->cached_raw_freq = freq; | 150 | sg_policy->cached_raw_freq = freq; |
152 | return cpufreq_driver_resolve_freq(policy, freq); | 151 | return cpufreq_driver_resolve_freq(policy, freq); |
153 | } | 152 | } |
154 | 153 | ||
@@ -213,7 +212,7 @@ static void sugov_update_single(struct update_util_data *hook, u64 time, | |||
213 | } else { | 212 | } else { |
214 | sugov_get_util(&util, &max); | 213 | sugov_get_util(&util, &max); |
215 | sugov_iowait_boost(sg_cpu, &util, &max); | 214 | sugov_iowait_boost(sg_cpu, &util, &max); |
216 | next_f = get_next_freq(sg_cpu, util, max); | 215 | next_f = get_next_freq(sg_policy, util, max); |
217 | } | 216 | } |
218 | sugov_update_commit(sg_policy, time, next_f); | 217 | sugov_update_commit(sg_policy, time, next_f); |
219 | } | 218 | } |
@@ -267,7 +266,7 @@ static unsigned int sugov_next_freq_shared(struct sugov_cpu *sg_cpu, | |||
267 | sugov_iowait_boost(j_sg_cpu, &util, &max); | 266 | sugov_iowait_boost(j_sg_cpu, &util, &max); |
268 | } | 267 | } |
269 | 268 | ||
270 | return get_next_freq(sg_cpu, util, max); | 269 | return get_next_freq(sg_policy, util, max); |
271 | } | 270 | } |
272 | 271 | ||
273 | static void sugov_update_shared(struct update_util_data *hook, u64 time, | 272 | static void sugov_update_shared(struct update_util_data *hook, u64 time, |
@@ -580,6 +579,7 @@ static int sugov_start(struct cpufreq_policy *policy) | |||
580 | sg_policy->next_freq = UINT_MAX; | 579 | sg_policy->next_freq = UINT_MAX; |
581 | sg_policy->work_in_progress = false; | 580 | sg_policy->work_in_progress = false; |
582 | sg_policy->need_freq_update = false; | 581 | sg_policy->need_freq_update = false; |
582 | sg_policy->cached_raw_freq = 0; | ||
583 | 583 | ||
584 | for_each_cpu(cpu, policy->cpus) { | 584 | for_each_cpu(cpu, policy->cpus) { |
585 | struct sugov_cpu *sg_cpu = &per_cpu(sugov_cpu, cpu); | 585 | struct sugov_cpu *sg_cpu = &per_cpu(sugov_cpu, cpu); |
@@ -590,7 +590,6 @@ static int sugov_start(struct cpufreq_policy *policy) | |||
590 | sg_cpu->max = 0; | 590 | sg_cpu->max = 0; |
591 | sg_cpu->flags = SCHED_CPUFREQ_RT; | 591 | sg_cpu->flags = SCHED_CPUFREQ_RT; |
592 | sg_cpu->last_update = 0; | 592 | sg_cpu->last_update = 0; |
593 | sg_cpu->cached_raw_freq = 0; | ||
594 | sg_cpu->iowait_boost = 0; | 593 | sg_cpu->iowait_boost = 0; |
595 | sg_cpu->iowait_boost_max = policy->cpuinfo.max_freq; | 594 | sg_cpu->iowait_boost_max = policy->cpuinfo.max_freq; |
596 | cpufreq_add_update_util_hook(cpu, &sg_cpu->update_util, | 595 | cpufreq_add_update_util_hook(cpu, &sg_cpu->update_util, |
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 3e88b35ac157..dea138964b91 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c | |||
@@ -5799,7 +5799,7 @@ static int select_idle_cpu(struct task_struct *p, struct sched_domain *sd, int t | |||
5799 | * Due to large variance we need a large fuzz factor; hackbench in | 5799 | * Due to large variance we need a large fuzz factor; hackbench in |
5800 | * particularly is sensitive here. | 5800 | * particularly is sensitive here. |
5801 | */ | 5801 | */ |
5802 | if ((avg_idle / 512) < avg_cost) | 5802 | if (sched_feat(SIS_AVG_CPU) && (avg_idle / 512) < avg_cost) |
5803 | return -1; | 5803 | return -1; |
5804 | 5804 | ||
5805 | time = local_clock(); | 5805 | time = local_clock(); |
diff --git a/kernel/sched/features.h b/kernel/sched/features.h index 69631fa46c2f..1b3c8189b286 100644 --- a/kernel/sched/features.h +++ b/kernel/sched/features.h | |||
@@ -51,6 +51,11 @@ SCHED_FEAT(NONTASK_CAPACITY, true) | |||
51 | */ | 51 | */ |
52 | SCHED_FEAT(TTWU_QUEUE, true) | 52 | SCHED_FEAT(TTWU_QUEUE, true) |
53 | 53 | ||
54 | /* | ||
55 | * When doing wakeups, attempt to limit superfluous scans of the LLC domain. | ||
56 | */ | ||
57 | SCHED_FEAT(SIS_AVG_CPU, false) | ||
58 | |||
54 | #ifdef HAVE_RT_PUSH_IPI | 59 | #ifdef HAVE_RT_PUSH_IPI |
55 | /* | 60 | /* |
56 | * In order to avoid a thundering herd attack of CPUs that are | 61 | * In order to avoid a thundering herd attack of CPUs that are |
diff --git a/kernel/sched/wait.c b/kernel/sched/wait.c index 4d2ea6f25568..b8c84c6dee64 100644 --- a/kernel/sched/wait.c +++ b/kernel/sched/wait.c | |||
@@ -242,6 +242,45 @@ long prepare_to_wait_event(wait_queue_head_t *q, wait_queue_t *wait, int state) | |||
242 | } | 242 | } |
243 | EXPORT_SYMBOL(prepare_to_wait_event); | 243 | EXPORT_SYMBOL(prepare_to_wait_event); |
244 | 244 | ||
245 | /* | ||
246 | * Note! These two wait functions are entered with the | ||
247 | * wait-queue lock held (and interrupts off in the _irq | ||
248 | * case), so there is no race with testing the wakeup | ||
249 | * condition in the caller before they add the wait | ||
250 | * entry to the wake queue. | ||
251 | */ | ||
252 | int do_wait_intr(wait_queue_head_t *wq, wait_queue_t *wait) | ||
253 | { | ||
254 | if (likely(list_empty(&wait->task_list))) | ||
255 | __add_wait_queue_tail(wq, wait); | ||
256 | |||
257 | set_current_state(TASK_INTERRUPTIBLE); | ||
258 | if (signal_pending(current)) | ||
259 | return -ERESTARTSYS; | ||
260 | |||
261 | spin_unlock(&wq->lock); | ||
262 | schedule(); | ||
263 | spin_lock(&wq->lock); | ||
264 | return 0; | ||
265 | } | ||
266 | EXPORT_SYMBOL(do_wait_intr); | ||
267 | |||
268 | int do_wait_intr_irq(wait_queue_head_t *wq, wait_queue_t *wait) | ||
269 | { | ||
270 | if (likely(list_empty(&wait->task_list))) | ||
271 | __add_wait_queue_tail(wq, wait); | ||
272 | |||
273 | set_current_state(TASK_INTERRUPTIBLE); | ||
274 | if (signal_pending(current)) | ||
275 | return -ERESTARTSYS; | ||
276 | |||
277 | spin_unlock_irq(&wq->lock); | ||
278 | schedule(); | ||
279 | spin_lock_irq(&wq->lock); | ||
280 | return 0; | ||
281 | } | ||
282 | EXPORT_SYMBOL(do_wait_intr_irq); | ||
283 | |||
245 | /** | 284 | /** |
246 | * finish_wait - clean up after waiting in a queue | 285 | * finish_wait - clean up after waiting in a queue |
247 | * @q: waitqueue waited on | 286 | * @q: waitqueue waited on |