From: "Jan H. Schönherr" <jschoenh@amazon.de>
To: Ingo Molnar <mingo@redhat.com>, Peter Zijlstra <peterz@infradead.org>
Cc: "Jan H. Schönherr" <jschoenh@amazon.de>, linux-kernel@vger.kernel.org
Subject: [RFC 58/60] cosched: Switch runqueues between regular scheduling and coscheduling
Date: Fri, 7 Sep 2018 23:40:45 +0200 [thread overview]
Message-ID: <20180907214047.26914-59-jschoenh@amazon.de> (raw)
In-Reply-To: <20180907214047.26914-1-jschoenh@amazon.de>
A regularly scheduled runqueue is enqueued via its TG-SE in its parent
task-group. When coscheduled it is enqueued via its hierarchical
parent's SD-SE. Switching between both means to replace one with the
other, and taking care to get rid of all references to the no longer
current SE, which is recorded as parent SE for various other SEs.
Essentially, this changes the SE-parent path through the task-group and
SD hierarchy, by flipping a part of this path. For example, switching
the runqueue marked with X from !is_root to is_root as part of switching
the child-TG from scheduled==2 to scheduled==1:
Before:
parent-TG
child-TG
,----------------O
System ,O´
/ O O
Core X´ O
/ O O O O
CPU O O O O
CPU0 1 2 3 0 1 2 3
After:
parent-TG
child-TG
,O
System O /
,----------------O´ O
Core X´ O
/ O O O O
CPU O O O O
CPU0 1 2 3 0 1 2 3
Signed-off-by: Jan H. Schönherr <jschoenh@amazon.de>
---
kernel/sched/cosched.c | 138 ++++++++++++++++++++++++++++++++++++++++++++++++-
kernel/sched/fair.c | 14 ++++-
kernel/sched/sched.h | 2 +
3 files changed, 151 insertions(+), 3 deletions(-)
diff --git a/kernel/sched/cosched.c b/kernel/sched/cosched.c
index 7c8b8c8d2814..eb6a6a61521e 100644
--- a/kernel/sched/cosched.c
+++ b/kernel/sched/cosched.c
@@ -515,9 +515,145 @@ void cosched_offline_group(struct task_group *tg)
list_del_rcu(&cfs->sdrq.tg_siblings);
}
+static void update_parent_entities(struct cfs_rq *cfs)
+{
+ struct sched_entity *se = __pick_first_entity(cfs);
+
+ while (se) {
+ set_entity_cfs(se, se->cfs_rq);
+ se = __pick_next_entity(se);
+ }
+
+ if (cfs->curr) {
+ /* curr is not kept within the tree */
+ set_entity_cfs(cfs->curr, cfs->curr->cfs_rq);
+ }
+}
+
+/*
+ * FIXME: We may be missing calls to attach_entity_cfs_rq() & co here
+ * and maybe elsewhere.
+ */
static void sdrq_update_root(struct sdrq *sdrq)
{
- /* TBD */
+ bool is_root, running;
+ struct sdrq *child;
+ struct rq *rq = sdrq->cfs_rq->rq;
+ struct rq *prq = parent_rq(rq);
+ struct rq_flags rf, prf;
+
+ lockdep_assert_held(&sdrq->cfs_rq->tg->lock);
+
+ if (!sdrq->sd_parent) {
+ /* If we are at the top, is_root must always be true */
+ SCHED_WARN_ON(sdrq->is_root != 1);
+ return;
+ }
+
+ is_root = sdrq->cfs_rq->tg->scheduled <= sdrq->data->level;
+
+ /* Exit early, when there is no change */
+ if (is_root == sdrq->is_root)
+ return;
+
+ /* Get proper locks */
+ rq_lock_irqsave(rq, &rf);
+
+ sdrq->is_root = is_root;
+ if (is_root)
+ sdrq->cfs_rq->my_se = sdrq->tg_se;
+ else
+ sdrq->cfs_rq->my_se = sdrq->sd_parent->sd_se;
+
+ /* Update parent entity of SD-SE */
+ if (sdrq->sd_se)
+ set_entity_cfs(sdrq->sd_se, sdrq->cfs_rq);
+
+ /* Update parent entities of TG-SEs of child task groups */
+ rcu_read_lock();
+ list_for_each_entry_rcu(child, &sdrq->tg_children, tg_siblings)
+ set_entity_cfs(child->tg_se, sdrq->cfs_rq);
+ rcu_read_unlock();
+
+ /*
+ * Update parent entities of tasks
+ *
+ * This is complicated by the fact, that there are no per-cpu lists of
+ * tasks. There is the complete list of tasks via do_each_thread/
+ * while_each_thread, but that is too much. Then, there is a list
+ * of all tasks within the current task group via cgroup_iter_start/
+ * cgroup_iter_next/cgroup_iter_end, but that would require additional
+ * filtering for the correct CPU, which is also not nice.
+ *
+ * Therefore, we only go through all currently enqueued tasks, and make
+ * sure to update all non-enqueued tasks during enqueue in
+ * enqueue_task_fair().
+ */
+ update_parent_entities(sdrq->cfs_rq);
+
+ /*
+ * FIXME: update_parent_entities() also updates non-task-SEs.
+ * So we could skip sd_se and tg_se updates, when we also update
+ * them during enqueuing. Not sure about the overhead, though.
+ */
+
+ running = sdrq->cfs_rq->nr_running > 0;
+
+ /* FIXME: Might fire on dynamic reconfigurations with throttling */
+ SCHED_WARN_ON(running && sdrq->cfs_rq->load.weight == 0);
+ SCHED_WARN_ON(!running && sdrq->cfs_rq->load.weight);
+
+ if (is_root) {
+ /* Change from 0 to 1: possibly dequeue sd_se, enqueue tg_se */
+ if (running) {
+ atomic64_sub(sdrq->cfs_rq->load.weight,
+ &sdrq->sd_parent->sdse_load);
+ dequeue_entity_fair(rq, sdrq->sd_parent->sd_se,
+ DEQUEUE_SLEEP,
+ sdrq->cfs_rq->h_nr_running);
+ }
+ if (sdrq->cfs_rq->curr) {
+ rq_lock(prq, &prf);
+ if (sdrq->data->leader == sdrq->sd_parent->data->leader)
+ put_prev_entity_fair(prq, sdrq->sd_parent->sd_se);
+ rq_unlock(prq, &prf);
+ if (sdrq->tg_se)
+ set_curr_entity_fair(rq, sdrq->tg_se);
+ }
+ /*
+ * FIXME: this is probably not enough with nested TGs, as the weights of the
+ * nested TGS could still be zero.
+ */
+ if ((sdrq->cfs_rq->curr || running) && sdrq->tg_se)
+ update_cfs_group(sdrq->tg_se);
+ if (running && sdrq->tg_se)
+ enqueue_entity_fair(rq, sdrq->tg_se,
+ ENQUEUE_WAKEUP,
+ sdrq->cfs_rq->h_nr_running);
+ } else {
+ /* Change from 1 to 0: dequeue tg_se, possibly enqueue sd_se */
+ if (running && sdrq->tg_se)
+ dequeue_entity_fair(rq, sdrq->tg_se, DEQUEUE_SLEEP,
+ sdrq->cfs_rq->h_nr_running);
+ if (sdrq->cfs_rq->curr) {
+ if (sdrq->tg_se)
+ put_prev_entity_fair(rq, sdrq->tg_se);
+ rq_lock(prq, &prf);
+ update_rq_clock(prq);
+ if (sdrq->data->leader == sdrq->sd_parent->data->leader)
+ set_curr_entity_fair(prq, sdrq->sd_parent->sd_se);
+ rq_unlock(prq, &prf);
+ }
+ if (running) {
+ atomic64_add(sdrq->cfs_rq->load.weight,
+ &sdrq->sd_parent->sdse_load);
+ enqueue_entity_fair(rq, sdrq->sd_parent->sd_se,
+ ENQUEUE_WAKEUP,
+ sdrq->cfs_rq->h_nr_running);
+ }
+ }
+
+ rq_unlock_irqrestore(rq, &rf);
}
void cosched_set_scheduled(struct task_group *tg, int level)
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 0c1d9334ea8e..322a84ec9511 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -768,7 +768,7 @@ struct sched_entity *__pick_first_entity(struct cfs_rq *cfs_rq)
return rb_entry(left, struct sched_entity, run_node);
}
-static struct sched_entity *__pick_next_entity(struct sched_entity *se)
+struct sched_entity *__pick_next_entity(struct sched_entity *se)
{
struct rb_node *next = rb_next(&se->run_node);
@@ -3145,7 +3145,7 @@ static inline int throttled_hierarchy(struct cfs_rq *cfs_rq);
* Recomputes the group entity based on the current state of its group
* runqueue.
*/
-static void update_cfs_group(struct sched_entity *se)
+void update_cfs_group(struct sched_entity *se)
{
struct cfs_rq *gcfs_rq = group_cfs_rq(se);
long shares, runnable;
@@ -5336,6 +5336,16 @@ bool enqueue_entity_fair(struct rq *rq, struct sched_entity *se, int flags,
int lcpu = rq->sdrq_data.leader;
#endif
+#ifdef CONFIG_COSCHEDULING
+ /*
+ * Update se->parent, in case sdrq_update_root() was called while
+ * this task was sleeping.
+ *
+ * FIXME: Can this be moved into enqueue_task_fair()?
+ */
+ set_entity_cfs(se, se->cfs_rq);
+#endif
+
rq_chain_init(&rc, rq);
for_each_sched_entity(se) {
rq_chain_lock(&rc, se);
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index e257451e05a5..310a706f0361 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -477,6 +477,7 @@ extern void sched_move_task(struct task_struct *tsk);
#ifdef CONFIG_FAIR_GROUP_SCHED
extern int sched_group_set_shares(struct task_group *tg, unsigned long shares);
+void update_cfs_group(struct sched_entity *se);
#ifdef CONFIG_SMP
extern void set_task_rq_fair(struct sched_entity *se,
@@ -2453,6 +2454,7 @@ static inline void double_rq_unlock(struct rq *rq1, struct rq *rq2)
extern struct sched_entity *__pick_first_entity(struct cfs_rq *cfs_rq);
extern struct sched_entity *__pick_last_entity(struct cfs_rq *cfs_rq);
+struct sched_entity *__pick_next_entity(struct sched_entity *se);
#ifdef CONFIG_SCHED_DEBUG
extern bool sched_debug_enabled;
--
2.9.3.1.gcba166c.dirty
next prev parent reply other threads:[~2018-09-07 21:47 UTC|newest]
Thread overview: 114+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-09-07 21:39 [RFC 00/60] Coscheduling for Linux Jan H. Schönherr
2018-09-07 21:39 ` [RFC 01/60] sched: Store task_group->se[] pointers as part of cfs_rq Jan H. Schönherr
2018-09-07 21:39 ` [RFC 02/60] sched: Introduce set_entity_cfs() to place a SE into a certain CFS runqueue Jan H. Schönherr
2018-09-07 21:39 ` [RFC 03/60] sched: Setup sched_domain_shared for all sched_domains Jan H. Schönherr
2018-09-07 21:39 ` [RFC 04/60] sched: Replace sd_numa_mask() hack with something sane Jan H. Schönherr
2018-09-07 21:39 ` [RFC 05/60] sched: Allow to retrieve the sched_domain_topology Jan H. Schönherr
2018-09-07 21:39 ` [RFC 06/60] sched: Add a lock-free variant of resched_cpu() Jan H. Schönherr
2018-09-07 21:39 ` [RFC 07/60] sched: Reduce dependencies of init_tg_cfs_entry() Jan H. Schönherr
2018-09-07 21:39 ` [RFC 08/60] sched: Move init_entity_runnable_average() into init_tg_cfs_entry() Jan H. Schönherr
2018-09-07 21:39 ` [RFC 09/60] sched: Do not require a CFS in init_tg_cfs_entry() Jan H. Schönherr
2018-09-07 21:39 ` [RFC 10/60] sched: Use parent_entity() in more places Jan H. Schönherr
2018-09-07 21:39 ` [RFC 11/60] locking/lockdep: Increase number of supported lockdep subclasses Jan H. Schönherr
2018-09-07 21:39 ` [RFC 12/60] locking/lockdep: Make cookie generator accessible Jan H. Schönherr
2018-09-07 21:40 ` [RFC 13/60] sched: Remove useless checks for root task-group Jan H. Schönherr
2018-09-07 21:40 ` [RFC 14/60] sched: Refactor sync_throttle() to accept a CFS runqueue as argument Jan H. Schönherr
2018-09-07 21:40 ` [RFC 15/60] sched: Introduce parent_cfs_rq() and use it Jan H. Schönherr
2018-09-07 21:40 ` [RFC 16/60] sched: Preparatory code movement Jan H. Schönherr
2018-09-07 21:40 ` [RFC 17/60] sched: Introduce and use generic task group CFS traversal functions Jan H. Schönherr
2018-09-07 21:40 ` [RFC 18/60] sched: Fix return value of SCHED_WARN_ON() Jan H. Schönherr
2018-09-07 21:40 ` [RFC 19/60] sched: Add entity variants of enqueue_task_fair() and dequeue_task_fair() Jan H. Schönherr
2018-09-07 21:40 ` [RFC 20/60] sched: Let {en,de}queue_entity_fair() work with a varying amount of tasks Jan H. Schönherr
2018-09-07 21:40 ` [RFC 21/60] sched: Add entity variants of put_prev_task_fair() and set_curr_task_fair() Jan H. Schönherr
2018-09-07 21:40 ` [RFC 22/60] cosched: Add config option for coscheduling support Jan H. Schönherr
2018-09-07 21:40 ` [RFC 23/60] cosched: Add core data structures for coscheduling Jan H. Schönherr
2018-09-07 21:40 ` [RFC 24/60] cosched: Do minimal pre-SMP coscheduler initialization Jan H. Schönherr
2018-09-07 21:40 ` [RFC 25/60] cosched: Prepare scheduling domain topology for coscheduling Jan H. Schönherr
2018-09-07 21:40 ` [RFC 26/60] cosched: Construct runqueue hierarchy Jan H. Schönherr
2018-09-07 21:40 ` [RFC 27/60] cosched: Add some small helper functions for later use Jan H. Schönherr
2018-09-07 21:40 ` [RFC 28/60] cosched: Add is_sd_se() to distinguish SD-SEs from TG-SEs Jan H. Schönherr
2018-09-07 21:40 ` [RFC 29/60] cosched: Adjust code reflecting on the total number of CFS tasks on a CPU Jan H. Schönherr
2018-09-07 21:40 ` [RFC 30/60] cosched: Disallow share modification on task groups for now Jan H. Schönherr
2018-09-07 21:40 ` [RFC 31/60] cosched: Don't disable idle tick " Jan H. Schönherr
2018-09-07 21:40 ` [RFC 32/60] cosched: Specialize parent_cfs_rq() for hierarchical runqueues Jan H. Schönherr
2018-09-07 21:40 ` [RFC 33/60] cosched: Allow resched_curr() to be called " Jan H. Schönherr
2018-09-07 21:40 ` [RFC 34/60] cosched: Add rq_of() variants for different use cases Jan H. Schönherr
2018-09-07 21:40 ` [RFC 35/60] cosched: Adjust rq_lock() functions to work with hierarchical runqueues Jan H. Schönherr
2018-09-07 21:40 ` [RFC 36/60] cosched: Use hrq_of() for rq_clock() and rq_clock_task() Jan H. Schönherr
2018-09-07 21:40 ` [RFC 37/60] cosched: Use hrq_of() for (indirect calls to) ___update_load_sum() Jan H. Schönherr
2018-09-07 21:40 ` [RFC 38/60] cosched: Skip updates on non-CPU runqueues in cfs_rq_util_change() Jan H. Schönherr
2018-09-07 21:40 ` [RFC 39/60] cosched: Adjust task group management for hierarchical runqueues Jan H. Schönherr
2018-09-07 21:40 ` [RFC 40/60] cosched: Keep track of task group hierarchy within each SD-RQ Jan H. Schönherr
2018-09-07 21:40 ` [RFC 41/60] cosched: Introduce locking for leader activities Jan H. Schönherr
2018-09-07 21:40 ` [RFC 42/60] cosched: Introduce locking for (mostly) enqueuing and dequeuing Jan H. Schönherr
2018-09-07 21:40 ` [RFC 43/60] cosched: Add for_each_sched_entity() variant for owned entities Jan H. Schönherr
2018-09-07 21:40 ` [RFC 44/60] cosched: Perform various rq_of() adjustments in scheduler code Jan H. Schönherr
2018-09-07 21:40 ` [RFC 45/60] cosched: Continue to account all load on per-CPU runqueues Jan H. Schönherr
2018-09-07 21:40 ` [RFC 46/60] cosched: Warn on throttling attempts of non-CPU runqueues Jan H. Schönherr
2018-09-07 21:40 ` [RFC 47/60] cosched: Adjust SE traversal and locking for common leader activities Jan H. Schönherr
2018-09-07 21:40 ` [RFC 48/60] cosched: Adjust SE traversal and locking for yielding and buddies Jan H. Schönherr
2018-09-07 21:40 ` [RFC 49/60] cosched: Adjust locking for enqueuing and dequeueing Jan H. Schönherr
2018-09-07 21:40 ` [RFC 50/60] cosched: Propagate load changes across hierarchy levels Jan H. Schönherr
2018-09-07 21:40 ` [RFC 51/60] cosched: Hacky work-around to avoid observing zero weight SD-SE Jan H. Schönherr
2018-09-07 21:40 ` [RFC 52/60] cosched: Support SD-SEs in enqueuing and dequeuing Jan H. Schönherr
2018-09-07 21:40 ` [RFC 53/60] cosched: Prevent balancing related functions from crossing hierarchy levels Jan H. Schönherr
2018-09-07 21:40 ` [RFC 54/60] cosched: Support idling in a coscheduled set Jan H. Schönherr
2018-09-07 21:40 ` [RFC 55/60] cosched: Adjust task selection for coscheduling Jan H. Schönherr
2018-09-07 21:40 ` [RFC 56/60] cosched: Adjust wakeup preemption rules " Jan H. Schönherr
2018-09-07 21:40 ` [RFC 57/60] cosched: Add sysfs interface to configure coscheduling on cgroups Jan H. Schönherr
2018-09-07 21:40 ` Jan H. Schönherr [this message]
2018-09-07 21:40 ` [RFC 59/60] cosched: Handle non-atomicity during switches to and from coscheduling Jan H. Schönherr
2018-09-07 21:40 ` [RFC 60/60] cosched: Add command line argument to enable coscheduling Jan H. Schönherr
2018-09-10 2:50 ` Randy Dunlap
2018-09-12 0:24 ` [RFC 00/60] Coscheduling for Linux Nishanth Aravamudan
2018-09-12 19:34 ` Jan H. Schönherr
2018-09-12 23:15 ` Nishanth Aravamudan
2018-09-13 11:31 ` Jan H. Schönherr
2018-09-13 18:16 ` Nishanth Aravamudan
2018-09-12 23:18 ` Jan H. Schönherr
2018-09-13 3:05 ` Nishanth Aravamudan
2018-09-13 19:19 ` [RFC 61/60] cosched: Accumulated fixes and improvements Jan H. Schönherr
2018-09-26 17:25 ` Nishanth Aravamudan
2018-09-26 21:05 ` Nishanth Aravamudan
2018-10-01 9:13 ` Jan H. Schönherr
2018-09-14 11:12 ` [RFC 00/60] Coscheduling for Linux Peter Zijlstra
2018-09-14 16:25 ` Jan H. Schönherr
2018-09-15 8:48 ` Task group cleanups and optimizations (was: Re: [RFC 00/60] Coscheduling for Linux) Jan H. Schönherr
2018-09-17 9:48 ` Peter Zijlstra
2018-09-18 13:22 ` Jan H. Schönherr
2018-09-18 13:38 ` Peter Zijlstra
2018-09-18 13:54 ` Jan H. Schönherr
2018-09-18 13:42 ` Peter Zijlstra
2018-09-18 14:35 ` Rik van Riel
2018-09-19 9:23 ` Jan H. Schönherr
2018-11-23 16:51 ` Frederic Weisbecker
2018-12-04 13:23 ` Jan H. Schönherr
2018-09-17 11:33 ` [RFC 00/60] Coscheduling for Linux Peter Zijlstra
2018-11-02 22:13 ` Nishanth Aravamudan
2018-09-17 12:25 ` Peter Zijlstra
2018-09-26 9:58 ` Jan H. Schönherr
2018-09-27 18:36 ` Subhra Mazumdar
2018-11-23 16:29 ` Frederic Weisbecker
2018-09-17 13:37 ` Peter Zijlstra
2018-09-26 9:35 ` Jan H. Schönherr
2018-09-18 14:40 ` Rik van Riel
2018-09-24 15:23 ` Jan H. Schönherr
2018-09-24 18:01 ` Rik van Riel
2018-09-18 0:33 ` Subhra Mazumdar
2018-09-18 11:44 ` Jan H. Schönherr
2018-09-19 21:53 ` Subhra Mazumdar
2018-09-24 15:43 ` Jan H. Schönherr
2018-09-27 18:12 ` Subhra Mazumdar
2018-10-04 13:29 ` Jon Masters
2018-10-17 2:09 ` Frederic Weisbecker
2018-10-19 11:40 ` Jan H. Schönherr
2018-10-19 14:52 ` Frederic Weisbecker
2018-10-19 15:16 ` Rik van Riel
2018-10-19 15:33 ` Frederic Weisbecker
2018-10-19 15:45 ` Rik van Riel
2018-10-19 19:07 ` Jan H. Schönherr
2018-10-19 0:26 ` Subhra Mazumdar
2018-10-26 23:44 ` Jan H. Schönherr
2018-10-29 22:52 ` Subhra Mazumdar
2018-10-26 23:05 ` Subhra Mazumdar
2018-10-27 0:07 ` Jan H. Schönherr
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=20180907214047.26914-59-jschoenh@amazon.de \
--to=jschoenh@amazon.de \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@redhat.com \
--cc=peterz@infradead.org \
/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
Powered by JetHome