summaryrefslogtreecommitdiffstats
path: root/meta-eas/recipes-kernel/linux/linux-renesas/0008-sched-fair-Fix-hierarchical-order-in-rq-leaf_cfs_rq_.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-eas/recipes-kernel/linux/linux-renesas/0008-sched-fair-Fix-hierarchical-order-in-rq-leaf_cfs_rq_.patch')
-rw-r--r--meta-eas/recipes-kernel/linux/linux-renesas/0008-sched-fair-Fix-hierarchical-order-in-rq-leaf_cfs_rq_.patch171
1 files changed, 171 insertions, 0 deletions
diff --git a/meta-eas/recipes-kernel/linux/linux-renesas/0008-sched-fair-Fix-hierarchical-order-in-rq-leaf_cfs_rq_.patch b/meta-eas/recipes-kernel/linux/linux-renesas/0008-sched-fair-Fix-hierarchical-order-in-rq-leaf_cfs_rq_.patch
new file mode 100644
index 0000000..323a48f
--- /dev/null
+++ b/meta-eas/recipes-kernel/linux/linux-renesas/0008-sched-fair-Fix-hierarchical-order-in-rq-leaf_cfs_rq_.patch
@@ -0,0 +1,171 @@
+From b351fc19a07fde281957aeb737cd32392c7bf5ba Mon Sep 17 00:00:00 2001
+From: Vincent Guittot <vincent.guittot@linaro.org>
+Date: Tue, 8 Nov 2016 10:53:43 +0100
+Subject: [PATCH 08/92] sched/fair: Fix hierarchical order in
+ rq->leaf_cfs_rq_list
+
+Fix the insertion of cfs_rq in rq->leaf_cfs_rq_list to ensure that a
+child will always be called before its parent.
+
+The hierarchical order in shares update list has been introduced by
+commit:
+
+ 67e86250f8ea ("sched: Introduce hierarchal order on shares update list")
+
+With the current implementation a child can be still put after its
+parent.
+
+Lets take the example of:
+
+ root
+ \
+ b
+ /\
+ c d*
+ |
+ e*
+
+with root -> b -> c already enqueued but not d -> e so the
+leaf_cfs_rq_list looks like: head -> c -> b -> root -> tail
+
+The branch d -> e will be added the first time that they are enqueued,
+starting with e then d.
+
+When e is added, its parents is not already on the list so e is put at
+the tail : head -> c -> b -> root -> e -> tail
+
+Then, d is added at the head because its parent is already on the
+list: head -> d -> c -> b -> root -> e -> tail
+
+e is not placed at the right position and will be called the last
+whereas it should be called at the beginning.
+
+Because it follows the bottom-up enqueue sequence, we are sure that we
+will finished to add either a cfs_rq without parent or a cfs_rq with a
+parent that is already on the list. We can use this event to detect
+when we have finished to add a new branch. For the others, whose
+parents are not already added, we have to ensure that they will be
+added after their children that have just been inserted the steps
+before, and after any potential parents that are already in the list.
+The easiest way is to put the cfs_rq just after the last inserted one
+and to keep track of it untl the branch is fully added.
+
+Signed-off-by: Vincent Guittot <vincent.guittot@linaro.org>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Acked-by: Dietmar Eggemann <dietmar.eggemann@arm.com>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Morten.Rasmussen@arm.com
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Cc: bsegall@google.com
+Cc: kernellwp@gmail.com
+Cc: pjt@google.com
+Cc: yuyang.du@intel.com
+Link: http://lkml.kernel.org/r/1478598827-32372-3-git-send-email-vincent.guittot@linaro.org
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+(cherry picked from commit 9c2791f936ef5fd04a118b5c284f2c9a95f4a647)
+Signed-off-by: Gaku Inami <gaku.inami.xw@bp.renesas.com>
+---
+ kernel/sched/core.c | 1 +
+ kernel/sched/fair.c | 54 +++++++++++++++++++++++++++++++++++++++++++++-------
+ kernel/sched/sched.h | 1 +
+ 3 files changed, 49 insertions(+), 7 deletions(-)
+
+diff --git a/kernel/sched/core.c b/kernel/sched/core.c
+index e891e12..391d6c9 100644
+--- a/kernel/sched/core.c
++++ b/kernel/sched/core.c
+@@ -7603,6 +7603,7 @@ void __init sched_init(void)
+ #ifdef CONFIG_FAIR_GROUP_SCHED
+ root_task_group.shares = ROOT_TASK_GROUP_LOAD;
+ INIT_LIST_HEAD(&rq->leaf_cfs_rq_list);
++ rq->tmp_alone_branch = &rq->leaf_cfs_rq_list;
+ /*
+ * How much cpu bandwidth does root_task_group get?
+ *
+diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
+index 0731aff..4a67026 100644
+--- a/kernel/sched/fair.c
++++ b/kernel/sched/fair.c
+@@ -283,19 +283,59 @@ static inline struct cfs_rq *group_cfs_rq(struct sched_entity *grp)
+ static inline void list_add_leaf_cfs_rq(struct cfs_rq *cfs_rq)
+ {
+ if (!cfs_rq->on_list) {
++ struct rq *rq = rq_of(cfs_rq);
++ int cpu = cpu_of(rq);
+ /*
+ * Ensure we either appear before our parent (if already
+ * enqueued) or force our parent to appear after us when it is
+- * enqueued. The fact that we always enqueue bottom-up
+- * reduces this to two cases.
++ * enqueued. The fact that we always enqueue bottom-up
++ * reduces this to two cases and a special case for the root
++ * cfs_rq. Furthermore, it also means that we will always reset
++ * tmp_alone_branch either when the branch is connected
++ * to a tree or when we reach the beg of the tree
+ */
+ if (cfs_rq->tg->parent &&
+- cfs_rq->tg->parent->cfs_rq[cpu_of(rq_of(cfs_rq))]->on_list) {
+- list_add_rcu(&cfs_rq->leaf_cfs_rq_list,
+- &rq_of(cfs_rq)->leaf_cfs_rq_list);
+- } else {
++ cfs_rq->tg->parent->cfs_rq[cpu]->on_list) {
++ /*
++ * If parent is already on the list, we add the child
++ * just before. Thanks to circular linked property of
++ * the list, this means to put the child at the tail
++ * of the list that starts by parent.
++ */
++ list_add_tail_rcu(&cfs_rq->leaf_cfs_rq_list,
++ &(cfs_rq->tg->parent->cfs_rq[cpu]->leaf_cfs_rq_list));
++ /*
++ * The branch is now connected to its tree so we can
++ * reset tmp_alone_branch to the beginning of the
++ * list.
++ */
++ rq->tmp_alone_branch = &rq->leaf_cfs_rq_list;
++ } else if (!cfs_rq->tg->parent) {
++ /*
++ * cfs rq without parent should be put
++ * at the tail of the list.
++ */
+ list_add_tail_rcu(&cfs_rq->leaf_cfs_rq_list,
+- &rq_of(cfs_rq)->leaf_cfs_rq_list);
++ &rq->leaf_cfs_rq_list);
++ /*
++ * We have reach the beg of a tree so we can reset
++ * tmp_alone_branch to the beginning of the list.
++ */
++ rq->tmp_alone_branch = &rq->leaf_cfs_rq_list;
++ } else {
++ /*
++ * The parent has not already been added so we want to
++ * make sure that it will be put after us.
++ * tmp_alone_branch points to the beg of the branch
++ * where we will add parent.
++ */
++ list_add_rcu(&cfs_rq->leaf_cfs_rq_list,
++ rq->tmp_alone_branch);
++ /*
++ * update tmp_alone_branch to points to the new beg
++ * of the branch
++ */
++ rq->tmp_alone_branch = &cfs_rq->leaf_cfs_rq_list;
+ }
+
+ cfs_rq->on_list = 1;
+diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
+index 345c1cc..36f30e0 100644
+--- a/kernel/sched/sched.h
++++ b/kernel/sched/sched.h
+@@ -623,6 +623,7 @@ struct rq {
+ #ifdef CONFIG_FAIR_GROUP_SCHED
+ /* list of leaf cfs_rq on this cpu: */
+ struct list_head leaf_cfs_rq_list;
++ struct list_head *tmp_alone_branch;
+ #endif /* CONFIG_FAIR_GROUP_SCHED */
+
+ /*
+--
+1.9.1
+