Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1607331 > unrolled thread
| Started by | Byungchul Park <byungchul.park@lge.com> |
|---|---|
| First post | 2017-03-23 11:40 +0100 |
| Last post | 2017-03-28 09:40 +0200 |
| Articles | 12 — 2 participants |
Back to article view | Back to linux.kernel
[PATCH 0/8] sched/deadline: Return the best satisfying affinity and dl in cpudl_find Byungchul Park <byungchul.park@lge.com> - 2017-03-23 11:40 +0100
[PATCH 4/8] sched/deadline: Factor out the selecting of suitable max cpu Byungchul Park <byungchul.park@lge.com> - 2017-03-23 11:40 +0100
[PATCH 3/8] sched/deadline: Add cpudl_maximum_dl() for clean-up Byungchul Park <byungchul.park@lge.com> - 2017-03-23 11:40 +0100
[PATCH 5/8] sched/deadline: Protect read of cpudl heap with a lock Byungchul Park <byungchul.park@lge.com> - 2017-03-23 11:40 +0100
[PATCH 2/8] sched/deadline: Re-define parameters of cpudl heapify functions Byungchul Park <byungchul.park@lge.com> - 2017-03-23 11:40 +0100
[PATCH 6/8] sched/deadline: Don't return meaningless cpu in cpudl_maximum_cpu() Byungchul Park <byungchul.park@lge.com> - 2017-03-23 11:40 +0100
[PATCH 7/8] sched/deadline: Factor out the modifying of cpudl's heap tree Byungchul Park <byungchul.park@lge.com> - 2017-03-23 11:40 +0100
Re: [PATCH 0/8] sched/deadline: Return the best satisfying affinity and dl in cpudl_find Byungchul Park <byungchul.park@lge.com> - 2017-03-23 23:40 +0100
Re: [PATCH 0/8] sched/deadline: Return the best satisfying affinity and dl in cpudl_find Juri Lelli <juri.lelli@arm.com> - 2017-03-27 16:10 +0200
Re: [PATCH 0/8] sched/deadline: Return the best satisfying affinity and dl in cpudl_find Byungchul Park <byungchul.park@lge.com> - 2017-03-28 02:50 +0200
Re: [PATCH 0/8] sched/deadline: Return the best satisfying affinity and dl in cpudl_find Juri Lelli <juri.lelli@arm.com> - 2017-03-28 09:20 +0200
Re: [PATCH 0/8] sched/deadline: Return the best satisfying affinity and dl in cpudl_find Byungchul Park <byungchul.park@lge.com> - 2017-03-28 09:40 +0200
| From | Byungchul Park <byungchul.park@lge.com> |
|---|---|
| Date | 2017-03-23 11:40 +0100 |
| Subject | [PATCH 0/8] sched/deadline: Return the best satisfying affinity and dl in cpudl_find |
| Message-ID | <to8jU-XG-9@gated-at.bofh.it> |
cpudl_find() is used to find a cpu having the latest dl. The function
should return the latest cpu among ones satisfying task's affinity and
dl constraint, but current code gives up immediately and just return
fail when it fails at the test *only with* the maximum cpu.
For example:
cpu 0 is running a task (dl: 10).
cpu 1 is running a task (dl: 9).
cpu 2 is running a task (dl: 8).
cpu 3 is running a task (dl: 2).
where cpu 3 want to push a task (affinity is 1 2 3 and dl is 1).
In this case, the task should be migrated from cpu 3 to cpu 1, and
preempt cpu 1's task. However, current code just returns fail because
it fails at the affinity test with the maximum cpu, that is, cpu 0.
This patch set tries to find the best among ones satisfying task's
affinity and dl constraint until success or no more to see.
Byungchul Park (8):
sched/deadline: Make find_later_rq() choose a closer cpu in topology
sched/deadline: Re-define parameters of cpudl heapify functions
sched/deadline: Add cpudl_maximum_dl() for clean-up
sched/deadline: Factor out the selecting of suitable max cpu
sched/deadline: Protect read of cpudl heap with a lock
sched/deadline: Don't return meaningless cpu in cpudl_maximum_cpu()
sched/deadline: Factor out the modifying of cpudl's heap tree
sched/deadline: Return the best satisfying affinity and dl in
cpudl_find
kernel/sched/cpudeadline.c | 228 +++++++++++++++++++++++++++++++--------------
kernel/sched/cpudeadline.h | 9 ++
kernel/sched/deadline.c | 29 +++---
3 files changed, 182 insertions(+), 84 deletions(-)
--
1.9.1
[toc] | [next] | [standalone]
| From | Byungchul Park <byungchul.park@lge.com> |
|---|---|
| Date | 2017-03-23 11:40 +0100 |
| Subject | [PATCH 4/8] sched/deadline: Factor out the selecting of suitable max cpu |
| Message-ID | <to8jU-XG-13@gated-at.bofh.it> |
| In reply to | #1607331 |
Currently, dl scheduler selects a cpu having the maximum dl on pushing.
On success, it would be a fast path, but it might fail because of the
task's affinity or dl value, so we need a slow path in case of failure.
As a first step in adding a slow path, factor out the selecting into
helper function, cpudl_fast_find().
Signed-off-by: Byungchul Park <byungchul.park@lge.com>
---
kernel/sched/cpudeadline.c | 21 ++++++++++++++++-----
1 file changed, 16 insertions(+), 5 deletions(-)
diff --git a/kernel/sched/cpudeadline.c b/kernel/sched/cpudeadline.c
index f1a6ce4..f03479c 100644
--- a/kernel/sched/cpudeadline.c
+++ b/kernel/sched/cpudeadline.c
@@ -115,6 +115,19 @@ static inline u64 cpudl_maximum_dl(struct cpudl *cp)
return cp->elements[0].dl;
}
+static int cpudl_fast_find(struct cpudl *cp, struct task_struct *p)
+{
+ const struct sched_dl_entity *dl_se = &p->dl;
+ int max_cpu = cpudl_maximum_cpu(cp);
+ u64 max_dl = cpudl_maximum_dl(cp);
+
+ if (cpumask_test_cpu(max_cpu, &p->cpus_allowed) &&
+ dl_time_before(dl_se->deadline, max_dl))
+ return max_cpu;
+
+ return -1;
+}
+
/*
* cpudl_find - find the best (later-dl) CPU in the system
* @cp: the cpudl max-heap context
@@ -127,16 +140,14 @@ int cpudl_find(struct cpudl *cp, struct task_struct *p,
struct cpumask *later_mask)
{
int best_cpu = -1;
- const struct sched_dl_entity *dl_se = &p->dl;
if (later_mask &&
cpumask_and(later_mask, cp->free_cpus, &p->cpus_allowed)) {
best_cpu = cpumask_any(later_mask);
goto out;
- } else if (cpumask_test_cpu(cpudl_maximum_cpu(cp), &p->cpus_allowed) &&
- dl_time_before(dl_se->deadline, cpudl_maximum_dl(cp))) {
- best_cpu = cpudl_maximum_cpu(cp);
- if (later_mask)
+ } else {
+ best_cpu = cpudl_fast_find(cp, p);
+ if (best_cpu != -1 && later_mask)
cpumask_set_cpu(best_cpu, later_mask);
}
--
1.9.1
[toc] | [prev] | [next] | [standalone]
| From | Byungchul Park <byungchul.park@lge.com> |
|---|---|
| Date | 2017-03-23 11:40 +0100 |
| Subject | [PATCH 3/8] sched/deadline: Add cpudl_maximum_dl() for clean-up |
| Message-ID | <to8jU-XG-17@gated-at.bofh.it> |
| In reply to | #1607331 |
Current code uses cpudl_maximum() to get the root node's cpu, while it
directly accesses the root node using 'cp->elements[0].dl' to get the
root node's dl. It would be better and more readible if a function to
get the dl is added. So add it.
Signed-off-by: Byungchul Park <byungchul.park@lge.com>
---
kernel/sched/cpudeadline.c | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/kernel/sched/cpudeadline.c b/kernel/sched/cpudeadline.c
index 7dd6d9d..f1a6ce4 100644
--- a/kernel/sched/cpudeadline.c
+++ b/kernel/sched/cpudeadline.c
@@ -105,11 +105,16 @@ static void cpudl_heapify(struct cpudl_item *e, int size, int idx)
cpudl_heapify_down(e, size, idx);
}
-static inline int cpudl_maximum(struct cpudl *cp)
+static inline int cpudl_maximum_cpu(struct cpudl *cp)
{
return cp->elements[0].cpu;
}
+static inline u64 cpudl_maximum_dl(struct cpudl *cp)
+{
+ return cp->elements[0].dl;
+}
+
/*
* cpudl_find - find the best (later-dl) CPU in the system
* @cp: the cpudl max-heap context
@@ -128,9 +133,9 @@ int cpudl_find(struct cpudl *cp, struct task_struct *p,
cpumask_and(later_mask, cp->free_cpus, &p->cpus_allowed)) {
best_cpu = cpumask_any(later_mask);
goto out;
- } else if (cpumask_test_cpu(cpudl_maximum(cp), &p->cpus_allowed) &&
- dl_time_before(dl_se->deadline, cp->elements[0].dl)) {
- best_cpu = cpudl_maximum(cp);
+ } else if (cpumask_test_cpu(cpudl_maximum_cpu(cp), &p->cpus_allowed) &&
+ dl_time_before(dl_se->deadline, cpudl_maximum_dl(cp))) {
+ best_cpu = cpudl_maximum_cpu(cp);
if (later_mask)
cpumask_set_cpu(best_cpu, later_mask);
}
--
1.9.1
[toc] | [prev] | [next] | [standalone]
| From | Byungchul Park <byungchul.park@lge.com> |
|---|---|
| Date | 2017-03-23 11:40 +0100 |
| Subject | [PATCH 5/8] sched/deadline: Protect read of cpudl heap with a lock |
| Message-ID | <to8jU-XG-23@gated-at.bofh.it> |
| In reply to | #1607331 |
Current code reads cp->elements[0].cpu and cp->elements[0].dl without
acquiring cpudl's lock. There are two problems on it:
1. When we read elements[0].dl, the value can be broken on 32 bit
machine because elements[0].dl is 64 bit data. We should guarantee
it to be done atomically.
2. Obsolete data can be read unless syncronizing with updaters:
updater1 updater2 reader
-------- -------- ------
lock A
set maxcpu = cpu1
unlock A
lock A
set maxcpu = cpu2
unlock A
read maxcpu, it might be -1
where maxcpu was -1 initially.
When reading maxcpu, the value might be -1, we expect that should be
cpu2 though. So force readers also to be protected using the lock.
Signed-off-by: Byungchul Park <byungchul.park@lge.com>
---
kernel/sched/cpudeadline.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/kernel/sched/cpudeadline.c b/kernel/sched/cpudeadline.c
index f03479c..37bbb66 100644
--- a/kernel/sched/cpudeadline.c
+++ b/kernel/sched/cpudeadline.c
@@ -118,8 +118,14 @@ static inline u64 cpudl_maximum_dl(struct cpudl *cp)
static int cpudl_fast_find(struct cpudl *cp, struct task_struct *p)
{
const struct sched_dl_entity *dl_se = &p->dl;
- int max_cpu = cpudl_maximum_cpu(cp);
- u64 max_dl = cpudl_maximum_dl(cp);
+ unsigned long flags;
+ int max_cpu;
+ u64 max_dl;
+
+ raw_spin_lock_irqsave(&cp->lock, flags);
+ max_cpu = cpudl_maximum_cpu(cp);
+ max_dl = cpudl_maximum_dl(cp);
+ raw_spin_unlock_irqrestore(&cp->lock, flags);
if (cpumask_test_cpu(max_cpu, &p->cpus_allowed) &&
dl_time_before(dl_se->deadline, max_dl))
--
1.9.1
[toc] | [prev] | [next] | [standalone]
| From | Byungchul Park <byungchul.park@lge.com> |
|---|---|
| Date | 2017-03-23 11:40 +0100 |
| Subject | [PATCH 2/8] sched/deadline: Re-define parameters of cpudl heapify functions |
| Message-ID | <to8jU-XG-25@gated-at.bofh.it> |
| In reply to | #1607331 |
If you don't like this clean-up patch, please let me know. If so, I will
exclude this patch from next spin.
Thank you,
Byungchul
-----8<-----
From b303ccf6b64064ce22aa17d16a012dcc7904ad32 Mon Sep 17 00:00:00 2001
From: Byungchul Park <byungchul.park@lge.com>
Date: Wed, 22 Mar 2017 14:07:22 +0900
Subject: [PATCH 2/8] sched/deadline: Re-define parameters of cpudl heapify
functions
Currently whole 'struct cpudl' is used as a parameter on heapifying.
However, only elements and size are needed on the work. So change the
parameters.
Signed-off-by: Byungchul Park <byungchul.park@lge.com>
---
kernel/sched/cpudeadline.c | 63 ++++++++++++++++++++++------------------------
1 file changed, 30 insertions(+), 33 deletions(-)
diff --git a/kernel/sched/cpudeadline.c b/kernel/sched/cpudeadline.c
index fba235c..7dd6d9d 100644
--- a/kernel/sched/cpudeadline.c
+++ b/kernel/sched/cpudeadline.c
@@ -31,14 +31,14 @@ static inline int right_child(int i)
return (i << 1) + 2;
}
-static void cpudl_heapify_down(struct cpudl *cp, int idx)
+static void cpudl_heapify_down(struct cpudl_item *e, int size, int idx)
{
int l, r, largest;
- int orig_cpu = cp->elements[idx].cpu;
- u64 orig_dl = cp->elements[idx].dl;
+ int orig_cpu = e[idx].cpu;
+ u64 orig_dl = e[idx].dl;
- if (left_child(idx) >= cp->size)
+ if (left_child(idx) >= size)
return;
/* adapted from lib/prio_heap.c */
@@ -49,63 +49,60 @@ static void cpudl_heapify_down(struct cpudl *cp, int idx)
largest = idx;
largest_dl = orig_dl;
- if ((l < cp->size) && dl_time_before(orig_dl,
- cp->elements[l].dl)) {
+ if ((l < size) && dl_time_before(orig_dl, e[l].dl)) {
largest = l;
- largest_dl = cp->elements[l].dl;
+ largest_dl = e[l].dl;
}
- if ((r < cp->size) && dl_time_before(largest_dl,
- cp->elements[r].dl))
+ if ((r < size) && dl_time_before(largest_dl, e[r].dl))
largest = r;
if (largest == idx)
break;
/* pull largest child onto idx */
- cp->elements[idx].cpu = cp->elements[largest].cpu;
- cp->elements[idx].dl = cp->elements[largest].dl;
- cp->elements[cp->elements[idx].cpu].idx = idx;
+ e[idx].cpu = e[largest].cpu;
+ e[idx].dl = e[largest].dl;
+ e[e[idx].cpu].idx = idx;
idx = largest;
}
/* actual push down of saved original values orig_* */
- cp->elements[idx].cpu = orig_cpu;
- cp->elements[idx].dl = orig_dl;
- cp->elements[cp->elements[idx].cpu].idx = idx;
+ e[idx].cpu = orig_cpu;
+ e[idx].dl = orig_dl;
+ e[e[idx].cpu].idx = idx;
}
-static void cpudl_heapify_up(struct cpudl *cp, int idx)
+static void cpudl_heapify_up(struct cpudl_item *e, int size, int idx)
{
int p;
- int orig_cpu = cp->elements[idx].cpu;
- u64 orig_dl = cp->elements[idx].dl;
+ int orig_cpu = e[idx].cpu;
+ u64 orig_dl = e[idx].dl;
if (idx == 0)
return;
do {
p = parent(idx);
- if (dl_time_before(orig_dl, cp->elements[p].dl))
+ if (dl_time_before(orig_dl, e[p].dl))
break;
/* pull parent onto idx */
- cp->elements[idx].cpu = cp->elements[p].cpu;
- cp->elements[idx].dl = cp->elements[p].dl;
- cp->elements[cp->elements[idx].cpu].idx = idx;
+ e[idx].cpu = e[p].cpu;
+ e[idx].dl = e[p].dl;
+ e[e[idx].cpu].idx = idx;
idx = p;
} while (idx != 0);
/* actual push up of saved original values orig_* */
- cp->elements[idx].cpu = orig_cpu;
- cp->elements[idx].dl = orig_dl;
- cp->elements[cp->elements[idx].cpu].idx = idx;
+ e[idx].cpu = orig_cpu;
+ e[idx].dl = orig_dl;
+ e[e[idx].cpu].idx = idx;
}
-static void cpudl_heapify(struct cpudl *cp, int idx)
+static void cpudl_heapify(struct cpudl_item *e, int size, int idx)
{
- if (idx > 0 && dl_time_before(cp->elements[parent(idx)].dl,
- cp->elements[idx].dl))
- cpudl_heapify_up(cp, idx);
+ if (idx > 0 && dl_time_before(e[parent(idx)].dl, e[idx].dl))
+ cpudl_heapify_up(e, size, idx);
else
- cpudl_heapify_down(cp, idx);
+ cpudl_heapify_down(e, size, idx);
}
static inline int cpudl_maximum(struct cpudl *cp)
@@ -176,7 +173,7 @@ void cpudl_clear(struct cpudl *cp, int cpu)
cp->size--;
cp->elements[new_cpu].idx = old_idx;
cp->elements[cpu].idx = IDX_INVALID;
- cpudl_heapify(cp, old_idx);
+ cpudl_heapify(cp->elements, cp->size, old_idx);
cpumask_set_cpu(cpu, cp->free_cpus);
}
@@ -208,11 +205,11 @@ void cpudl_set(struct cpudl *cp, int cpu, u64 dl)
cp->elements[new_idx].dl = dl;
cp->elements[new_idx].cpu = cpu;
cp->elements[cpu].idx = new_idx;
- cpudl_heapify_up(cp, new_idx);
+ cpudl_heapify_up(cp->elements, cp->size, new_idx);
cpumask_clear_cpu(cpu, cp->free_cpus);
} else {
cp->elements[old_idx].dl = dl;
- cpudl_heapify(cp, old_idx);
+ cpudl_heapify(cp->elements, cp->size, old_idx);
}
raw_spin_unlock_irqrestore(&cp->lock, flags);
--
1.9.1
[toc] | [prev] | [next] | [standalone]
| From | Byungchul Park <byungchul.park@lge.com> |
|---|---|
| Date | 2017-03-23 11:40 +0100 |
| Subject | [PATCH 6/8] sched/deadline: Don't return meaningless cpu in cpudl_maximum_cpu() |
| Message-ID | <to8jV-XG-31@gated-at.bofh.it> |
| In reply to | #1607331 |
When the heap tree is empty, cp->elements[0].cpu has meaningless value.
We need to consider the case.
Signed-off-by: Byungchul Park <byungchul.park@lge.com>
---
kernel/sched/cpudeadline.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/kernel/sched/cpudeadline.c b/kernel/sched/cpudeadline.c
index 37bbb66..21404b8 100644
--- a/kernel/sched/cpudeadline.c
+++ b/kernel/sched/cpudeadline.c
@@ -107,7 +107,8 @@ static void cpudl_heapify(struct cpudl_item *e, int size, int idx)
static inline int cpudl_maximum_cpu(struct cpudl *cp)
{
- return cp->elements[0].cpu;
+ int cpu = cp->elements[0].cpu;
+ return cp->elements[cpu].idx == IDX_INVALID ? -1 : cpu;
}
static inline u64 cpudl_maximum_dl(struct cpudl *cp)
@@ -127,7 +128,8 @@ static int cpudl_fast_find(struct cpudl *cp, struct task_struct *p)
max_dl = cpudl_maximum_dl(cp);
raw_spin_unlock_irqrestore(&cp->lock, flags);
- if (cpumask_test_cpu(max_cpu, &p->cpus_allowed) &&
+ if (max_cpu != -1 &&
+ cpumask_test_cpu(max_cpu, &p->cpus_allowed) &&
dl_time_before(dl_se->deadline, max_dl))
return max_cpu;
--
1.9.1
[toc] | [prev] | [next] | [standalone]
| From | Byungchul Park <byungchul.park@lge.com> |
|---|---|
| Date | 2017-03-23 11:40 +0100 |
| Subject | [PATCH 7/8] sched/deadline: Factor out the modifying of cpudl's heap tree |
| Message-ID | <to8jV-XG-33@gated-at.bofh.it> |
| In reply to | #1607331 |
Currently, cpudl_{set,clear} is responsible for manipulating cpudl's
heap tree and free_cpus list under lock protection. However, operation
manipulating the heap tree itself is reusable.
Actually, the operation is useful when picking up the second maximum
node from the tree, where it does not need to manipulate free_cpus list
but only needs to manipulate the tree.
Signed-off-by: Byungchul Park <byungchul.park@lge.com>
---
kernel/sched/cpudeadline.c | 95 ++++++++++++++++++++++++++++++----------------
1 file changed, 62 insertions(+), 33 deletions(-)
diff --git a/kernel/sched/cpudeadline.c b/kernel/sched/cpudeadline.c
index 21404b8..453159a 100644
--- a/kernel/sched/cpudeadline.c
+++ b/kernel/sched/cpudeadline.c
@@ -116,6 +116,64 @@ static inline u64 cpudl_maximum_dl(struct cpudl *cp)
return cp->elements[0].dl;
}
+/*
+ * __cpudl_clear - remove a cpu from the cpudl max-heap
+ * @cp: the cpudl max-heap context
+ * @cpu: the target cpu
+ *
+ * Notes: assumes cpu_rq(cpu)->lock and cpudl->lock are locked
+ *
+ * Returns: (void)
+ */
+static void __cpudl_clear(struct cpudl *cp, int cpu)
+{
+ int old_idx, new_cpu;
+
+ old_idx = cp->elements[cpu].idx;
+ if (old_idx == IDX_INVALID) {
+ /*
+ * Nothing to remove if old_idx was invalid.
+ * This could happen if a rq_offline_dl is
+ * called for a CPU without -dl tasks running.
+ */
+ } else {
+ new_cpu = cp->elements[cp->size - 1].cpu;
+ cp->elements[old_idx].dl = cp->elements[cp->size - 1].dl;
+ cp->elements[old_idx].cpu = new_cpu;
+ cp->size--;
+ cp->elements[new_cpu].idx = old_idx;
+ cp->elements[cpu].idx = IDX_INVALID;
+ cpudl_heapify(cp->elements, cp->size, old_idx);
+ }
+}
+
+/*
+ * __cpudl_set - update the cpudl max-heap
+ * @cp: the cpudl max-heap context
+ * @cpu: the target cpu
+ * @dl: the new earliest deadline for this cpu
+ *
+ * Notes: assumes cpu_rq(cpu)->lock and cpudl->lock are locked
+ *
+ * Returns: (void)
+ */
+static void __cpudl_set(struct cpudl *cp, int cpu, u64 dl)
+{
+ int old_idx;
+
+ old_idx = cp->elements[cpu].idx;
+ if (old_idx == IDX_INVALID) {
+ int new_idx = cp->size++;
+ cp->elements[new_idx].dl = dl;
+ cp->elements[new_idx].cpu = cpu;
+ cp->elements[cpu].idx = new_idx;
+ cpudl_heapify_up(cp->elements, cp->size, new_idx);
+ } else {
+ cp->elements[old_idx].dl = dl;
+ cpudl_heapify(cp->elements, cp->size, old_idx);
+ }
+}
+
static int cpudl_fast_find(struct cpudl *cp, struct task_struct *p)
{
const struct sched_dl_entity *dl_se = &p->dl;
@@ -176,31 +234,14 @@ int cpudl_find(struct cpudl *cp, struct task_struct *p,
*/
void cpudl_clear(struct cpudl *cp, int cpu)
{
- int old_idx, new_cpu;
unsigned long flags;
WARN_ON(!cpu_present(cpu));
raw_spin_lock_irqsave(&cp->lock, flags);
-
- old_idx = cp->elements[cpu].idx;
- if (old_idx == IDX_INVALID) {
- /*
- * Nothing to remove if old_idx was invalid.
- * This could happen if a rq_offline_dl is
- * called for a CPU without -dl tasks running.
- */
- } else {
- new_cpu = cp->elements[cp->size - 1].cpu;
- cp->elements[old_idx].dl = cp->elements[cp->size - 1].dl;
- cp->elements[old_idx].cpu = new_cpu;
- cp->size--;
- cp->elements[new_cpu].idx = old_idx;
- cp->elements[cpu].idx = IDX_INVALID;
- cpudl_heapify(cp->elements, cp->size, old_idx);
-
+ __cpudl_clear(cp, cpu);
+ if (cp->elements[cpu].idx != IDX_INVALID)
cpumask_set_cpu(cpu, cp->free_cpus);
- }
raw_spin_unlock_irqrestore(&cp->lock, flags);
}
@@ -216,26 +257,14 @@ void cpudl_clear(struct cpudl *cp, int cpu)
*/
void cpudl_set(struct cpudl *cp, int cpu, u64 dl)
{
- int old_idx;
unsigned long flags;
WARN_ON(!cpu_present(cpu));
raw_spin_lock_irqsave(&cp->lock, flags);
-
- old_idx = cp->elements[cpu].idx;
- if (old_idx == IDX_INVALID) {
- int new_idx = cp->size++;
- cp->elements[new_idx].dl = dl;
- cp->elements[new_idx].cpu = cpu;
- cp->elements[cpu].idx = new_idx;
- cpudl_heapify_up(cp->elements, cp->size, new_idx);
+ __cpudl_set(cp, cpu, dl);
+ if (cp->elements[cpu].idx == IDX_INVALID)
cpumask_clear_cpu(cpu, cp->free_cpus);
- } else {
- cp->elements[old_idx].dl = dl;
- cpudl_heapify(cp->elements, cp->size, old_idx);
- }
-
raw_spin_unlock_irqrestore(&cp->lock, flags);
}
--
1.9.1
[toc] | [prev] | [next] | [standalone]
| From | Byungchul Park <byungchul.park@lge.com> |
|---|---|
| Date | 2017-03-23 23:40 +0100 |
| Subject | Re: [PATCH 0/8] sched/deadline: Return the best satisfying affinity and dl in cpudl_find |
| Message-ID | <tojyG-sG-11@gated-at.bofh.it> |
| In reply to | #1607331 |
On Thu, Mar 23, 2017 at 07:32:35PM +0900, Byungchul Park wrote:
> cpudl_find() is used to find a cpu having the latest dl. The function
> should return the latest cpu among ones satisfying task's affinity and
> dl constraint, but current code gives up immediately and just return
> fail when it fails at the test *only with* the maximum cpu.
>
> For example:
>
> cpu 0 is running a task (dl: 10).
> cpu 1 is running a task (dl: 9).
> cpu 2 is running a task (dl: 8).
> cpu 3 is running a task (dl: 2).
^
should be 1
>
> where cpu 3 want to push a task (affinity is 1 2 3 and dl is 1).
^
should be 2
>
> In this case, the task should be migrated from cpu 3 to cpu 1, and
> preempt cpu 1's task. However, current code just returns fail because
> it fails at the affinity test with the maximum cpu, that is, cpu 0.
>
> This patch set tries to find the best among ones satisfying task's
> affinity and dl constraint until success or no more to see.
>
> Byungchul Park (8):
> sched/deadline: Make find_later_rq() choose a closer cpu in topology
> sched/deadline: Re-define parameters of cpudl heapify functions
> sched/deadline: Add cpudl_maximum_dl() for clean-up
> sched/deadline: Factor out the selecting of suitable max cpu
> sched/deadline: Protect read of cpudl heap with a lock
> sched/deadline: Don't return meaningless cpu in cpudl_maximum_cpu()
> sched/deadline: Factor out the modifying of cpudl's heap tree
> sched/deadline: Return the best satisfying affinity and dl in
> cpudl_find
>
> kernel/sched/cpudeadline.c | 228 +++++++++++++++++++++++++++++++--------------
> kernel/sched/cpudeadline.h | 9 ++
> kernel/sched/deadline.c | 29 +++---
> 3 files changed, 182 insertions(+), 84 deletions(-)
>
> --
> 1.9.1
[toc] | [prev] | [next] | [standalone]
| From | Juri Lelli <juri.lelli@arm.com> |
|---|---|
| Date | 2017-03-27 16:10 +0200 |
| Subject | Re: [PATCH 0/8] sched/deadline: Return the best satisfying affinity and dl in cpudl_find |
| Message-ID | <tpDvj-Li-1@gated-at.bofh.it> |
| In reply to | #1607331 |
Hi, On 23/03/17 19:32, Byungchul Park wrote: > cpudl_find() is used to find a cpu having the latest dl. The function > should return the latest cpu among ones satisfying task's affinity and > dl constraint, but current code gives up immediately and just return > fail when it fails at the test *only with* the maximum cpu. > > For example: > > cpu 0 is running a task (dl: 10). > cpu 1 is running a task (dl: 9). > cpu 2 is running a task (dl: 8). > cpu 3 is running a task (dl: 2). > > where cpu 3 want to push a task (affinity is 1 2 3 and dl is 1). Hummm, but this should only happen if you disable admission control, right? Otherwise task's affinity can't be smaller that 0-3. > > In this case, the task should be migrated from cpu 3 to cpu 1, and > preempt cpu 1's task. However, current code just returns fail because > it fails at the affinity test with the maximum cpu, that is, cpu 0. > > This patch set tries to find the best among ones satisfying task's > affinity and dl constraint until success or no more to see. > Anyway, do you have numbers showing how common is you fail scenario? It would be interesting to understand how much the slow path is actually used, IMHO. Thanks, - Juri
[toc] | [prev] | [next] | [standalone]
| From | Byungchul Park <byungchul.park@lge.com> |
|---|---|
| Date | 2017-03-28 02:50 +0200 |
| Subject | Re: [PATCH 0/8] sched/deadline: Return the best satisfying affinity and dl in cpudl_find |
| Message-ID | <tpNuG-7Yq-25@gated-at.bofh.it> |
| In reply to | #1609863 |
On Mon, Mar 27, 2017 at 03:05:07PM +0100, Juri Lelli wrote: > Hi, > > On 23/03/17 19:32, Byungchul Park wrote: > > cpudl_find() is used to find a cpu having the latest dl. The function > > should return the latest cpu among ones satisfying task's affinity and > > dl constraint, but current code gives up immediately and just return > > fail when it fails at the test *only with* the maximum cpu. > > > > For example: > > > > cpu 0 is running a task (dl: 10). > > cpu 1 is running a task (dl: 9). > > cpu 2 is running a task (dl: 8). > > cpu 3 is running a task (dl: 2). > > > > where cpu 3 want to push a task (affinity is 1 2 3 and dl is 1). > > Hummm, but this should only happen if you disable admission control, > right? Otherwise task's affinity can't be smaller that 0-3. Hi Juri, Can I ask you what is addmission control? Do you mean affinity setting? And do you mean s/disable/enable? Or am I misunderstanding? > > > > In this case, the task should be migrated from cpu 3 to cpu 1, and > > preempt cpu 1's task. However, current code just returns fail because > > it fails at the affinity test with the maximum cpu, that is, cpu 0. > > > > This patch set tries to find the best among ones satisfying task's > > affinity and dl constraint until success or no more to see. > > > > Anyway, do you have numbers showing how common is you fail scenario? Actually, it very depends on how to set test environment. I can provide you ones which generate many fails. IMHO, it's not a matter of frequency but a matter of whether it works corrently. As you know, rt policy already works corrently regarding this problem. In other words, if there are dl tasks in a system like: task a (dl: 1) -+ -+ task b (dl: 2) -| -| task c (dl: 3) -| -| task d (dl: 4) -| -+- should be run on 4 cpus machine task e (dl: 5) -| task f (dl: 6) -| task g (dl: 7) -| task h (dl: 8) -+- should be run on 8 cpus machine task i (dl: 9) task j (dl: 10) IMHO, deadline scheduler should ensure most urgent tasks as many as the number of cpus in the system to be run, as long as their affinities are satisfied. What do you think about this? Thanks, Byungchul > It would be interesting to understand how much the slow path is actually > used, IMHO. > > Thanks, > > - Juri
[toc] | [prev] | [next] | [standalone]
| From | Juri Lelli <juri.lelli@arm.com> |
|---|---|
| Date | 2017-03-28 09:20 +0200 |
| Subject | Re: [PATCH 0/8] sched/deadline: Return the best satisfying affinity and dl in cpudl_find |
| Message-ID | <tpTA5-45q-1@gated-at.bofh.it> |
| In reply to | #1610190 |
On 28/03/17 09:42, Byungchul Park wrote: > On Mon, Mar 27, 2017 at 03:05:07PM +0100, Juri Lelli wrote: > > Hi, > > > > On 23/03/17 19:32, Byungchul Park wrote: > > > cpudl_find() is used to find a cpu having the latest dl. The function > > > should return the latest cpu among ones satisfying task's affinity and > > > dl constraint, but current code gives up immediately and just return > > > fail when it fails at the test *only with* the maximum cpu. > > > > > > For example: > > > > > > cpu 0 is running a task (dl: 10). > > > cpu 1 is running a task (dl: 9). > > > cpu 2 is running a task (dl: 8). > > > cpu 3 is running a task (dl: 2). > > > > > > where cpu 3 want to push a task (affinity is 1 2 3 and dl is 1). > > > > Hummm, but this should only happen if you disable admission control, > > right? Otherwise task's affinity can't be smaller that 0-3. > > Hi Juri, > > Can I ask you what is addmission control? Do you mean affinity setting? sched_setattr() for DEADLINE tasks peforms a set of checks before admitting the task to the system. Please have a look at Documentation/ scheduler/sched-deadline.txt::Section5 for what concerns affinity. > And do you mean s/disable/enable? Or am I misunderstanding? > No, I meant disable. The problem is that if you disable admission control the problem you are pointing out can happen, if admission control is enabled otherwise it can't, as we enforce that tasks have affinity equal to the root_domain span to which they belong. E.g, in your case the task will have affinity set to 0-3 (or it won't be able to enter the system), so that would make the problem go away. > > > > > > In this case, the task should be migrated from cpu 3 to cpu 1, and > > > preempt cpu 1's task. However, current code just returns fail because > > > it fails at the affinity test with the maximum cpu, that is, cpu 0. > > > > > > This patch set tries to find the best among ones satisfying task's > > > affinity and dl constraint until success or no more to see. > > > > > > > Anyway, do you have numbers showing how common is you fail scenario? > > Actually, it very depends on how to set test environment. I can provide > you ones which generate many fails. IMHO, it's not a matter of frequency > but a matter of whether it works corrently. As you know, rt policy already > works corrently regarding this problem. > Right. But, my point is that if what you are highlighting turns out to be a pretty frequent situation, maybe we need to find a better data structure to speed up push operations or we will end up using the slow path most of the times, making the heap useless. > In other words, if there are dl tasks in a system like: > > task a (dl: 1) -+ -+ > task b (dl: 2) -| -| > task c (dl: 3) -| -| > task d (dl: 4) -| -+- should be run on 4 cpus machine > task e (dl: 5) -| > task f (dl: 6) -| > task g (dl: 7) -| > task h (dl: 8) -+- should be run on 8 cpus machine > task i (dl: 9) > task j (dl: 10) > > IMHO, deadline scheduler should ensure most urgent tasks as many as the > number of cpus in the system to be run, as long as their affinities are > satisfied. What do you think about this? > Correct. But please read above for what regards affinities.
[toc] | [prev] | [next] | [standalone]
| From | Byungchul Park <byungchul.park@lge.com> |
|---|---|
| Date | 2017-03-28 09:40 +0200 |
| Subject | Re: [PATCH 0/8] sched/deadline: Return the best satisfying affinity and dl in cpudl_find |
| Message-ID | <tpTTr-4eY-3@gated-at.bofh.it> |
| In reply to | #1610376 |
On Tue, Mar 28, 2017 at 08:11:53AM +0100, Juri Lelli wrote: > > > > For example: > > > > > > > > cpu 0 is running a task (dl: 10). > > > > cpu 1 is running a task (dl: 9). > > > > cpu 2 is running a task (dl: 8). > > > > cpu 3 is running a task (dl: 2). > > > > > > > > where cpu 3 want to push a task (affinity is 1 2 3 and dl is 1). > > > > > > Hummm, but this should only happen if you disable admission control, > > > right? Otherwise task's affinity can't be smaller that 0-3. > > > > Hi Juri, > > > > Can I ask you what is addmission control? Do you mean affinity setting? > > sched_setattr() for DEADLINE tasks peforms a set of checks before > admitting the task to the system. Please have a look at Documentation/ > scheduler/sched-deadline.txt::Section5 for what concerns affinity. I see. > > And do you mean s/disable/enable? Or am I misunderstanding? > > > > No, I meant disable. The problem is that if you disable admission > control the problem you are pointing out can happen, if admission > control is enabled otherwise it can't, as we enforce that tasks have > affinity equal to the root_domain span to which they belong. E.g, in > your case the task will have affinity set to 0-3 (or it won't be able to > enter the system), so that would make the problem go away. I see. > > > > In this case, the task should be migrated from cpu 3 to cpu 1, and > > > > preempt cpu 1's task. However, current code just returns fail because > > > > it fails at the affinity test with the maximum cpu, that is, cpu 0. > > > > > > > > This patch set tries to find the best among ones satisfying task's > > > > affinity and dl constraint until success or no more to see. > > > > > > > > > > Anyway, do you have numbers showing how common is you fail scenario? > > > > Actually, it very depends on how to set test environment. I can provide > > you ones which generate many fails. IMHO, it's not a matter of frequency > > but a matter of whether it works corrently. As you know, rt policy already > > works corrently regarding this problem. > > > > Right. But, my point is that if what you are highlighting turns out to > be a pretty frequent situation, maybe we need to find a better data > structure to speed up push operations or we will end up using the slow > path most of the times, making the heap useless. I totally agree with you. I will check it and let you know. Thank you, Byungchul
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web