[PATCH] cpuset: Use stride in cpulist_create

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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

The patch below uses spaces because gmail hates tabs. Tabs are used in the PR.

https://github.com/util-linux/util-linux/pull/3646

Signed-off-by: Jesse Rosenstock <jmr@xxxxxxxxxx>
---
 lib/cpuset.c                            | 75 +++++++++++++++++--------
 tests/expected/lscpu/lscpu-x86_64-64cpu |  6 +-
 tests/expected/misc/bits-list           |  2 +-
 tests/expected/misc/bits-parse-mask     |  2 +-
 tests/expected/schedutils/cpuset        |  4 +-
 5 files changed, 58 insertions(+), 31 deletions(-)

diff --git a/lib/cpuset.c b/lib/cpuset.c
index 533b8ab309b..d6469203092 100644
--- a/lib/cpuset.c
+++ b/lib/cpuset.c
@@ -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';
diff --git a/tests/expected/lscpu/lscpu-x86_64-64cpu
b/tests/expected/lscpu/lscpu-x86_64-64cpu
index b5b6c85c322..d359a6875e6 100644
--- a/tests/expected/lscpu/lscpu-x86_64-64cpu
+++ b/tests/expected/lscpu/lscpu-x86_64-64cpu
@@ -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
diff --git a/tests/expected/misc/bits-list b/tests/expected/misc/bits-list
index 7511e5378ea..e6c6d142a2f 100644
--- a/tests/expected/misc/bits-list
+++ b/tests/expected/misc/bits-list
@@ -1 +1 @@
-11,22,33,44
+11-44:11
diff --git a/tests/expected/misc/bits-parse-mask
b/tests/expected/misc/bits-parse-mask
index 59dd4b4c169..37b1257b85e 100644
--- a/tests/expected/misc/bits-parse-mask
+++ b/tests/expected/misc/bits-parse-mask
@@ -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
diff --git a/tests/expected/schedutils/cpuset b/tests/expected/schedutils/cpuset
index 10e17606c0e..695e75dc9f6 100644
--- a/tests/expected/schedutils/cpuset
+++ b/tests/expected/schedutils/cpuset
@@ -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]




[Index of Archives]     [Netdev]     [Ethernet Bridging]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux