From: Peter Zijlstra <peterz@infradead.org>
To: umgwanakikbuti@gmail.com, mingo@elte.hu
Cc: ktkhai@parallels.com, rostedt@goodmis.org, tglx@linutronix.de,
juri.lelli@gmail.com, pang.xunlei@linaro.org, oleg@redhat.com,
wanpeng.li@linux.intel.com, linux-kernel@vger.kernel.org,
peterz@infradead.org
Subject: [PATCH 11/14] sched: Streamline the task migration locking a little
Date: Fri, 05 Jun 2015 10:48:47 +0200 [thread overview]
Message-ID: <20150605085205.981342378@infradead.org> (raw)
In-Reply-To: <20150605084836.364306429@infradead.org>
[-- Attachment #1: peterz-sched-migrate-locking.patch --]
[-- Type: text/plain, Size: 4633 bytes --]
The whole migrate_task{,s}() locking seems a little shaky, there's a
lot of dropping an require happening. Pull the locking up into the
callers as far as possible to streamline the lot.
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
---
kernel/sched/core.c | 76 +++++++++++++++++++++++-----------------------------
1 file changed, 34 insertions(+), 42 deletions(-)
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -1065,10 +1065,8 @@ void check_preempt_curr(struct rq *rq, s
*
* Returns (locked) new rq. Old rq's lock is released.
*/
-static struct rq *move_queued_task(struct task_struct *p, int new_cpu)
+static struct rq *move_queued_task(struct rq *rq, struct task_struct *p, int new_cpu)
{
- struct rq *rq = task_rq(p);
-
lockdep_assert_held(&rq->lock);
dequeue_task(rq, p, 0);
@@ -1100,41 +1098,19 @@ struct migration_arg {
*
* So we race with normal scheduler movements, but that's OK, as long
* as the task is no longer on this CPU.
- *
- * Returns non-zero if task was successfully migrated.
*/
-static int __migrate_task(struct task_struct *p, int src_cpu, int dest_cpu)
+static struct rq *__migrate_task(struct rq *rq, struct task_struct *p, int dest_cpu)
{
- struct rq *rq;
- int ret = 0;
-
if (unlikely(!cpu_active(dest_cpu)))
- return ret;
-
- rq = cpu_rq(src_cpu);
-
- raw_spin_lock(&p->pi_lock);
- raw_spin_lock(&rq->lock);
- /* Already moved. */
- if (task_cpu(p) != src_cpu)
- goto done;
+ return rq;
/* Affinity changed (again). */
if (!cpumask_test_cpu(dest_cpu, tsk_cpus_allowed(p)))
- goto fail;
+ return rq;
- /*
- * If we're not on a rq, the next wake-up will ensure we're
- * placed properly.
- */
- if (task_on_rq_queued(p))
- rq = move_queued_task(p, dest_cpu);
-done:
- ret = 1;
-fail:
- raw_spin_unlock(&rq->lock);
- raw_spin_unlock(&p->pi_lock);
- return ret;
+ rq = move_queued_task(rq, p, dest_cpu);
+
+ return rq;
}
/*
@@ -1145,6 +1121,8 @@ static int __migrate_task(struct task_st
static int migration_cpu_stop(void *data)
{
struct migration_arg *arg = data;
+ struct task_struct *p = arg->task;
+ struct rq *rq = this_rq();
/*
* The original target cpu might have gone down and we might
@@ -1157,7 +1135,19 @@ static int migration_cpu_stop(void *data
* during wakeups, see set_cpus_allowed_ptr()'s TASK_WAKING test.
*/
sched_ttwu_pending();
- __migrate_task(arg->task, raw_smp_processor_id(), arg->dest_cpu);
+
+ raw_spin_lock(&p->pi_lock);
+ raw_spin_lock(&rq->lock);
+ /*
+ * If task_rq(p) != rq, it cannot be migrated here, because we're
+ * holding rq->lock, if p->on_rq == 0 it cannot get enqueued because
+ * we're holding p->pi_lock.
+ */
+ if (task_rq(p) == rq && task_on_rq_queued(p))
+ rq = __migrate_task(rq, p, arg->dest_cpu);
+ raw_spin_unlock(&rq->lock);
+ raw_spin_unlock(&p->pi_lock);
+
local_irq_enable();
return 0;
}
@@ -1212,7 +1202,7 @@ int set_cpus_allowed_ptr(struct task_str
tlb_migrate_finish(p->mm);
return 0;
} else if (task_on_rq_queued(p))
- rq = move_queued_task(p, dest_cpu);
+ rq = move_queued_task(rq, p, dest_cpu);
out:
task_rq_unlock(rq, p, &flags);
@@ -5049,9 +5039,9 @@ static struct task_struct fake_task = {
* there's no concurrency possible, we hold the required locks anyway
* because of lock validation efforts.
*/
-static void migrate_tasks(unsigned int dead_cpu)
+static void migrate_tasks(struct rq *dead_rq)
{
- struct rq *rq = cpu_rq(dead_cpu);
+ struct rq *rq = dead_rq;
struct task_struct *next, *stop = rq->stop;
int dest_cpu;
@@ -5073,7 +5063,7 @@ static void migrate_tasks(unsigned int d
*/
update_rq_clock(rq);
- for ( ; ; ) {
+ for (;;) {
/*
* There's this thread running, bail when that's the only
* remaining thread.
@@ -5086,12 +5076,14 @@ static void migrate_tasks(unsigned int d
next->sched_class->put_prev_task(rq, next);
/* Find suitable destination for @next, with force if needed. */
- dest_cpu = select_fallback_rq(dead_cpu, next);
- raw_spin_unlock(&rq->lock);
-
- __migrate_task(next, dead_cpu, dest_cpu);
+ dest_cpu = select_fallback_rq(dead_rq->cpu, next);
- raw_spin_lock(&rq->lock);
+ rq = __migrate_task(rq, next, dest_cpu);
+ if (rq != dead_rq) {
+ raw_spin_unlock(&rq->lock);
+ rq = dead_rq;
+ raw_spin_lock(&rq->lock);
+ }
}
rq->stop = stop;
@@ -5343,7 +5335,7 @@ migration_call(struct notifier_block *nf
BUG_ON(!cpumask_test_cpu(cpu, rq->rd->span));
set_rq_offline(rq);
}
- migrate_tasks(cpu);
+ migrate_tasks(rq);
BUG_ON(rq->nr_running != 1); /* the migration thread */
raw_spin_unlock_irqrestore(&rq->lock, flags);
break;
next prev parent reply other threads:[~2015-06-05 8:59 UTC|newest]
Thread overview: 55+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-06-05 8:48 [PATCH 00/14] sched: balance callbacks Peter Zijlstra
2015-06-05 8:48 ` [PATCH 01/14] sched: Replace post_schedule with a balance callback list Peter Zijlstra
2015-06-05 8:48 ` [PATCH 02/14] sched: Use replace normalize_task() with __sched_setscheduler() Peter Zijlstra
2015-06-05 8:48 ` [PATCH 03/14] sched: Allow balance callbacks for check_class_changed() Peter Zijlstra
2015-06-05 8:48 ` [PATCH 04/14] sched,rt: Remove return value from pull_rt_task() Peter Zijlstra
2015-06-05 8:48 ` [PATCH 05/14] sched,rt: Convert switched_{from,to}_rt() / prio_changed_rt() to balance callbacks Peter Zijlstra
2015-06-05 8:48 ` [PATCH 06/14] sched,dl: Remove return value from pull_dl_task() Peter Zijlstra
2015-06-05 8:48 ` [PATCH 07/14] sched,dl: Convert switched_{from,to}_dl() / prio_changed_dl() to balance callbacks Peter Zijlstra
2015-06-05 8:48 ` [PATCH 08/14] hrtimer: Allow hrtimer::function() to free the timer Peter Zijlstra
2015-06-05 9:48 ` Thomas Gleixner
2015-06-07 19:43 ` Oleg Nesterov
2015-06-07 22:33 ` Oleg Nesterov
2015-06-07 22:56 ` Oleg Nesterov
2015-06-08 8:06 ` Thomas Gleixner
2015-06-08 9:14 ` Peter Zijlstra
2015-06-08 10:55 ` Peter Zijlstra
2015-06-08 12:42 ` Peter Zijlstra
2015-06-08 14:27 ` Oleg Nesterov
2015-06-08 14:42 ` Peter Zijlstra
2015-06-08 15:49 ` Oleg Nesterov
2015-06-08 15:10 ` Peter Zijlstra
2015-06-08 15:16 ` Oleg Nesterov
2015-06-09 21:33 ` Oleg Nesterov
2015-06-09 21:39 ` Oleg Nesterov
2015-06-10 6:55 ` Peter Zijlstra
2015-06-10 7:46 ` Kirill Tkhai
2015-06-10 16:04 ` Oleg Nesterov
2015-06-11 7:31 ` Peter Zijlstra
2015-06-11 16:25 ` Kirill Tkhai
2015-06-10 15:49 ` Oleg Nesterov
2015-06-10 22:37 ` Peter Zijlstra
2015-06-08 14:03 ` Oleg Nesterov
2015-06-08 14:17 ` Peter Zijlstra
2015-06-08 15:10 ` [PATCH 0/3] hrtimer: HRTIMER_STATE_ fixes Oleg Nesterov
2015-06-08 15:11 ` [PATCH 2/3] hrtimer: turn newstate arg of __remove_hrtimer() into clear_enqueued Oleg Nesterov
2015-06-08 15:11 ` [PATCH 3/3] hrtimer: fix the __hrtimer_start_range_ns() race with hrtimer_active() Oleg Nesterov
2015-06-08 15:12 ` [PATCH 1/3] hrtimer: kill HRTIMER_STATE_MIGRATE, fix the race with hrtimer_is_queued() Oleg Nesterov
2015-06-08 15:35 ` [PATCH 0/3] hrtimer: HRTIMER_STATE_ fixes Peter Zijlstra
2015-06-08 15:56 ` Oleg Nesterov
2015-06-08 17:11 ` Thomas Gleixner
2015-06-08 19:08 ` Peter Zijlstra
2015-06-08 20:52 ` Oleg Nesterov
2015-06-08 15:10 ` [PATCH 1/3] hrtimer: kill HRTIMER_STATE_MIGRATE, fix the race with hrtimer_is_queued() Oleg Nesterov
2015-06-08 15:13 ` Oleg Nesterov
2015-06-05 8:48 ` [PATCH 09/14] sched,dl: Fix sched class hopping CBS hole Peter Zijlstra
2015-06-05 8:48 ` [PATCH 10/14] sched: Move code around Peter Zijlstra
2015-06-05 8:48 ` Peter Zijlstra [this message]
2015-06-05 8:48 ` [PATCH 12/14] lockdep: Simplify lock_release() Peter Zijlstra
2015-06-05 8:48 ` [PATCH 13/14] lockdep: Implement lock pinning Peter Zijlstra
2015-06-05 9:55 ` Ingo Molnar
2015-06-11 11:37 ` Peter Zijlstra
2015-06-05 8:48 ` [PATCH 14/14] sched,lockdep: Employ " Peter Zijlstra
2015-06-05 9:57 ` Ingo Molnar
2015-06-05 11:03 ` Peter Zijlstra
2015-06-05 11:24 ` Ingo Molnar
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20150605085205.981342378@infradead.org \
--to=peterz@infradead.org \
--cc=juri.lelli@gmail.com \
--cc=ktkhai@parallels.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@elte.hu \
--cc=oleg@redhat.com \
--cc=pang.xunlei@linaro.org \
--cc=rostedt@goodmis.org \
--cc=tglx@linutronix.de \
--cc=umgwanakikbuti@gmail.com \
--cc=wanpeng.li@linux.intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®