]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
cpuset: Use stride in cpulist_create
authorJesse Rosenstock <jmr@google.com>
Tue, 1 Jul 2025 10:38:24 +0000 (12:38 +0200)
committerJesse Rosenstock <jmr@google.com>
Tue, 8 Jul 2025 10:21:42 +0000 (12:21 +0200)
Format cpu lists for `taskset -c`, `lscpu`, etc. using stride.  This
usually produces shorter output.

Now:
% ./taskset -c 0-24:2,25-47:4 ./taskset -pc 0
pid 3937653's current affinity list: 0-24:2,25-45:4

Previously:
% ./taskset -c 0-23:2,24-47:4 ./taskset -pc 0
pid 3933321's current affinity list: 0,2,4,6,8,10,12,14,16,18,20,22,24,28,32,36,40,44

The ranges are constructed greedily; in general it is difficult to
construct a minimal list.
% ./taskset -c 0-63:3,0-63:4 ./taskset -pc 0
pid 3926213's current affinity list: 0,3,4-8:2,9-15:3,16-20:2,21-27:3,28-32:2,33-39:3,40-44:2,45

Signed-off-by: Jesse Rosenstock <jmr@google.com>
lib/cpuset.c
tests/expected/lscpu/lscpu-x86_64-64cpu
tests/expected/misc/bits-list
tests/expected/misc/bits-parse-mask
tests/expected/schedutils/cpuset

index 533b8ab309b1d222558cbfc4b88e9c96aee48e42..d6469203092d244e205dcabe3e2dd15b36afae1b 100644 (file)
@@ -147,43 +147,70 @@ int __cpuset_count_s(size_t setsize, const cpu_set_t *set)
 }
 #endif
 
+/*
+ * Finds the first CPU present after the specified index.
+ *
+ * start: starting index, inclusive.
+ * setsize: size of the set in *bytes*.
+ * set: CPU set to search.
+ *
+ * Return: the index of the first CPU present in `set`, starting at `start`.
+ * If no such CPU exists, returns the size of the set in *bits*.
+ */
+static size_t find_next_cpu(size_t start, size_t setsize, cpu_set_t *set)
+{
+       size_t nbits = cpuset_nbits(setsize);
+       for (; start < nbits; start++)
+               if (CPU_ISSET_S(start, setsize, set))
+                       return start;
+       return start;
+}
+
 /*
  * Returns human readable representation of the cpuset. The output format is
- * a list of CPUs with ranges (for example, "0,1,3-9").
+ * a list of CPUs with ranges (for example, "0,1,3-9:3").
  */
 char *cpulist_create(char *str, size_t len,
                        cpu_set_t *set, size_t setsize)
 {
-       size_t i;
        char *ptr = str;
        int entry_made = 0;
        size_t max = cpuset_nbits(setsize);
-
-       for (i = 0; i < max; i++) {
-               if (CPU_ISSET_S(i, setsize, set)) {
-                       int rlen;
-                       size_t j, run = 0;
-                       entry_made = 1;
-                       for (j = i + 1; j < max; j++) {
-                               if (CPU_ISSET_S(j, setsize, set))
-                                       run++;
-                               else
-                                       break;
+       size_t a = 0;  /* min for cpu range */
+       size_t next = 0;  /* where to start looking for next cpu */
+
+       while ((a = find_next_cpu(next, setsize, set)) < max) {
+               int rlen;
+               next = find_next_cpu(a + 1, setsize, set);
+               if (next == max) {
+                       rlen = snprintf(ptr, len, "%zu,", a);
+               } else {
+                       /* Extend range as long as we have the same stride. */
+                       size_t b = next;
+                       size_t s = b - a;
+                       while (((next = find_next_cpu(b + 1, setsize, set)) <
+                               max) && next - b == s) {
+                               b = next;
                        }
-                       if (!run)
-                               rlen = snprintf(ptr, len, "%zu,", i);
-                       else if (run == 1) {
-                               rlen = snprintf(ptr, len, "%zu,%zu,", i, i + 1);
-                               i++;
+                       if (b - a == s) {
+                               /*
+                                * Only print one CPU.  Hope the next one can
+                                * be put in the next range.
+                                */
+                               rlen = snprintf(ptr, len, "%zu,", a);
+                               next = b;
+                       } else if (s == 1) {
+                               rlen = snprintf(ptr, len, "%zu-%zu,", a, b);
                        } else {
-                               rlen = snprintf(ptr, len, "%zu-%zu,", i, i + run);
-                               i += run;
+                               rlen = snprintf(ptr, len, "%zu-%zu:%zu,",
+                                               a, b, s);
                        }
-                       if (rlen < 0 || (size_t) rlen >= len)
-                               return NULL;
-                       ptr += rlen;
-                       len -= rlen;
                }
+               if (rlen < 0 || (size_t) rlen >= len)
+                       return NULL;
+               ptr += rlen;
+               len -= rlen;
+               entry_made = 1;
        }
        ptr -= entry_made;
        *ptr = '\0';
index b5b6c85c322fd45638ca154ffa139c1d321beee9..d359a6875e6a93f93e241dfb3a050e8c4a084334 100644 (file)
@@ -21,9 +21,9 @@ L1i cache:           1 MiB (32 instances)
 L2 cache:            8 MiB (32 instances)
 L3 cache:            72 MiB (4 instances)
 NUMA node(s):        3
-NUMA node0 CPU(s):   0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58,60,62
-NUMA node2 CPU(s):   1,5,9,13,17,21,25,29,33,37,41,45,49,53,57,61
-NUMA node3 CPU(s):   3,7,11,15,19,23,27,31,35,39,43,47,51,55,59,63
+NUMA node0 CPU(s):   0-62:2
+NUMA node2 CPU(s):   1-61:4
+NUMA node3 CPU(s):   3-63:4
 
 # The following is the parsable format, which can be fed to other
 # programs. Each different item in every column has an unique ID
index 7511e5378ea4d9dfeb74254975205dd3efec4435..e6c6d142a2fbf1a6070d431f824f9475a89f4f6c 100644 (file)
@@ -1 +1 @@
-11,22,33,44
+11-44:11
index 59dd4b4c16964eb60d1edcd9a2cbd4d3ad1d0a41..37b1257b85e7030e9c822b043495a33ca7978501 100644 (file)
@@ -1 +1 @@
-1,3,6,7,9,11,14-16,18,19,21,23-25,27
+1,3,6,7-11:2,14-16,18,19-23:2,24,25,27
index 10e17606c0eddbd2e1190f88e9a18fdfc7adfd5b..695e75dc9f62e61a1e91a314a584a67140970a1b 100644 (file)
@@ -8,7 +8,7 @@ masks:
 0x00000007      =               7 [0-2]
 0x00000008      =               8 [3]
 0x00000009      =               9 [0,3]
-0x00005555      =            5555 [0,2,4,6,8,10,12,14]
+0x00005555      =            5555 [0-14:2]
 0x00007777      =            7777 [0-2,4-6,8-10,12-14]
 strings:
 0               =               1 [0]
@@ -20,5 +20,5 @@ strings:
 0-2             =               7 [0-2]
 3               =               8 [3]
 0,3             =               9 [0,3]
-0,2,4,6,8,10,12,14 =            5555 [0,2,4,6,8,10,12,14]
+0,2,4,6,8,10,12,14 =            5555 [0-14:2]
 0-2,4-6,8-10,12-14 =            7777 [0-2,4-6,8-10,12-14]