Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1263963

[PATCH 08/13] hperf_hmp: swap tasks function.

From Arseniy Krasnov <a.krasnov@samsung.com>
Newsgroups linux.kernel
Subject [PATCH 08/13] hperf_hmp: swap tasks function.
Date 2015-11-06 13:10 +0100
Message-ID <qrO0b-4jL-45@gated-at.bofh.it> (permalink)
References <qrO09-4jL-7@gated-at.bofh.it>
Organization linux.* mail to news gateway

Show all headers | View raw


	'swap_tasks' performs migration between current CPU and CPU from another
cluster. It scans two runqueues looking for tasks using 'druntime' metric. When
both tasks are found it pulls task from another cluster, and push task from the
current CPU.

Signed-off-by: Tarek Dakhran <t.dakhran@samsung.com>
Signed-off-by: Sergey Dyasly <s.dyasly@samsung.com>
Signed-off-by: Dmitriy Safonov <d.safonov@partner.samsung.com>
Signed-off-by: Arseniy Krasnov <a.krasnov@samsung.com>
Signed-off-by: Ilya Maximets <i.maximets@samsung.com>
---
 kernel/sched/fair.c  | 100 +++++++++++++++++++++++++++++++++++++++++++++++++++
 kernel/sched/sched.h |   1 +
 2 files changed, 101 insertions(+)

diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index ff05364..028d329 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -7419,6 +7419,106 @@ static unsigned int try_to_move_task(struct task_struct *migrate_task,
 
 	return migrate_runnable_task(migrate_task, destination_cpu);
 }
+
+/**
+ * swap_tasks(): swaps two tasks from different HMP domains
+ * @sd: Current sched domain
+ * @this_cpu: without NO_HZ same as smp_processor_id().
+ *
+ * Returns weight of migrated tasks.
+ */
+static unsigned int swap_tasks(struct sched_domain *sd, int this_cpu)
+{
+	unsigned int ld_moved = 0;
+	int local_stopper = 0;
+	int foreign_stopper = 0;
+	struct rq *local_rq = cpu_rq(this_cpu);
+	struct rq *foreign_rq = NULL;
+	struct task_struct *local_task = NULL;
+	struct task_struct *foreign_task = NULL;
+	unsigned long local_flags;
+
+	local_irq_save(local_flags);
+	foreign_rq = get_unfair_rq(sd, this_cpu);
+
+	if (!foreign_rq) {
+		local_irq_restore(local_flags);
+		return 0;
+	}
+
+	double_lock_balance(foreign_rq, local_rq);
+
+	/* rq's waiting for stopper execution, return */
+	if (foreign_rq->active_balance)
+		goto unlock;
+
+	if (local_rq->active_balance)
+		goto unlock;
+
+	foreign_task = get_migration_candidate(sd, foreign_rq, 0, this_cpu);
+
+	if (!foreign_task)
+		goto unlock;
+
+	/* Get local task for migration */
+	local_task = get_migration_candidate(sd, local_rq, 0, foreign_rq->cpu);
+
+	if (!local_task) {
+		foreign_task->se.migrate_candidate = 0;
+		goto unlock;
+	}
+	/* First try to push local task */
+	ld_moved = try_to_move_task(local_task, foreign_rq->cpu,
+					&local_stopper);
+
+	/* If failed to move, then return, don't try to move foreign task */
+	if (!ld_moved) {
+		local_task->se.migrate_candidate = 0;
+		foreign_task->se.migrate_candidate = 0;
+		goto unlock;
+	}
+
+	/*
+	 * Migration is possible, but task is running,
+	 * so mark rq to run stopper.
+	 */
+	if (local_stopper) {
+		local_rq->push_cpu = foreign_rq->cpu;
+		local_rq->migrate_task = local_task;
+		local_rq->active_balance = 1;
+	}
+
+	/* Now try to pull task from another cpu */
+	ld_moved = try_to_move_task(foreign_task, this_cpu,
+					&foreign_stopper);
+
+	/* Failed to move foreign_task */
+	if (!ld_moved)
+		foreign_task->se.migrate_candidate = 0;
+
+	/* Migration is possible, mark rq to run stopper */
+	if (foreign_stopper) {
+		foreign_rq->push_cpu = this_cpu;
+		foreign_rq->migrate_task = foreign_task;
+		foreign_rq->active_balance = 1;
+	}
+
+unlock:
+	double_rq_unlock(local_rq, foreign_rq);
+	local_irq_restore(local_flags);
+
+	if (local_stopper)
+		stop_one_cpu_nowait(local_rq->cpu,
+				    active_load_balance_cpu_stop, local_rq,
+				    &local_rq->active_balance_work);
+
+	if (foreign_stopper)
+		stop_one_cpu_nowait(foreign_rq->cpu,
+				    active_load_balance_cpu_stop, foreign_rq,
+				    &foreign_rq->active_balance_work);
+
+	return ld_moved;
+}
 #endif /* CONFIG_HPERF_HMP */
 
 /*
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index 94828dc..47e9605 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -598,6 +598,7 @@ struct rq {
 	unsigned long nr_uninterruptible;
 
 #ifdef CONFIG_HPERF_HMP
+	struct task_struct *migrate_task; /* task from this rq for migration */
 	/* shows the amount of accumulated unfairness by tasks of this rq */
 	long druntime_sum;
 	unsigned int nr_hmp_tasks;
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Back to linux.kernel | Previous | Next — Previous in thread | Next in thread | Find similar | Unroll thread


Thread

[PATCH 00/13] High performance balancing logic for big.LITTLE Arseniy Krasnov <a.krasnov@samsung.com> - 2015-11-06 13:10 +0100
  [PATCH 01/13] hperf_hmp: add new config for arm and arm64. Arseniy Krasnov <a.krasnov@samsung.com> - 2015-11-06 13:10 +0100
  [PATCH 02/13] hperf_hmp: introduce hew domain flag. Arseniy Krasnov <a.krasnov@samsung.com> - 2015-11-06 13:10 +0100
  [PATCH 13/13] hperf_hmp: cpufreq routines. Arseniy Krasnov <a.krasnov@samsung.com> - 2015-11-06 13:10 +0100
  [PATCH 07/13] hperf_hmp: migration auxiliary functions. Arseniy Krasnov <a.krasnov@samsung.com> - 2015-11-06 13:10 +0100
    Re: [PATCH 07/13] hperf_hmp: migration auxiliary functions. kbuild test robot <lkp@intel.com> - 2015-11-06 14:10 +0100
  [PATCH 10/13] hperf_hmp: idle pull function. Arseniy Krasnov <a.krasnov@samsung.com> - 2015-11-06 13:10 +0100
  [PATCH 08/13] hperf_hmp: swap tasks function. Arseniy Krasnov <a.krasnov@samsung.com> - 2015-11-06 13:10 +0100
  [PATCH 05/13] hperf_hmp: introduce druntime metric. Arseniy Krasnov <a.krasnov@samsung.com> - 2015-11-06 13:10 +0100
  Re: [PATCH 00/13] High performance balancing logic for big.LITTLE Peter Zijlstra <peterz@infradead.org> - 2015-11-07 11:00 +0100

csiph-web