From: Daisuke Nishimura Date: Thu, 15 Dec 2011 05:36:07 +0000 (+0900) Subject: [PORT FROM R4]sched: Fix cgroup movement of newly created process X-Git-Tag: 2.1b_release~564 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=f973e3eb0faf72b03ed52cf1aedf2ca7c19dd5ec;p=kernel%2Fkernel-mfld-blackbay.git [PORT FROM R4]sched: Fix cgroup movement of newly created process BZ: 42195 (backport of upstream commit 7ceff013, merged in 3.3-rc1) There is a small race between do_fork() and sched_move_task(), which is trying to move the child. do_fork() sched_move_task() --------------------------------+--------------------------------- copy_process() sched_fork() task_fork_fair() -> vruntime of the child is initialized based on that of the parent. -> we can see the child in "tasks" file now. task_rq_lock() task_move_group_fair() -> child.se.vruntime -= (old)cfs_rq->min_vruntime += (new)cfs_rq->min_vruntime task_rq_unlock() wake_up_new_task() ... enqueue_entity() child.se.vruntime += cfs_rq->min_vruntime As a result, vruntime of the child becomes far bigger than min_vruntime, if (new)cfs_rq->min_vruntime >> (old)cfs_rq->min_vruntime. This patch fixes this problem by just ignoring such process in task_move_group_fair(), because the vruntime has already been normalized in task_fork_fair(). Signed-off-by: Daisuke Nishimura Signed-off-by: Peter Zijlstra Cc: Tejun Heo Link: http://lkml.kernel.org/r/20111215143607.2ee12c5d.nishimura@mxp.nes.nec.co.jp Signed-off-by: Ingo Molnar Change-Id: I43b700487d934ede48fa95fe9942176d740c24f1 Orig-Change-Id: I2c9db9352e9ce33a62880192f798687280bd02ad Signed-off-by: German Monroy Reviewed-on: http://android.intel.com:8080/54408 Reviewed-by: Yang, Fei Tested-by: Ng, Cheon-woei Reviewed-by: buildbot Tested-by: buildbot --- diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c index 983c5ae..15eca5d 100644 --- a/kernel/sched_fair.c +++ b/kernel/sched_fair.c @@ -4262,6 +4262,19 @@ static void task_move_group_fair(struct task_struct *p, int on_rq) * to another cgroup's rq. This does somewhat interfere with the * fair sleeper stuff for the first placement, but who cares. */ + /* + * When !on_rq, vruntime of the task has usually NOT been normalized. + * But there are some cases where it has already been normalized: + * + * - Moving a forked child which is waiting for being woken up by + * wake_up_new_task(). + * + * To prevent boost or penalty in the new cfs_rq caused by delta + * min_vruntime between the two cfs_rqs, we skip vruntime adjustment. + */ + if (!on_rq && !p->se.sum_exec_runtime) + on_rq = 1; + if (!on_rq) p->se.vruntime -= cfs_rq_of(&p->se)->min_vruntime; set_task_rq(p, task_cpu(p));