aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrick Bellasi <patrick.bellasi@arm.com>2019-08-22 09:28:07 -0400
committerIngo Molnar <mingo@kernel.org>2019-09-03 03:17:38 -0400
commit0b60ba2dd342016e4e717dbaa4ca9af3a43f4434 (patch)
tree14a10f68a478842e0be1d676bca92c818618dc9b
parent2480c093130f64ac3a410504fa8b3db1fc4b87ce (diff)
sched/uclamp: Propagate parent clamps
In order to properly support hierarchical resources control, the cgroup delegation model requires that attribute writes from a child group never fail but still are locally consistent and constrained based on parent's assigned resources. This requires to properly propagate and aggregate parent attributes down to its descendants. Implement this mechanism by adding a new "effective" clamp value for each task group. The effective clamp value is defined as the smaller value between the clamp value of a group and the effective clamp value of its parent. This is the actual clamp value enforced on tasks in a task group. Since it's possible for a cpu.uclamp.min value to be bigger than the cpu.uclamp.max value, ensure local consistency by restricting each "protection" (i.e. min utilization) with the corresponding "limit" (i.e. max utilization). Do that at effective clamps propagation to ensure all user-space write never fails while still always tracking the most restrictive values. Signed-off-by: Patrick Bellasi <patrick.bellasi@arm.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Reviewed-by: Michal Koutny <mkoutny@suse.com> Acked-by: Tejun Heo <tj@kernel.org> Cc: Alessio Balsini <balsini@android.com> Cc: Dietmar Eggemann <dietmar.eggemann@arm.com> Cc: Joel Fernandes <joelaf@google.com> Cc: Juri Lelli <juri.lelli@redhat.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Morten Rasmussen <morten.rasmussen@arm.com> Cc: Paul Turner <pjt@google.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Quentin Perret <quentin.perret@arm.com> Cc: Rafael J . Wysocki <rafael.j.wysocki@intel.com> Cc: Steve Muckle <smuckle@google.com> Cc: Suren Baghdasaryan <surenb@google.com> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Todd Kjos <tkjos@google.com> Cc: Vincent Guittot <vincent.guittot@linaro.org> Cc: Viresh Kumar <viresh.kumar@linaro.org> Link: https://lkml.kernel.org/r/20190822132811.31294-3-patrick.bellasi@arm.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--kernel/sched/core.c44
-rw-r--r--kernel/sched/sched.h2
2 files changed, 46 insertions, 0 deletions
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index c186abed5c6d..8855481857b5 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -1166,6 +1166,7 @@ static void __init init_uclamp(void)
1166 uclamp_default[clamp_id] = uc_max; 1166 uclamp_default[clamp_id] = uc_max;
1167#ifdef CONFIG_UCLAMP_TASK_GROUP 1167#ifdef CONFIG_UCLAMP_TASK_GROUP
1168 root_task_group.uclamp_req[clamp_id] = uc_max; 1168 root_task_group.uclamp_req[clamp_id] = uc_max;
1169 root_task_group.uclamp[clamp_id] = uc_max;
1169#endif 1170#endif
1170 } 1171 }
1171} 1172}
@@ -6824,6 +6825,7 @@ static inline void alloc_uclamp_sched_group(struct task_group *tg,
6824 for_each_clamp_id(clamp_id) { 6825 for_each_clamp_id(clamp_id) {
6825 uclamp_se_set(&tg->uclamp_req[clamp_id], 6826 uclamp_se_set(&tg->uclamp_req[clamp_id],
6826 uclamp_none(clamp_id), false); 6827 uclamp_none(clamp_id), false);
6828 tg->uclamp[clamp_id] = parent->uclamp[clamp_id];
6827 } 6829 }
6828#endif 6830#endif
6829} 6831}
@@ -7070,6 +7072,45 @@ static void cpu_cgroup_attach(struct cgroup_taskset *tset)
7070} 7072}
7071 7073
7072#ifdef CONFIG_UCLAMP_TASK_GROUP 7074#ifdef CONFIG_UCLAMP_TASK_GROUP
7075static void cpu_util_update_eff(struct cgroup_subsys_state *css)
7076{
7077 struct cgroup_subsys_state *top_css = css;
7078 struct uclamp_se *uc_parent = NULL;
7079 struct uclamp_se *uc_se = NULL;
7080 unsigned int eff[UCLAMP_CNT];
7081 unsigned int clamp_id;
7082 unsigned int clamps;
7083
7084 css_for_each_descendant_pre(css, top_css) {
7085 uc_parent = css_tg(css)->parent
7086 ? css_tg(css)->parent->uclamp : NULL;
7087
7088 for_each_clamp_id(clamp_id) {
7089 /* Assume effective clamps matches requested clamps */
7090 eff[clamp_id] = css_tg(css)->uclamp_req[clamp_id].value;
7091 /* Cap effective clamps with parent's effective clamps */
7092 if (uc_parent &&
7093 eff[clamp_id] > uc_parent[clamp_id].value) {
7094 eff[clamp_id] = uc_parent[clamp_id].value;
7095 }
7096 }
7097 /* Ensure protection is always capped by limit */
7098 eff[UCLAMP_MIN] = min(eff[UCLAMP_MIN], eff[UCLAMP_MAX]);
7099
7100 /* Propagate most restrictive effective clamps */
7101 clamps = 0x0;
7102 uc_se = css_tg(css)->uclamp;
7103 for_each_clamp_id(clamp_id) {
7104 if (eff[clamp_id] == uc_se[clamp_id].value)
7105 continue;
7106 uc_se[clamp_id].value = eff[clamp_id];
7107 uc_se[clamp_id].bucket_id = uclamp_bucket_id(eff[clamp_id]);
7108 clamps |= (0x1 << clamp_id);
7109 }
7110 if (!clamps)
7111 css = css_rightmost_descendant(css);
7112 }
7113}
7073 7114
7074/* 7115/*
7075 * Integer 10^N with a given N exponent by casting to integer the literal "1eN" 7116 * Integer 10^N with a given N exponent by casting to integer the literal "1eN"
@@ -7138,6 +7179,9 @@ static ssize_t cpu_uclamp_write(struct kernfs_open_file *of, char *buf,
7138 */ 7179 */
7139 tg->uclamp_pct[clamp_id] = req.percent; 7180 tg->uclamp_pct[clamp_id] = req.percent;
7140 7181
7182 /* Update effective clamps to track the most restrictive value */
7183 cpu_util_update_eff(of_css(of));
7184
7141 rcu_read_unlock(); 7185 rcu_read_unlock();
7142 mutex_unlock(&uclamp_mutex); 7186 mutex_unlock(&uclamp_mutex);
7143 7187
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index ae1be61fb279..5b343112a47b 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -397,6 +397,8 @@ struct task_group {
397 unsigned int uclamp_pct[UCLAMP_CNT]; 397 unsigned int uclamp_pct[UCLAMP_CNT];
398 /* Clamp values requested for a task group */ 398 /* Clamp values requested for a task group */
399 struct uclamp_se uclamp_req[UCLAMP_CNT]; 399 struct uclamp_se uclamp_req[UCLAMP_CNT];
400 /* Effective clamp values used for a task group */
401 struct uclamp_se uclamp[UCLAMP_CNT];
400#endif 402#endif
401 403
402}; 404};