From: Xuewen Yan <xuewen.yan@xxxxxxxxxx> The uclamp can clamp the util within uclamp_min and uclamp_max, it is benifit to some tasks with small util, but for those tasks with middle util, it is useless. To speed up those tasks, convert UCLAMP_MIN to BOOST, the BOOST as schedtune does: boot = uclamp_min / SCHED_CAPACITY_SCALE; margin = boost * (uclamp_max - util) boost_util = util + margin; Scenario: if the task_util = 200, {uclamp_min, uclamp_max} = {100, 1024} without patch: clamp_util = 200; with patch: clamp_util = 200 + (100 / 1024) * (1024 - 200) = 280; On the other hand, adding a SYS interface to allow users to configure it according to their own needs. Signed-off-by: Xuewen Yan <xuewen.yan@xxxxxxxxxx> --- include/linux/sched/sysctl.h | 1 + kernel/sched/core.c | 19 +++++++++++++++++++ kernel/sched/fair.c | 15 ++++++++++++--- kernel/sched/sched.h | 10 +++++++++- kernel/sysctl.c | 9 +++++++++ 5 files changed, 50 insertions(+), 4 deletions(-) diff --git a/include/linux/sched/sysctl.h b/include/linux/sched/sysctl.h index db2c0f34aaaf..97d8c5ecd4e6 100644 --- a/include/linux/sched/sysctl.h +++ b/include/linux/sched/sysctl.h @@ -69,6 +69,7 @@ extern unsigned int sysctl_sched_dl_period_min; extern unsigned int sysctl_sched_uclamp_util_min; extern unsigned int sysctl_sched_uclamp_util_max; extern unsigned int sysctl_sched_uclamp_util_min_rt_default; +extern unsigned int sysctl_sched_uclamp_min_to_boost; #endif #ifdef CONFIG_CFS_BANDWIDTH diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 2d9ff40f4661..8a49f9962cda 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -1245,6 +1245,9 @@ unsigned int sysctl_sched_uclamp_util_max = SCHED_CAPACITY_SCALE; */ unsigned int sysctl_sched_uclamp_util_min_rt_default = SCHED_CAPACITY_SCALE; +/* map util clamp_min to boost */ +unsigned int sysctl_sched_uclamp_min_to_boost; + /* All clamps are required to be less or equal than these values */ static struct uclamp_se uclamp_default[UCLAMP_CNT]; @@ -1448,6 +1451,22 @@ uclamp_eff_get(struct task_struct *p, enum uclamp_id clamp_id) return uc_req; } +unsigned long uclamp_transform_boost(unsigned long util, unsigned long uclamp_min, + unsigned long uclamp_max) +{ + unsigned long margin; + + if (unlikely(uclamp_min > uclamp_max)) + return util; + + if (util >= uclamp_max) + return uclamp_max; + + margin = DIV_ROUND_CLOSEST_ULL(uclamp_min * (uclamp_max - util), + SCHED_CAPACITY_SCALE); + return util + margin; +} + unsigned long uclamp_eff_value(struct task_struct *p, enum uclamp_id clamp_id) { struct uclamp_se uc_eff; diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 44c452072a1b..790dfbb6c897 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -3934,9 +3934,18 @@ static inline unsigned long task_util_est(struct task_struct *p) #ifdef CONFIG_UCLAMP_TASK static inline unsigned long uclamp_task_util(struct task_struct *p) { - return clamp(task_util_est(p), - uclamp_eff_value(p, UCLAMP_MIN), - uclamp_eff_value(p, UCLAMP_MAX)); + unsigned long min_util = uclamp_eff_value(p, UCLAMP_MIN); + unsigned long max_util = uclamp_eff_value(p, UCLAMP_MAX); + unsigned long clamp_util, util; + + util = task_util_est(p); + + if (sysctl_sched_uclamp_min_to_boost) + clamp_util = uclamp_transform_boost(util, min_util, max_util); + else + clamp_util = clamp(util, min_util, max_util); + + return clamp_util; } #else static inline unsigned long uclamp_task_util(struct task_struct *p) diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index 14a41a243f7b..73657be84678 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -2796,6 +2796,8 @@ static inline void cpufreq_update_util(struct rq *rq, unsigned int flags) {} #ifdef CONFIG_UCLAMP_TASK unsigned long uclamp_eff_value(struct task_struct *p, enum uclamp_id clamp_id); +unsigned long uclamp_transform_boost(unsigned long util, unsigned long uclamp_min, + unsigned long uclamp_max); /** * uclamp_rq_util_with - clamp @util with @rq and @p effective uclamp values. @@ -2820,6 +2822,7 @@ unsigned long uclamp_rq_util_with(struct rq *rq, unsigned long util, { unsigned long min_util = 0; unsigned long max_util = 0; + unsigned long clamp_util; if (!static_branch_likely(&sched_uclamp_used)) return util; @@ -2847,7 +2850,12 @@ unsigned long uclamp_rq_util_with(struct rq *rq, unsigned long util, if (unlikely(min_util >= max_util)) return min_util; - return clamp(util, min_util, max_util); + if (sysctl_sched_uclamp_min_to_boost) + clamp_util = uclamp_transform_boost(util, min_util, max_util); + else + clamp_util = clamp(util, min_util, max_util); + + return clamp_util; } /* diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 272f4a272f8c..b3a83356a969 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -1827,6 +1827,15 @@ static struct ctl_table kern_table[] = { .mode = 0644, .proc_handler = sysctl_sched_uclamp_handler, }, + { + .procname = "sched_clamp_min2boost", + .data = &sysctl_sched_uclamp_min_to_boost, + .maxlen = sizeof(unsigned int), + .mode = 0644, + .proc_handler = proc_dointvec_minmax, + .extra1 = SYSCTL_ZERO, + .extra2 = SYSCTL_ONE, + }, #endif #ifdef CONFIG_SCHED_AUTOGROUP { -- 2.25.1