aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/sched.c
diff options
context:
space:
mode:
authorPeter Zijlstra <a.p.zijlstra@chello.nl>2009-12-16 12:04:41 -0500
committerIngo Molnar <mingo@elte.hu>2009-12-16 13:01:58 -0500
commit88ec22d3edb72b261f8628226cd543589a6d5e1b (patch)
treeca547c82ab6adce0b9e29afb6ceddf50cd417d44 /kernel/sched.c
parentefbbd05a595343a413964ad85a2ad359b7b7efbd (diff)
sched: Remove the cfs_rq dependency from set_task_cpu()
In order to remove the cfs_rq dependency from set_task_cpu() we need to ensure the task is cfs_rq invariant for all callsites. The simple approach is to substract cfs_rq->min_vruntime from se->vruntime on dequeue, and add cfs_rq->min_vruntime on enqueue. However, this has the downside of breaking FAIR_SLEEPERS since we loose the old vruntime as we only maintain the relative position. To solve this, we observe that we only migrate runnable tasks, we do this using deactivate_task(.sleep=0) and activate_task(.wakeup=0), therefore we can restrain the min_vruntime invariance to that state. The only other case is wakeup balancing, since we want to maintain the old vruntime we cannot make it relative on dequeue, but since we don't migrate inactive tasks, we can do so right before we activate it again. This is where we need the new pre-wakeup hook, we need to call this while still holding the old rq->lock. We could fold it into ->select_task_rq(), but since that has multiple callsites and would obfuscate the locking requirements, that seems like a fudge. This leaves the fork() case, simply make sure that ->task_fork() leaves the ->vruntime in a relative state. This covers all cases where set_task_cpu() gets called, and ensures it sees a relative vruntime. Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Mike Galbraith <efault@gmx.de> LKML-Reference: <20091216170518.191697025@chello.nl> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel/sched.c')
-rw-r--r--kernel/sched.c6
1 files changed, 1 insertions, 5 deletions
diff --git a/kernel/sched.c b/kernel/sched.c
index 6c571bdd5658..f92ce63edfff 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -2038,8 +2038,6 @@ task_hot(struct task_struct *p, u64 now, struct sched_domain *sd)
2038void set_task_cpu(struct task_struct *p, unsigned int new_cpu) 2038void set_task_cpu(struct task_struct *p, unsigned int new_cpu)
2039{ 2039{
2040 int old_cpu = task_cpu(p); 2040 int old_cpu = task_cpu(p);
2041 struct cfs_rq *old_cfsrq = task_cfs_rq(p),
2042 *new_cfsrq = cpu_cfs_rq(old_cfsrq, new_cpu);
2043 2041
2044#ifdef CONFIG_SCHED_DEBUG 2042#ifdef CONFIG_SCHED_DEBUG
2045 /* 2043 /*
@@ -2056,8 +2054,6 @@ void set_task_cpu(struct task_struct *p, unsigned int new_cpu)
2056 perf_sw_event(PERF_COUNT_SW_CPU_MIGRATIONS, 2054 perf_sw_event(PERF_COUNT_SW_CPU_MIGRATIONS,
2057 1, 1, NULL, 0); 2055 1, 1, NULL, 0);
2058 } 2056 }
2059 p->se.vruntime -= old_cfsrq->min_vruntime -
2060 new_cfsrq->min_vruntime;
2061 2057
2062 __set_task_cpu(p, new_cpu); 2058 __set_task_cpu(p, new_cpu);
2063} 2059}
@@ -10102,7 +10098,7 @@ void sched_move_task(struct task_struct *tsk)
10102 10098
10103#ifdef CONFIG_FAIR_GROUP_SCHED 10099#ifdef CONFIG_FAIR_GROUP_SCHED
10104 if (tsk->sched_class->moved_group) 10100 if (tsk->sched_class->moved_group)
10105 tsk->sched_class->moved_group(tsk); 10101 tsk->sched_class->moved_group(tsk, on_rq);
10106#endif 10102#endif
10107 10103
10108 if (unlikely(running)) 10104 if (unlikely(running))