sched: Fix wakeup preemption regression
Peter Zijlstra
maintainercover sched: Fix wakeup preemption regression
A recent commit caused an interactivity/starvation issue because we wrecked rq local wakeup preemption.
These patches rectify this while also (hopefully) keeping the problem that led to the fault patch fixed.
Mike, Pavan, could you guys please confirm?
Peter Zijlstra
maintainerPATCH 1/3 sched,fair: Move record_wakee()
Since I want to make ->task_woken() conditional on the task getting migrated, we cannot use it to call record_wakee().
Move it to select_task_rq_fair(), which gets called in almost all the same conditions. The only exception is if the woken task (@p) is cpu-bound (as per the nr_cpus_allowed test in select_task_rq()).
--- kernel/sched/fair.c | 61 ++++++++++++++++++++++++++++------------------------ 1 file changed, 33 insertions(+), 28 deletions(-)
kernel/sched/fair.c +33 -28
@@ -4811,24 +4811,6 @@ static unsigned long cpu_avg_load_per_tareturn 0 ; } -static void record_wakee (struct task_struct *p) -{ -/* -* Rough decay (wiping) for cost saving, don't worry -* about the boundary, really active task won't care -* about the loss. -*/ -if (time_after (jiffies, current->wakee_flip_decay_ts +HZ )) { - current->wakee_flips >>=1 ; - current->wakee_flip_decay_ts = jiffies; - } - -if (current->last_wakee != p) { - current->last_wakee = p; - current->wakee_flips++; - } -} -static void task_waking_fair (struct task_struct *p) {struct sched_entity *se = &p->se;
@@ -4848,7 +4830,6 @@ static void task_waking_fair(struct task#endif se->vruntime -= min_vruntime; -record_wakee (p); }#ifdef CONFIG_FAIR_GROUP_SCHED
@@ -4966,17 +4947,39 @@ static long effective_load(struct task_g#endif +static void record_wakee (struct task_struct *p) +{ +/* +* Only decay a single time; tasks that have less then 1 wakeup per +* jiffy will not have built up many flips. +*/ +if (time_after (jiffies, current->wakee_flip_decay_ts +HZ )) { + current->wakee_flips >>=1 ; + current->wakee_flip_decay_ts = jiffies; + } + +if (current->last_wakee != p) { + current->last_wakee = p; + current->wakee_flips++; + } +} +/* * Detect M:N waker/wakee relationships via a switching-frequency heuristic. +* * A waker of many should wake a different task than the one last awakened -* at a frequency roughly N times higher than one of its wakees. In order -* to determine whether we should let the load spread vs consolodating to -* shared cache, we look for a minimum 'flip' frequency of llc_size in one -* partner, and a factor of lls_size higher frequency in the other. With -* both conditions met, we can be relatively sure that the relationship is -* non-monogamous, with partner count exceeding socket size. Waker/wakee -* being client/server, worker/dispatcher, interrupt source or whatever is -* irrelevant, spread criteria is apparent partner count exceeds socket size. +* at a frequency roughly N times higher than one of its wakees. +* +* In order to determine whether we should let the load spread vs consolidating +* to shared cache, we look for a minimum 'flip' frequency of llc_size in one +* partner, and a factor of lls_size higher frequency in the other. +* +* With both conditions met, we can be relatively sure that the relationship is +* non-monogamous, with partner count exceeding socket size. +* +* Waker/wakee being client/server, worker/dispatcher, interrupt source or +* whatever is irrelevant, spread criteria is apparent partner count exceeds +* socket size. */ static int wake_wide (struct task_struct *p) {
@@ -5281,8 +5284,10 @@ select_task_rq_fair(struct task_struct *int want_affine =0 ;int sync = wake_flags &WF_SYNC ; -if (sd_flag &SD_BALANCE_WAKE ) +if (sd_flag &SD_BALANCE_WAKE ) { +record_wakee (p); want_affine = !wake_wide (p) &&cpumask_test_cpu (cpu,tsk_cpus_allowed (p)); + }rcu_read_lock ();for_each_domain (cpu, tmp) {
Re: [PATCH 1/3] sched,fair: Move record_wakee()
Quoted 2 lines · Peter Zijlstra
Since I want to make ->task_woken() conditional on the task getting migrated, we cannot use it to call
record_wakee().
You mean ->task_waking(), right?
Peter Zijlstra
maintainerRe: [PATCH 1/3] sched,fair: Move record_wakee()
Quoted 5 lines · Matt Fleming
Quoted 2 lines · Peter Zijlstra
Since I want to make ->task_woken() conditional on the task getting migrated, we cannot use it to call
record_wakee().You mean ->task_waking(), right?
Uh yes :-) typing be hard.
Peter Zijlstra
maintainerPATCH 2/3 sched,fair: Fix local starvation
In reply to Peter ZijlstraMike reported that the recent commit 3a47d5124a95 ("sched/fair: Fix fairness issue on migration") broke interactivity and the signal starve test.
The problem is that I assumed ENQUEUE_WAKING was only set when we do a cross-cpu wakeup (migration), which isn't true. This means we now destroy the vruntime history of tasks and wakeup-preemption suffers.
Cure this by making my assumption true, only call sched_class::task_waking() when we do a cross-cpu wakeup. This avoids the indirect call in the case we do a local wakeup.
--- kernel/sched/core.c | 29 +++++++++++++++++++++-------- kernel/sched/fair.c | 41 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 61 insertions(+), 9 deletions(-)
kernel/sched/core.c +21 -8
@@ -1709,14 +1709,22 @@ static void ttwu_do_activate(struct rq *rq, struct task_struct *p, int wake_flags, struct pin_cookie cookie) { + int en_flags = ENQUEUE_WAKEUP; +lockdep_assert_held (&rq->lock);#ifdef CONFIG_SMP if (p->sched_contributes_to_load) rq->nr_uninterruptible--; + +/* +* If we migrated; we must have called sched_class::task_waking(). +*/ +if (wake_flags &WF_MIGRATED ) + en_flags |=ENQUEUE_WAKING ;#endif -ttwu_activate (rq, p,ENQUEUE_WAKEUP |ENQUEUE_WAKING ); +ttwu_activate (rq, p, en_flags);ttwu_do_wakeup (rq, p, wake_flags, cookie); }
@@ -1762,7 +1770,11 @@ void sched_ttwu_pending(void)while (llist) { p = llist_entry(llist, struct task_struct, wake_entry); llist =llist_next (llist); -ttwu_do_activate (rq, p,0 , cookie); +/* +* See ttwu_queue(); we only call ttwu_queue_remote() when +* its a x-cpu wakeup. +*/ +ttwu_do_activate (rq, p,WF_MIGRATED , cookie); }lockdep_unpin_lock (&rq->lock, cookie);
@@ -1849,7 +1861,7 @@ bool cpus_share_cache(int this_cpu, int }#endif /* CONFIG_SMP */ -static void ttwu_queue (struct task_struct *p,int cpu) +static void ttwu_queue (struct task_struct *p,int cpu,int wake_flags) {struct rq *rq =cpu_rq (cpu);struct pin_cookie cookie;
@@ -1864,7 +1876,7 @@ static void ttwu_queue(struct task_strucraw_spin_lock (&rq->lock); cookie =lockdep_pin_lock (&rq->lock); -ttwu_do_activate (rq, p,0 , cookie); +ttwu_do_activate (rq, p, wake_flags, cookie);lockdep_unpin_lock (&rq->lock, cookie);raw_spin_unlock (&rq->lock); }
@@ -2034,17 +2046,18 @@ try_to_wake_up(struct task_struct *p, un p->sched_contributes_to_load = !!task_contributes_to_load (p); p->state =TASK_WAKING ; -if (p->sched_class->task_waking) - p->sched_class->task_waking (p); - cpu =select_task_rq (p, p->wake_cpu,SD_BALANCE_WAKE , wake_flags);if (task_cpu (p) != cpu) { wake_flags |=WF_MIGRATED ; + +if (p->sched_class->task_waking) + p->sched_class->task_waking (p); +set_task_cpu (p, cpu); }#endif /* CONFIG_SMP */ -ttwu_queue (p, cpu); +ttwu_queue (p, cpu, wake_flags); stat:if (schedstat_enabled ())ttwu_stat (p, cpu, wake_flags);
kernel/sched/fair.c +40 -1
59 lines not on this page · raw message
Re: [PATCH 2/3] sched,fair: Fix local starvation
Quoted 3 lines · Peter Zijlstra
Mike reported that the recent commit
3a47d5124a95("sched/fair: Fix fairness issue on migration") broke interactivity and the signal starve test.
This looks pretty dangerous for v4.6 - how about simply reverting in 3a47d5124a95 and re-trying in v4.7?
Thanks,
Ingo
Peter Zijlstra
maintainerRe: [PATCH 2/3] sched,fair: Fix local starvation
Quoted 9 lines · Ingo Molnar
Quoted 3 lines · Peter Zijlstra
Mike reported that the recent commit
3a47d5124a95("sched/fair: Fix fairness issue on migration") broke interactivity and the signal starve test.This looks pretty dangerous for v4.6 - how about simply reverting in
3a47d5124a95and re-trying in v4.7?
Sure.
Re: [PATCH 2/3] sched,fair: Fix local starvation
In reply to Peter ZijlstraQuoted 23 lines · Peter Zijlstra
Mike reported that the recent commit
3a47d5124a95("sched/fair: Fix fairness issue on migration") broke interactivity and the signal starve test.The problem is that I assumed
ENQUEUE_WAKINGwas only set when we do a cross-cpu wakeup (migration), which isn't true. This means we now destroy the vruntime history of tasks and wakeup-preemption suffers.Cure this by making my assumption true, only call
sched_class::task_waking()when we do a cross-cpu wakeup. This avoids the indirect call in the case we do a local wakeup.Cc Pavan Kondeti <[email protected]>Cc Ben Segall <[email protected]>Cc Matt Fleming <[email protected]>Cc Morten Rasmussen <[email protected]>Cc Paul Turner <[email protected]>Cc Thomas Gleixner <[email protected]>Cc Andrew Hunter <[email protected]>Fixes 3a47d5124a95 ("sched/fair: Fix fairness issue on migration")Reported-by Mike Galbraith <[email protected]>Signed-off-by Peter Zijlstra (Intel) <[email protected]>
Quoted 4 lines
--- kernel/sched/core.c | 29 +++++++++++++++++++++-------- kernel/sched/fair.c | 41 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 61 insertions(+), 9 deletions(-)
This patch appears to cause a regression for hackbench -pipe of between ~8% and ~10% with groups >= NR_CPU.
I haven't probed much yet, but it looks like the vruntime of tasks has gone nuts.
Re: [PATCH 2/3] sched,fair: Fix local starvation
In reply to Peter ZijlstraOn Tue, 2016-05-10 at 19:43 +0200, Peter Zijlstra wrote:
(Evolution authors must either not do patch review, or use some other mailer. Squint hard, this crud really is your patch;)
kernel/sched/core.c void sched_ttwu_pending(void) · line 1777
Quoted 13 lines
kernel/sched/core.c +5
-1@@ -1762,7 +1770,11 @@ void sched_ttwu_pending(void) > > while (llist) { > > > p = llist_entry(llist, struct task_struct, wake_entry); > > > llist = llist_next(llist); -> > > ttwu_do_activate(rq, p, 0, cookie); +> > > /* +> > > * See ttwu_queue(); we only call ttwu_queue_remote() when +> > > * its a x-cpu wakeup. +> > > */ +> > > ttwu_do_activate(rq, p, WF_MIGRATED, cookie);
Wakees that were not migrated/normalized eat an unwanted min_vruntime, and likely take a size XXL latency hit. Big box running master bled profusely under heavy load until I turned TTWU_QUEUE off.
-Mike
Re: [PATCH 2/3] sched,fair: Fix local starvation
Quoted 3 lines · Mike Galbraith
Wakees that were not migrated/normalized eat an unwanted
min_vruntime, and likely take a size XXL latency hit. Big box running master bled profusely under heavy load until I turnedTTWU_QUEUEoff.
The below made big box a happy camper again.
sched/fair: Move se->vruntime normalization state into struct sched_entity
Make ->vruntime normalization state explicit.
--- include/linux/sched.h | 1 + kernel/sched/core.c | 1 + kernel/sched/fair.c | 42 ++++++++++++++---------------------------- 3 files changed, 16 insertions(+), 28 deletions(-)
include/linux/sched.h +1 -0
@@ -1348,6 +1348,7 @@ struct sched_entity {struct rb_node run_node;struct list_head group_node;unsigned int on_rq; +bool normalized;u64 exec_start;u64 sum_exec_runtime;
kernel/sched/core.c +1 -0
@@ -2259,6 +2259,7 @@ static void __sched_fork(unsigned long c p->se.prev_sum_exec_runtime =0 ; p->se.nr_migrations =0 ; p->se.vruntime =0 ; + p->se.normalized = true;INIT_LIST_HEAD (&p->se.group_node);#ifdef CONFIG_FAIR_GROUP_SCHED
kernel/sched/fair.c +14 -28
100 lines not on this page · raw message
PATCH 1/1 sched/fair: Move se->vruntime normalization state into struct sched_entity
Quoted 5 lines · Mike Galbraith
Quoted 3 lines · Mike Galbraith
Wakees that were not migrated/normalized eat an unwanted
min_vruntime, and likely take a size XXL latency hit. Big box running master bled profusely under heavy load until I turnedTTWU_QUEUEoff.
May as well make it official and against master.today. Fly or die little patchlet.
sched/fair: Move se->vruntime normalization state into struct sched_entity
b5179ac70de ceased globally normalizing wakee vruntime in ttwu(), leaving sched_ttwu_pending() with the need to know whether each wakee on wake_list was migrated or not, to pass that on to fair class functions so they can DTRT wrt vruntime normalization. Store vruntime normalization state in struct sched_entity, so fair class functions that need it always have it, and sched_ttwu_pending() again doesn't need to care whether tasks on the wake_list have been migrated or not.
Since there are now no consumers of ENQUEUE_MIGRATED, drop it as well.
master v4.6-8889-gf6c658df6385 virgin
256 49096 71698.99 MB/sec warmup 1 sec latency 1136.488 ms 256 155009 72862.08 MB/sec execute 1 sec latency 3136.900 ms 256 207430 72628.04 MB/sec execute 2 sec latency 4137.001 ms 256 259635 72442.97 MB/sec execute 3 sec latency 5137.105 ms 256 311905 72371.84 MB/sec execute 4 sec latency 6137.214 ms 256 364210 72564.99 MB/sec execute 5 sec latency 7137.323 ms 256 416551 72598.74 MB/sec execute 6 sec latency 5816.895 ms 256 468824 72601.54 MB/sec execute 7 sec latency 6815.386 ms 256 520996 72621.87 MB/sec execute 8 sec latency 7815.499 ms 256 573113 72608.75 MB/sec execute 9 sec latency 8815.609 ms 256 cleanup 10 sec 0 cleanup 10 sec
master v4.6-8889-gf6c658df6385 post
256 51527 75357.55 MB/sec warmup 1 sec latency 21.591 ms 256 157610 73188.06 MB/sec execute 1 sec latency 12.985 ms 256 210089 72809.01 MB/sec execute 2 sec latency 11.543 ms 256 262554 72681.86 MB/sec execute 3 sec latency 0.209 ms 256 315432 72798.65 MB/sec execute 4 sec latency 0.206 ms 256 368162 72963.33 MB/sec execute 5 sec latency 8.052 ms 256 420854 72976.50 MB/sec execute 6 sec latency 0.221 ms 256 473420 72953.76 MB/sec execute 7 sec latency 0.198 ms 256 525859 73011.17 MB/sec execute 8 sec latency 2.810 ms 256 578301 73052.84 MB/sec execute 9 sec latency 0.247 ms 256 cleanup 10 sec 0 cleanup 10 sec
--- include/linux/sched.h | 1 kernel/sched/core.c | 6 +---- kernel/sched/fair.c | 60 ++++++++++++++++++++------------------------------ 3 files changed, 28 insertions(+), 39 deletions(-)
include/linux/sched.h +1 -0
@@ -1319,6 +1319,7 @@ struct sched_entity {struct rb_node run_node;struct list_head group_node;unsigned int on_rq; +bool normalized;u64 exec_start;u64 sum_exec_runtime;
kernel/sched/core.c +2 -4
@@ -1719,9 +1719,6 @@ ttwu_do_activate(struct rq *rq, struct t#ifdef CONFIG_SMP if (p->sched_contributes_to_load) rq->nr_uninterruptible--; - -if (wake_flags &WF_MIGRATED ) - en_flags |=ENQUEUE_MIGRATED ;#endif ttwu_activate (rq, p, en_flags);
@@ -1774,7 +1771,7 @@ void sched_ttwu_pending(void)* See ttwu_queue(); we only call ttwu_queue_remote() when * its a x-cpu wakeup. */ -ttwu_do_activate (rq, p,WF_MIGRATED , cookie); +ttwu_do_activate (rq, p,0 , cookie); }lockdep_unpin_lock (&rq->lock, cookie);
@@ -2166,6 +2163,7 @@ static void __sched_fork(unsigned long c p->se.prev_sum_exec_runtime =0 ; p->se.nr_migrations =0 ; p->se.vruntime =0 ; + p->se.normalized = true;INIT_LIST_HEAD (&p->se.group_node);#ifdef CONFIG_FAIR_GROUP_SCHED
kernel/sched/fair.c +25 -35
125 lines not on this page · raw message
Peter Zijlstra
maintainerRe: [patch] sched/fair: Move se->vruntime normalization state into struct sched_entity
Quoted 11 lines · Mike Galbraith
Quoted 5 lines · Mike Galbraith
Quoted 3 lines · Mike Galbraith
Wakees that were not migrated/normalized eat an unwanted
min_vruntime, and likely take a size XXL latency hit. Big box running master bled profusely under heavy load until I turnedTTWU_QUEUEoff.May as well make it official and against master.today. Fly or die little patchlet.
sched/fair: Move
se->vruntimenormalization state into structsched_entity
Yeah, I used to have a patch like this; but for debugging. I don't particularly like carrying this information other than for verification because it means we either do too much or too little normalization.
I'll try and have a look on Monday, but I got some real-life things to sort out first..
Re: [patch] sched/fair: Move se->vruntime normalization state into struct sched_entity
Quoted 11 lines · Peter Zijlstra
Quoted 10 lines · Mike Galbraith
Quoted 5 lines · Mike Galbraith
Quoted 3 lines · Mike Galbraith
Wakees that were not migrated/normalized eat an unwanted
min_vruntime, and likely take a size XXL latency hit. Big box running master bled profusely under heavy load until I turnedTTWU_QUEUEoff.May as well make it official and against master.today. Fly or die little patchlet.
Quoted 8 lines
Quoted 1 line
sched/fair: Move
se->vruntimenormalization state into structsched_entityYeah, I used to have a patch like this; but for debugging. I don't particularly like carrying this information other than for verification because it means we either do too much or too little normalization.
I'll try and have a look on Monday, but I got some real-life things to sort out first..
Ok (flush, say hi to the goldfish little patchlet). I don't care how it gets fixed, only that it does, and yours will likely be prettier :)
-Mike
Peter Zijlstra
maintainerRe: [patch] sched/fair: Move se->vruntime normalization state into struct sched_entity
In reply to Peter ZijlstraQuoted 9 lines · Peter Zijlstra
Quoted 2 lines
sched/fair: Move
se->vruntimenormalization state into structsched_entityYeah, I used to have a patch like this; but for debugging. I don't particularly like carrying this information other than for verification because it means we either do too much or too little normalization.
I'll try and have a look on Monday, but I got some real-life things to sort out first..
Ah, I think I see why we might actually need a variable this time... Brain seems to have worked overtime while pulling weeds in the garden :-)
In any case, I'll have a look on Monday.
Peter Zijlstra
maintainerRe: [patch] sched/fair: Move se->vruntime normalization state into struct sched_entity
In reply to Mike GalbraithQuoted 11 lines · Mike Galbraith
Quoted 5 lines · Mike Galbraith
Quoted 3 lines · Mike Galbraith
Wakees that were not migrated/normalized eat an unwanted
min_vruntime, and likely take a size XXL latency hit. Big box running master bled profusely under heavy load until I turnedTTWU_QUEUEoff.May as well make it official and against master.today. Fly or die little patchlet.
sched/fair: Move
se->vruntimenormalization state into structsched_entity
Does this work?
--- include/linux/sched.h | 1 + kernel/sched/core.c | 18 +++++++++++------- 2 files changed, 12 insertions(+), 7 deletions(-)
include/linux/sched.h +1 -0
@@ -1534,6 +1534,7 @@ struct task_struct { unsigned sched_reset_on_fork:1; unsigned sched_contributes_to_load:1; unsigned sched_migrated:1; + unsigned sched_remote_wakeup:1; unsigned :0; /* force alignment to the next boundary *//* unserialized, strictly 'current' */
kernel/sched/core.c +11 -7
@@ -1768,13 +1768,15 @@ void sched_ttwu_pending(void) cookie =lockdep_pin_lock (&rq->lock);while (llist) { +int wake_flags =0 ; + p = llist_entry(llist, struct task_struct, wake_entry); llist =llist_next (llist); -/* -* See ttwu_queue(); we only call ttwu_queue_remote() when -* its a x-cpu wakeup. -*/ -ttwu_do_activate (rq, p,WF_MIGRATED , cookie); + +if (p->sched_remote_wakeup) + wake_flags =WF_MIGRATED ; + +ttwu_do_activate (rq, p, wake_flags, cookie); }lockdep_unpin_lock (&rq->lock, cookie);
@@ -1819,10 +1821,12 @@ void scheduler_ipi(void)irq_exit (); } -static void ttwu_queue_remote (struct task_struct *p,int cpu) +static void ttwu_queue_remote (struct task_struct *p,int cpu,int wake_flags) {struct rq *rq =cpu_rq (cpu); + p->sched_remote_wakeup = !!(wake_flags &WF_MIGRATED ); +if (llist_add (&p->wake_entry, &cpu_rq (cpu)->wake_list)) {if (!set_nr_if_polling (rq->idle))smp_send_reschedule (cpu);
@@ -1869,7 +1873,7 @@ static void ttwu_queue(struct task_struct *p, int cpu, int wake_flags)#if defined(CONFIG_SMP )if (sched_feat (TTWU_QUEUE ) && !cpus_share_cache (smp_processor_id (), cpu)) {sched_clock_cpu (cpu);/* sync clocks x-cpu */ -ttwu_queue_remote (p, cpu); +ttwu_queue_remote (p, cpu, wake_flags);return ; }#endif
Re: [patch] sched/fair: Move se->vruntime normalization state into struct sched_entity
Quoted 8 lines · Peter Zijlstra
Quoted 7 lines · Mike Galbraith
Quoted 5 lines · Mike Galbraith
Quoted 3 lines · Mike Galbraith
Wakees that were not migrated/normalized eat an unwanted
min_vruntime, and likely take a size XXL latency hit. Big box running master bled profusely under heavy load until I turnedTTWU_QUEUEoff.
Quoted 6 lines
Quoted 4 lines
May as well make it official and against master.today. Fly or die little patchlet.
sched/fair: Move
se->vruntimenormalization state into structsched_entityDoes this work?
Yup, bugs--. Kinda funny, I considered ~this way first, but thought you'd not that approach.. dang, got it back-assward ;-)
Quoted 70 lines
--- include/linux/sched.h | 1 + kernel/sched/core.c | 18 +++++++++++------- 2 files changed, 12 insertions(+), 7 deletions(-)include/linux/sched.h +1
-0@@ -1534,6 +1534,7 @@ struct task_struct { unsigned sched_reset_on_fork:1; unsigned sched_contributes_to_load:1; unsigned sched_migrated:1; + unsigned sched_remote_wakeup:1; unsigned :0; /* force alignment to the next boundary *//* unserialized, strictly 'current' */ kernel/sched/core.c +2
-2@@ -1768,13 +1768,15 @@ void sched_ttwu_pending(void) cookie =lockdep_pin_lock (&rq->lock);while (llist) { +int wake_flags =0 ; + p = llist_entry(llist, struct task_struct, wake_entry); llist =llist_next (llist); -/* -* See ttwu_queue(); we only call
ttwu_queue_remote()whenkernel/sched/core.c +8
-4-* its a x-cpu wakeup. -*/ -ttwu_do_activate (rq, p,WF_MIGRATED , cookie); + +if (p->sched_remote_wakeup) + wake_flags =WF_MIGRATED ; + +ttwu_do_activate (rq, p, wake_flags, cookie); }lockdep_unpin_lock (&rq->lock, cookie);@@ -1819,10 +1821,12 @@ void scheduler_ipi(void)irq_exit (); } -static void ttwu_queue_remote (struct task_struct *p,int cpu) +static void ttwu_queue_remote (struct task_struct *p,int cpu,int wake_flags) {struct rq *rq =cpu_rq (cpu); + p->sched_remote_wakeup = !!(wake_flags &WF_MIGRATED ); +if (llist_add (&p->wake_entry, &cpu_rq (cpu)->wake_list)) {if (!set_nr_if_polling (rq->idle))kernel/sched/core.c +1
-1smp_send_reschedule (cpu);@@ -1869,7 +1873,7 @@ static void ttwu_queue(struct task_struct *p, int cpu, int wake_flags)#if defined(CONFIG_SMP )if (sched_feat (TTWU_QUEUE ) && !cpus_share_cache (smp_processor_id (), cpu)) {sched_clock_cpu (cpu);/* sync clocks x-cpu */ -ttwu_queue_remote (p, cpu); +ttwu_queue_remote (p, cpu, wake_flags);return ;}
#endif
Wanpeng Li
Reviewed-byRe: [patch] sched/fair: Move se->vruntime normalization state into struct sched_entity
2016-05-23 17:40 GMT+08:00 Mike Galbraith <[email protected]>:
Quoted 12 lines · Peter Zijlstra
Quoted 11 lines · Mike Galbraith
Quoted 10 lines · Mike Galbraith
Quoted 5 lines · Mike Galbraith
Quoted 4 lines
Wakees that were not migrated/normalized eat an unwanted
min_vruntime, and likely take a size XXL latency hit. Big box running master bled profusely under heavy load until I turnedTTWU_QUEUEoff.May as well make it official and against master.today. Fly or die little patchlet.
Quoted 7 lines
Quoted 3 lines
Quoted 1 line
sched/fair: Move
se->vruntimenormalization state into structsched_entityDoes this work?
Yup, bugs--. Kinda funny, I considered ~this way first, but thought you'd not that approach.. dang, got it back-assward ;-)
Nicer this one.
Quoted 70 lines
Quoted 70 lines
--- include/linux/sched.h | 1 + kernel/sched/core.c | 18 +++++++++++------- 2 files changed, 12 insertions(+), 7 deletions(-)include/linux/sched.h +1
-0@@ -1534,6 +1534,7 @@ struct task_struct { unsigned sched_reset_on_fork:1; unsigned sched_contributes_to_load:1; unsigned sched_migrated:1; + unsigned sched_remote_wakeup:1; unsigned :0; /* force alignment to the next boundary *//* unserialized, strictly 'current' */ kernel/sched/core.c +2
-2@@ -1768,13 +1768,15 @@ void sched_ttwu_pending(void) cookie =lockdep_pin_lock (&rq->lock);while (llist) { +int wake_flags =0 ; + p = llist_entry(llist, struct task_struct, wake_entry); llist =llist_next (llist); -/* -* See ttwu_queue(); we only call
ttwu_queue_remote()whenkernel/sched/core.c +8
-4-* its a x-cpu wakeup. -*/ -ttwu_do_activate (rq, p,WF_MIGRATED , cookie); + +if (p->sched_remote_wakeup) + wake_flags =WF_MIGRATED ; + +ttwu_do_activate (rq, p, wake_flags, cookie); }lockdep_unpin_lock (&rq->lock, cookie);@@ -1819,10 +1821,12 @@ void scheduler_ipi(void)irq_exit (); } -static void ttwu_queue_remote (struct task_struct *p,int cpu) +static void ttwu_queue_remote (struct task_struct *p,int cpu,int wake_flags) {struct rq *rq =cpu_rq (cpu); + p->sched_remote_wakeup = !!(wake_flags &WF_MIGRATED ); +if (llist_add (&p->wake_entry, &cpu_rq (cpu)->wake_list)) {if (!set_nr_if_polling (rq->idle))smp_send_reschedule(cpu);kernel/sched/core.c +1
-1@@ -1869,7 +1873,7 @@ static void ttwu_queue(struct task_struct *p, int cpu, int wake_flags)#if defined(CONFIG_SMP )if (sched_feat (TTWU_QUEUE ) && !cpus_share_cache (smp_processor_id (), cpu)) {sched_clock_cpu (cpu);/* sync clocks x-cpu */ -ttwu_queue_remote (p, cpu); +ttwu_queue_remote (p, cpu, wake_flags);return ;}#endif
Signature · 2 lines
Regards, Wanpeng Li
Re: [patch] sched/fair: Move se->vruntime normalization state into struct sched_entity
Quoted 19 lines · Wanpeng Li
2016-05-23 17:40 GMT+08:00 Mike Galbraith <[email protected]>:
Quoted 18 lines · Peter Zijlstra
Quoted 17 lines · Mike Galbraith
Quoted 15 lines · Mike Galbraith
Quoted 7 lines · Mike Galbraith
Quoted 6 lines
Wakees that were not migrated/normalized eat an unwanted
min_vruntime,
and likely take a size XXL latency hit. Big box running master bled
profusely under heavy load until I turnedTTWU_QUEUEoff.May as well make it official and against master.today. Fly or die
little patchlet.sched/fair: Move
se->vruntimenormalization state into structsched_entity
Quoted 8 lines
Quoted 6 lines
Quoted 1 line
Does this work?
Yup, bugs--. Kinda funny, I considered ~this way first, but thought
you'd not that approach.. dang, got it back-assward ;-)Nicer this one.
Well, the wakeup is a remote wakeup whether the flag is set or not, so in that regard it's not _squeaky_ clean, but is dinky, works (yay).. and doesn't invent helpers with funny names vs what they actually do.
-Mike
Peter Zijlstra
maintainerRe: [patch] sched/fair: Move se->vruntime normalization state into struct sched_entity
In reply to Mike GalbraithQuoted 2 lines · Mike Galbraith
Yup, bugs--. Kinda funny, I considered ~this way first, but thought you'd not that approach.. dang, got it back-assward ;-)
Hehe, so the new flag is in a word we've already written to on this path and it avoids growing the structure (by an undefined number of bytes, see gripes about sizeof(bool)).
I am thinking of doing the thing you did for a debug aid -- then again; if the Google guys would finally get the global vruntime patches sorted, we can go and kill all this code.
tip-bot for Peter Zijlstra
merge bot[tip:sched/urgent] sched/core: Fix remote wakeups
In reply to Peter Zijlstrasched/core: Fix remote wakeups
Commit-ID: b7e7ade34e6188bee2e3b0d42b51d25137d9e2a5 Gitweb: http://git.kernel.org/tip/b7e7ade34e6188bee2e3b0d42b51d25137d9e2a5 Author: Peter Zijlstra <[email protected]> AuthorDate: Mon, 23 May 2016 11:19:07 +0200 Committer: Ingo Molnar <[email protected]> CommitDate: Wed, 25 May 2016 08:35:18 +0200
sched/core: Fix remote wakeups
Commit:
b5179ac70de8 ("sched/fair: Prepare to fix fairness problems on migration")
... introduced a bug: Mike Galbraith found that it introduced a performance regression, while Paul E. McKenney reported lost wakeups and bisected it to this commit.
The reason is that I mis-read ttwu_queue() such that I assumed any wakeup that got a remote queue must have had the task migrated.
Since this is not so; we need to transfer this information between queueing the wakeup and actually doing the wakeup. Use a new task_struct::sched_flag for this, we already write to sched_contributes_to_load in the wakeup path so this is a hot and modified cacheline.
--- include/linux/sched.h | 1 + kernel/sched/core.c | 18 +++++++++++------- 2 files changed, 12 insertions(+), 7 deletions(-)
include/linux/sched.h +1 -0
@@ -1533,6 +1533,7 @@ struct task_struct { unsigned sched_reset_on_fork:1; unsigned sched_contributes_to_load:1; unsigned sched_migrated:1; + unsigned sched_remote_wakeup:1; unsigned :0; /* force alignment to the next boundary *//* unserialized, strictly 'current' */
kernel/sched/core.c +11 -7
@@ -1768,13 +1768,15 @@ void sched_ttwu_pending(void) cookie =lockdep_pin_lock (&rq->lock);while (llist) { +int wake_flags =0 ; + p = llist_entry(llist, struct task_struct, wake_entry); llist =llist_next (llist); -/* -* See ttwu_queue(); we only call ttwu_queue_remote() when -* its a x-cpu wakeup. -*/ -ttwu_do_activate (rq, p,WF_MIGRATED , cookie); + +if (p->sched_remote_wakeup) + wake_flags =WF_MIGRATED ; + +ttwu_do_activate (rq, p, wake_flags, cookie); }lockdep_unpin_lock (&rq->lock, cookie);
@@ -1819,10 +1821,12 @@ void scheduler_ipi(void)irq_exit (); } -static void ttwu_queue_remote (struct task_struct *p,int cpu) +static void ttwu_queue_remote (struct task_struct *p,int cpu,int wake_flags) {struct rq *rq =cpu_rq (cpu); + p->sched_remote_wakeup = !!(wake_flags &WF_MIGRATED ); +if (llist_add (&p->wake_entry, &cpu_rq (cpu)->wake_list)) {if (!set_nr_if_polling (rq->idle))smp_send_reschedule (cpu);
@@ -1869,7 +1873,7 @@ static void ttwu_queue(struct task_struct *p, int cpu, int wake_flags)#if defined(CONFIG_SMP )if (sched_feat (TTWU_QUEUE ) && !cpus_share_cache (smp_processor_id (), cpu)) {sched_clock_cpu (cpu);/* sync clocks x-cpu */ -ttwu_queue_remote (p, cpu); +ttwu_queue_remote (p, cpu, wake_flags);return ; }#endif
Re: [PATCH 2/3] sched,fair: Fix local starvation
In reply to Mike Galbraith2016-05-21 22:04 GMT+08:00 Mike Galbraith <[email protected]>:
Quoted 8 lines · Peter Zijlstra
(Evolution authors must either not do patch review, or use some other mailer. Squint hard, this crud really is your patch;)
Quoted 3 lines
kernel/sched/core.c +0
-0
Quoted 12 lines
kernel/sched/core.c void sched_ttwu_pending(void) · line 1777
Quoted 10 lines
kernel/sched/core.c +5
-1@@ -1762,7 +1770,11 @@ void sched_ttwu_pending(void) > > while (llist) { > > > p = llist_entry(llist, struct task_struct, wake_entry); > > > llist = llist_next(llist); -> > > ttwu_do_activate(rq, p, 0, cookie); +> > > /* +> > > * See ttwu_queue(); we only call ttwu_queue_remote() when +> > > * its a x-cpu wakeup. +> > > */ +> > > ttwu_do_activate(rq, p, WF_MIGRATED, cookie);Wakees that were not migrated/normalized eat an unwanted
min_vruntime,
Why there were wakees queued by twu_queue_remote() not migrated?
Regards,
Wanpeng Li
Re: [PATCH 2/3] sched,fair: Fix local starvation
Quoted 22 lines · Wanpeng Li
2016-05-21 22:04 GMT+08:00 Mike Galbraith <[email protected]>:
Quoted 8 lines · Peter Zijlstra
(Evolution authors must either not do patch review, or use some other mailer. Squint hard, this crud really is your patch;)
Quoted 3 lines
kernel/sched/core.c +0
-0Quoted 12 lines
kernel/sched/core.c void sched_ttwu_pending(void) · line 1777
Quoted 10 lines
kernel/sched/core.c +5
-1@@ -1762,7 +1770,11 @@ void sched_ttwu_pending(void) > > while (llist) { > > > p = llist_entry(llist, struct task_struct, wake_entry); > > > llist = llist_next(llist); -> > > ttwu_do_activate(rq, p, 0, cookie); +> > > /* +> > > * See ttwu_queue(); we only call ttwu_queue_remote() when +> > > * its a x-cpu wakeup. +> > > */ +> > > ttwu_do_activate(rq, p, WF_MIGRATED, cookie);Wakees that were not migrated/normalized eat an unwanted
min_vruntime,
Quoted 1 line
Why there were wakees queued by
twu_queue_remote()not migrated?
Queuing to a remote cache domain implies x-cpu wakeup, but does not imply migration.
-Mike
Re: [PATCH 2/3] sched,fair: Fix local starvation
2016-05-22 15:15 GMT+08:00 Mike Galbraith <[email protected]>:
Quoted 23 lines · Wanpeng Li
Quoted 22 lines
2016-05-21 22:04 GMT+08:00 Mike Galbraith <[email protected]>:
Quoted 20 lines · Peter Zijlstra
(Evolution authors must either not do patch review, or use some other mailer. Squint hard, this crud really is your patch;)
kernel/sched/core.c void sched_ttwu_pending(void) · line 1777
Quoted 13 lines
kernel/sched/core.c +5
-1@@ -1762,7 +1770,11 @@ void sched_ttwu_pending(void) > > while (llist) { > > > p = llist_entry(llist, struct task_struct, wake_entry); > > > llist = llist_next(llist); -> > > ttwu_do_activate(rq, p, 0, cookie); +> > > /* +> > > * See ttwu_queue(); we only call ttwu_queue_remote() when +> > > * its a x-cpu wakeup. +> > > */ +> > > ttwu_do_activate(rq, p, WF_MIGRATED, cookie);Wakees that were not migrated/normalized eat an unwanted
min_vruntime,
Quoted 4 lines
Quoted 1 line
Why there were wakees queued by
twu_queue_remote()not migrated?Queuing to a remote cache domain implies x-cpu wakeup, but does not imply migration.
What's the meaning of 'x-cpu wakeup'? ;-)
Regards,
Wanpeng Li
Re: [PATCH 2/3] sched,fair: Fix local starvation
Quoted 1 line · Wanpeng Li
What's the meaning of 'x-cpu wakeup'? ;-)
Generally, cross CPU, as in waker/wakee reside on different CPUs, but in this case, it's cross socket wakeup.
-Mike
Re: [PATCH 2/3] sched,fair: Fix local starvation
2016-05-22 15:32 GMT+08:00 Mike Galbraith <[email protected]>:
Quoted 6 lines · Wanpeng Li
Quoted 2 lines
What's the meaning of 'x-cpu wakeup'? ;-)
Generally, cross CPU, as in waker/wakee reside on different CPUs, but in this case, it's cross socket wakeup.
Do you mean wakeup wakees on remote socket don't imply migration/normalized, why?
Regards,
Wanpeng Li
Re: [PATCH 2/3] sched,fair: Fix local starvation
Quoted 11 lines · Wanpeng Li
2016-05-22 15:32 GMT+08:00 Mike Galbraith <[email protected]>:
Quoted 7 lines · Wanpeng Li
Quoted 2 lines
What's the meaning of 'x-cpu wakeup'? ;-)
Generally, cross CPU, as in waker/wakee reside on different CPUs, but
in this case, it's cross socket wakeup.Do you mean wakeup wakees on remote socket don't imply migration/normalized, why?
Because the wakee is NOT necessarily migrated simply because it lives in some remote cache domain. It was a simple but nasty booboo.
ttwu():
cpu = select_task_rq(p, p->wake_cpu, SD_BALANCE_WAKE, wake_flags);
if (task_cpu(p) != cpu) {
wake_flags |= WF_MIGRATED;
set_task_cpu(p, cpu);set_task_cpu():
if (task_cpu(p) != new_cpu) {
if (p->sched_class->migrate_task_rq)
p->sched_class->migrate_task_rq(p);
^^^^^^^^^^^^^^^^^^migrate_task_rq_fair() normalizes wakee, those wakees that did not migrate have NOT been normalized, leaving two flavors of wakee on the wake_list, with no discriminator. Store class information internally, and the x-socket information disconnect evaporates.
-Mike
Re: [PATCH 2/3] sched,fair: Fix local starvation
2016-05-22 16:04 GMT+08:00 Mike Galbraith <[email protected]>:
Quoted 28 lines · Wanpeng Li
Quoted 11 lines
2016-05-22 15:32 GMT+08:00 Mike Galbraith <[email protected]>:
Quoted 7 lines · Wanpeng Li
Quoted 2 lines
What's the meaning of 'x-cpu wakeup'? ;-)
Generally, cross CPU, as in waker/wakee reside on different CPUs, but
in this case, it's cross socket wakeup.Do you mean wakeup wakees on remote socket don't imply migration/normalized, why?
Because the wakee is NOT necessarily migrated simply because it lives in some remote cache domain. It was a simple but nasty booboo.
ttwu():cpu = select_task_rq(p, p->wake_cpu, SD_BALANCE_WAKE, wake_flags); if (task_cpu(p) != cpu) { wake_flags |= WF_MIGRATED; set_task_cpu(p, cpu);
set_task_cpu():if (task_cpu(p) != new_cpu) { if (p->sched_class->migrate_task_rq) p->sched_class->migrate_task_rq(p); ^^^^^^^^^^^^^^^^^^
Quoted 4 lines
migrate_task_rq_fair()normalizes wakee, those wakees that did not migrate have NOT been normalized, leaving two flavors of wakee on thewake_list, with no discriminator. Store class information internally, and the x-socket information disconnect evaporates.
Do all wakees live on some remote cache domain will not migrate or just the ones which can't find an suitable cpu in current local socket(failed in select_task_rq())?
Regards,
Wanpeng Li
Re: [PATCH 2/3] sched,fair: Fix local starvation
Quoted 3 lines · Wanpeng Li
Do all wakees live on some remote cache domain will not migrate or just the ones which can't find an suitable cpu in current local
socket(failed in select_task_rq())?
?? The picture I drew already answered that.
-Mike
Re: [PATCH 2/3] sched,fair: Fix local starvation
2016-05-22 16:39 GMT+08:00 Mike Galbraith <[email protected]>:
Quoted 7 lines · Wanpeng Li
Quoted 4 lines
Do all wakees live on some remote cache domain will not migrate or just the ones which can't find an suitable cpu in current local
socket(failed in select_task_rq())??? The picture I drew already answered that.
I see, thanks for your great explanation. :-)
Regards,
Wanpeng Li
Peter Zijlstra
maintainerPATCH 3/3 sched: Kill sched_class::task_waking
In reply to Peter ZijlstraWith sched_class::task_waking being called only when we do set_task_cpu(), we can make sched_class::migrate_task_rq() do the work and eliminate sched_class::task_waking entirely.
--- kernel/sched/core.c | 9 ------- kernel/sched/fair.c | 58 ++++++++++++++++++++++++--------------------------- kernel/sched/sched.h | 7 ++---- 3 files changed, 32 insertions(+), 42 deletions(-)
kernel/sched/core.c +1 -8
@@ -1717,11 +1717,8 @@ ttwu_do_activate(struct rq *rq, struct tif (p->sched_contributes_to_load) rq->nr_uninterruptible--; -/* -* If we migrated; we must have called sched_class::task_waking(). -*/ if (wake_flags &WF_MIGRATED ) - en_flags |=ENQUEUE_WAKING ; + en_flags |=ENQUEUE_MIGRATED ;#endif ttwu_activate (rq, p, en_flags);
@@ -2049,10 +2046,6 @@ try_to_wake_up(struct task_struct *p, un cpu =select_task_rq (p, p->wake_cpu,SD_BALANCE_WAKE , wake_flags);if (task_cpu (p) != cpu) { wake_flags |=WF_MIGRATED ; - -if (p->sched_class->task_waking) - p->sched_class->task_waking (p); -set_task_cpu (p, cpu); }#endif /* CONFIG_SMP */
kernel/sched/fair.c +28 -30
88 lines not on this page · raw message
kernel/sched/sched.h +3 -4
@@ -1164,7 +1164,7 @@ extern const u32 sched_prio_to_wmult[40]* * ENQUEUE_HEAD - place at front of runqueue (tail if not specified) * ENQUEUE_REPLENISH - CBS (replenish runtime and postpone deadline) -* ENQUEUE_WAKING - sched_class::task_waking was called +* ENQUEUE_MIGRATED - the task was migrated during wakeup * */
@@ -1179,9 +1179,9 @@ extern const u32 sched_prio_to_wmult[40]#define ENQUEUE_HEAD 0x08#define ENQUEUE_REPLENISH 0x10#ifdef CONFIG_SMP -#define ENQUEUE_WAKING 0x20 +#define ENQUEUE_MIGRATED 0x20#else -#define ENQUEUE_WAKING 0x00 +#define ENQUEUE_MIGRATED 0x00#endif #define RETRY_TASK ((void *)-1UL)
@@ -1213,7 +1213,6 @@ struct sched_class {int (*select_task_rq)(struct task_struct *p,int task_cpu,int sd_flag,int flags);void (*migrate_task_rq)(struct task_struct *p); -void (*task_waking) (struct task_struct *task);void (*task_woken) (struct rq *this_rq,struct task_struct *task); void (*set_cpus_allowed)(struct task_struct *p,
Quoted 1 line · Peter Zijlstra
Mike, Pavan, could you guys please confirm?
Plugging the series into master.today, all seems peachy on my end.
-Mike
Hi Peter,
Quoted 9 lines · Peter Zijlstra
A recent commit caused an interactivity/starvation issue because we wrecked rq local wakeup preemption.
These patches rectify this while also (hopefully) keeping the problem that led to the fault patch fixed.
Mike, Pavan, could you guys please confirm?
I tested with your latest patches. The original problem (migrated task's vruntime falling
beyond the min_vruntime) is not reproducible.
Thanks,
Pavan
Signature · 3 lines
Qualcomm India Private Limited, on behalf of Qualcomm Innovation Center, Inc. Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project
Quoted 7 lines · Peter Zijlstra
A recent commit caused an interactivity/starvation issue because we wrecked rq local wakeup preemption.
These patches rectify this while also (hopefully) keeping the problem that led to the fault patch fixed.
Mike, Pavan, could you guys please confirm?
FWIW, I took a quick look over these patches and they made sense to me. (I appreciate the comment block above enqueue_entity())