From: Furkan Caliskan Date: Thu, 14 May 2026 11:52:22 +0000 (+0300) Subject: chrt: Add support for SCHED_FLAG_UTIL_CLAMP X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9a3143a9ee58f99ae7bca6ac939ada019c7add49;p=thirdparty%2Futil-linux.git chrt: Add support for SCHED_FLAG_UTIL_CLAMP The SCHED_FLAG_UTIL_CLAMP_MIN and SCHED_FLAG_UTIL_CLAMP_MAX flags allow users to set utilization hints for tasks. The minimum clamp tells the scheduler to place the task on a CPU with enough capacity, while the maximum clamp prevents unnecessary CPU frequency boosting. Both accept a value in the range 0-1024, where 1024 represents 100% of maximum CPU capacity. Mainly useful on heterogeneous systems. Add -U/--clamp-min and -X/--clamp-max options to allow users to set these hints for any scheduling policy. Closes: https://github.com/util-linux/util-linux/issues/4339 Signed-off-by: Furkan Caliskan --- diff --git a/bash-completion/chrt b/bash-completion/chrt index ead03b023..dc4d3b317 100644 --- a/bash-completion/chrt +++ b/bash-completion/chrt @@ -18,6 +18,8 @@ _chrt_module() OPTS=" --all-tasks --batch + --clamp-max + --clamp-min --deadline --deadline-overrun --ext diff --git a/schedutils/chrt.1.adoc b/schedutils/chrt.1.adoc index 13a785c7e..bd7720023 100644 --- a/schedutils/chrt.1.adoc +++ b/schedutils/chrt.1.adoc @@ -88,6 +88,12 @@ Enables GRUB (Greedy Reclamation of Unused Bandwidth) algorithm. Linux-specific, *-O*, *--deadline-overrun*:: Set *SCHED_FLAG_DL_OVERRUN* to receive *SIGXCPU* when a *SCHED_DEADLINE* task exceeds its runtime budget within a period. Without this flag the task is silently throttled until the next period. Linux-specific, supported since 4.16. +*-U*, *--clamp-min* _value_:: +Set *SCHED_FLAG_UTIL_CLAMP_MIN* to define the minimum utilization hint for the task (range 0-1024, where 1024 represents 100% of maximum CPU capacity). Tells the scheduler to place the task on a cpu with enough capacity. Linux-specific, supported since 5.3. + +*-X*, *--clamp-max* _value_:: +Set *SCHED_FLAG_UTIL_CLAMP_MAX* to define the maximum utilization cap for the task (range 0-1024). Tells the scheduler not to boost CPU frequency unnecessarily for this task. Linux-specific, supported since 5.3. + *-R*, *--reset-on-fork*:: Use *SCHED_RESET_ON_FORK* or *SCHED_FLAG_RESET_ON_FORK* flag. Linux-specific, supported since 2.6.31. + diff --git a/schedutils/chrt.c b/schedutils/chrt.c index cec41468a..b586a241a 100644 --- a/schedutils/chrt.c +++ b/schedutils/chrt.c @@ -51,6 +51,9 @@ struct chrt_ctl { uint64_t period; uint64_t sched_flags; /* For sched_attr->sched_flags member */ + uint32_t util_min; /* --clamp-min value */ + uint32_t util_max; /* --clamp-max value */ + unsigned int all_tasks : 1, /* all threads of the PID */ reset_on_fork : 1, /* SCHED_RESET_ON_FORK or SCHED_FLAG_RESET_ON_FORK */ altered : 1, /* sched_set**() used */ @@ -97,6 +100,8 @@ static void __attribute__((__noreturn__)) usage(void) fputs(_(" -T, --sched-runtime runtime parameter for DEADLINE\n"), out); fputs(_(" -P, --sched-period period parameter for DEADLINE\n"), out); fputs(_(" -D, --sched-deadline deadline parameter for DEADLINE\n"), out); + fputs(_(" -U, --clamp-min set SCHED_FLAG_UTIL_CLAMP_MIN (0-1024)\n"), out); + fputs(_(" -X, --clamp-max set SCHED_FLAG_UTIL_CLAMP_MAX (0-1024)\n"), out); fputs(USAGE_SEPARATOR, out); fputs(_("Other options:\n"), out); @@ -392,6 +397,8 @@ static int set_sched_one(struct chrt_ctl *ctl, pid_t pid) sa.sched_period = ctl->period; sa.sched_deadline = ctl->deadline; sa.sched_flags = ctl->sched_flags; + sa.sched_util_min = ctl->util_min; + sa.sched_util_max = ctl->util_max; # ifdef SCHED_FLAG_RESET_ON_FORK /* Don't use SCHED_RESET_ON_FORK for sched_setattr()! */ @@ -440,6 +447,8 @@ int main(int argc, char **argv) static const struct option longopts[] = { { "all-tasks", no_argument, NULL, 'a' }, { "batch", no_argument, NULL, 'b' }, + { "clamp-min", required_argument, NULL, 'U' }, + { "clamp-max", required_argument, NULL, 'X' }, { "deadline", no_argument, NULL, 'd' }, { "deadline-overrun", no_argument, NULL, 'O' }, { "ext", no_argument, NULL, 'e' }, @@ -465,7 +474,7 @@ int main(int argc, char **argv) textdomain(PACKAGE); close_stdout_atexit(); - while((c = getopt_long(argc, argv, "+abdD:efiphmoOP:T:rRGvV", longopts, NULL)) != -1) + while((c = getopt_long(argc, argv, "+abdD:efiphmoOP:T:rRU:X:GvV", longopts, NULL)) != -1) { switch (c) { case 'a': @@ -506,6 +515,22 @@ int main(int argc, char **argv) case 'O': #ifdef SCHED_FLAG_DL_OVERRUN ctl->sched_flags |= SCHED_FLAG_DL_OVERRUN; +#endif + break; + case 'U': +#ifdef SCHED_FLAG_UTIL_CLAMP_MIN + ctl->sched_flags |= SCHED_FLAG_UTIL_CLAMP_MIN; + ctl->util_min = strtou32_or_err(optarg, _("invalid --clamp-min value")); + if (ctl->util_min > 1024) + errx(EXIT_FAILURE, _("--clamp-min value must be in range 0-1024")); +#endif + break; + case 'X': +#ifdef SCHED_FLAG_UTIL_CLAMP_MAX + ctl->sched_flags |= SCHED_FLAG_UTIL_CLAMP_MAX; + ctl->util_max = strtou32_or_err(optarg, _("invalid --clamp-max value")); + if (ctl->util_max > 1024) + errx(EXIT_FAILURE, _("--clamp-max value must be in range 0-1024")); #endif break; case 'i': @@ -612,6 +637,17 @@ int main(int argc, char **argv) if ((ctl->sched_flags & SCHED_FLAG_DL_OVERRUN) && ctl->policy != SCHED_DEADLINE) errx(EXIT_FAILURE, _("--deadline-overrun is only supported for SCHED_DEADLINE")); # endif + +#ifndef HAVE_SCHED_SETATTR +# ifdef SCHED_FLAG_UTIL_CLAMP_MIN + if (ctl->sched_flags & SCHED_FLAG_UTIL_CLAMP_MIN) + errx(EXIT_FAILURE, _("SCHED_FLAG_UTIL_CLAMP_MIN is unsupported")); +# endif +# ifdef SCHED_FLAG_UTIL_CLAMP_MAX + if (ctl->sched_flags & SCHED_FLAG_UTIL_CLAMP_MAX) + errx(EXIT_FAILURE, _("SCHED_FLAG_UTIL_CLAMP_MAX is unsupported")); +# endif +#endif if (ctl->policy == SCHED_DEADLINE) { /* The basic rule is runtime <= deadline <= period, so we can * make deadline and runtime optional on command line. Note we