diff options
author | Kirill Tkhai <ktkhai@parallels.com> | 2014-08-20 05:47:50 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2014-08-20 08:53:02 -0400 |
commit | a1e01829796aa7a993e28ffd7fee5c8d525be175 (patch) | |
tree | 9ae2970e5c0dc25972bf3d7663d997ab8808ddad /kernel/sched/core.c | |
parent | cca26e8009d1939a6a5bf0200d276fa26f03e536 (diff) |
sched: Remove double_rq_lock() from __migrate_task()
Avoid double_rq_lock() and use TASK_ON_RQ_MIGRATING for
__migrate_task(). The advantage is (obviously) not holding two
rq->lock's at the same time and thereby increasing parallelism.
The important point to note is that because we acquire dst->lock
immediately after releasing src->lock the potential wait time of
task_rq_lock() callers on TASK_ON_RQ_MIGRATING is not longer
than it would have been in the double rq lock scenario.
Signed-off-by: Kirill Tkhai <ktkhai@parallels.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Paul Turner <pjt@google.com>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Mike Galbraith <umgwanakikbuti@gmail.com>
Cc: Kirill Tkhai <tkhai@yandex.ru>
Cc: Tim Chen <tim.c.chen@linux.intel.com>
Cc: Nicolas Pitre <nicolas.pitre@linaro.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Link: http://lkml.kernel.org/r/1408528070.23412.89.camel@tkhai
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'kernel/sched/core.c')
-rw-r--r-- | kernel/sched/core.c | 23 |
1 files changed, 15 insertions, 8 deletions
diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 71b836034912..a773c919d88d 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c | |||
@@ -4679,20 +4679,20 @@ EXPORT_SYMBOL_GPL(set_cpus_allowed_ptr); | |||
4679 | */ | 4679 | */ |
4680 | static int __migrate_task(struct task_struct *p, int src_cpu, int dest_cpu) | 4680 | static int __migrate_task(struct task_struct *p, int src_cpu, int dest_cpu) |
4681 | { | 4681 | { |
4682 | struct rq *rq_dest, *rq_src; | 4682 | struct rq *rq; |
4683 | int ret = 0; | 4683 | int ret = 0; |
4684 | 4684 | ||
4685 | if (unlikely(!cpu_active(dest_cpu))) | 4685 | if (unlikely(!cpu_active(dest_cpu))) |
4686 | return ret; | 4686 | return ret; |
4687 | 4687 | ||
4688 | rq_src = cpu_rq(src_cpu); | 4688 | rq = cpu_rq(src_cpu); |
4689 | rq_dest = cpu_rq(dest_cpu); | ||
4690 | 4689 | ||
4691 | raw_spin_lock(&p->pi_lock); | 4690 | raw_spin_lock(&p->pi_lock); |
4692 | double_rq_lock(rq_src, rq_dest); | 4691 | raw_spin_lock(&rq->lock); |
4693 | /* Already moved. */ | 4692 | /* Already moved. */ |
4694 | if (task_cpu(p) != src_cpu) | 4693 | if (task_cpu(p) != src_cpu) |
4695 | goto done; | 4694 | goto done; |
4695 | |||
4696 | /* Affinity changed (again). */ | 4696 | /* Affinity changed (again). */ |
4697 | if (!cpumask_test_cpu(dest_cpu, tsk_cpus_allowed(p))) | 4697 | if (!cpumask_test_cpu(dest_cpu, tsk_cpus_allowed(p))) |
4698 | goto fail; | 4698 | goto fail; |
@@ -4702,15 +4702,22 @@ static int __migrate_task(struct task_struct *p, int src_cpu, int dest_cpu) | |||
4702 | * placed properly. | 4702 | * placed properly. |
4703 | */ | 4703 | */ |
4704 | if (task_on_rq_queued(p)) { | 4704 | if (task_on_rq_queued(p)) { |
4705 | dequeue_task(rq_src, p, 0); | 4705 | dequeue_task(rq, p, 0); |
4706 | p->on_rq = TASK_ON_RQ_MIGRATING; | ||
4706 | set_task_cpu(p, dest_cpu); | 4707 | set_task_cpu(p, dest_cpu); |
4707 | enqueue_task(rq_dest, p, 0); | 4708 | raw_spin_unlock(&rq->lock); |
4708 | check_preempt_curr(rq_dest, p, 0); | 4709 | |
4710 | rq = cpu_rq(dest_cpu); | ||
4711 | raw_spin_lock(&rq->lock); | ||
4712 | BUG_ON(task_rq(p) != rq); | ||
4713 | p->on_rq = TASK_ON_RQ_QUEUED; | ||
4714 | enqueue_task(rq, p, 0); | ||
4715 | check_preempt_curr(rq, p, 0); | ||
4709 | } | 4716 | } |
4710 | done: | 4717 | done: |
4711 | ret = 1; | 4718 | ret = 1; |
4712 | fail: | 4719 | fail: |
4713 | double_rq_unlock(rq_src, rq_dest); | 4720 | raw_spin_unlock(&rq->lock); |
4714 | raw_spin_unlock(&p->pi_lock); | 4721 | raw_spin_unlock(&p->pi_lock); |
4715 | return ret; | 4722 | return ret; |
4716 | } | 4723 | } |