]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
chrt: Add support for SCHED_FLAG_UTIL_CLAMP
authorFurkan Caliskan <frn1furkan10@gmail.com>
Thu, 14 May 2026 11:52:22 +0000 (14:52 +0300)
committerFurkan Caliskan <frn1furkan10@gmail.com>
Thu, 14 May 2026 12:03:18 +0000 (15:03 +0300)
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 <frn1furkan10@gmail.com>
bash-completion/chrt
schedutils/chrt.1.adoc
schedutils/chrt.c

index ead03b02377d5ac9d2d6eef7573b9fdea8798a93..dc4d3b317cf353134bc61dd0c94b48ae15e990b5 100644 (file)
@@ -18,6 +18,8 @@ _chrt_module()
                        OPTS="
                                --all-tasks
                                --batch
+                               --clamp-max
+                               --clamp-min
                                --deadline
                                --deadline-overrun
                                --ext
index 13a785c7e729e46708a860629f56bf4d991b0069..bd77200237f96cf62dbe64b31b0ed37b9131e88c 100644 (file)
@@ -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.
 +
index cec41468ae702afcdd1431591deea968249f8242..b586a241a4fddd6de93d6f7e1e5bdc96ee473f18 100644 (file)
@@ -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 <ns>  runtime parameter for DEADLINE\n"), out);
        fputs(_(" -P, --sched-period <ns>   period parameter for DEADLINE\n"), out);
        fputs(_(" -D, --sched-deadline <ns> deadline parameter for DEADLINE\n"), out);
+       fputs(_(" -U, --clamp-min <value>   set SCHED_FLAG_UTIL_CLAMP_MIN (0-1024)\n"), out);
+       fputs(_(" -X, --clamp-max <value>   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