]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
perf record: Adapt affinity to machines with #CPUs > 1K
authorAlexey Budankov <alexey.budankov@linux.intel.com>
Tue, 3 Dec 2019 11:45:27 +0000 (14:45 +0300)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Mon, 6 Jan 2020 14:46:09 +0000 (11:46 -0300)
Use struct mmap_cpu_mask type for the tool's thread and mmap data
buffers to overcome current 1024 CPUs mask size limitation of cpu_set_t
type.

Currently glibc's cpu_set_t type has an internal mask size limit of 1024
CPUs.

Moving to the 'struct mmap_cpu_mask' type allows overcoming that limit.

The tools bitmap API is used to manipulate objects of 'struct mmap_cpu_mask'
type.

Committer notes:

To print the 'nbits' struct member we must use %zd, since it is a
size_t, this fixes the build in some toolchains/arches.

Reported-by: Andi Kleen <ak@linux.intel.com>
Signed-off-by: Alexey Budankov <alexey.budankov@linux.intel.com>
Acked-by: Jiri Olsa <jolsa@redhat.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lore.kernel.org/lkml/96d7e2ff-ce8b-c1e0-d52c-aa59ea96f0ea@linux.intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/builtin-record.c
tools/perf/util/mmap.c
tools/perf/util/mmap.h

index fb19ef63cc35fa78ad1a7a2318031ff70a770fe0..4c301466101baea9803f7a236fa1da3ed0396a80 100644 (file)
@@ -62,6 +62,7 @@
 #include <linux/string.h>
 #include <linux/time64.h>
 #include <linux/zalloc.h>
+#include <linux/bitmap.h>
 
 struct switch_output {
        bool             enabled;
@@ -93,7 +94,7 @@ struct record {
        bool                    timestamp_boundary;
        struct switch_output    switch_output;
        unsigned long long      samples;
-       cpu_set_t               affinity_mask;
+       struct mmap_cpu_mask    affinity_mask;
        unsigned long           output_max_size;        /* = 0: unlimited */
 };
 
@@ -961,10 +962,15 @@ static struct perf_event_header finished_round_event = {
 static void record__adjust_affinity(struct record *rec, struct mmap *map)
 {
        if (rec->opts.affinity != PERF_AFFINITY_SYS &&
-           !CPU_EQUAL(&rec->affinity_mask, &map->affinity_mask)) {
-               CPU_ZERO(&rec->affinity_mask);
-               CPU_OR(&rec->affinity_mask, &rec->affinity_mask, &map->affinity_mask);
-               sched_setaffinity(0, sizeof(rec->affinity_mask), &rec->affinity_mask);
+           !bitmap_equal(rec->affinity_mask.bits, map->affinity_mask.bits,
+                         rec->affinity_mask.nbits)) {
+               bitmap_zero(rec->affinity_mask.bits, rec->affinity_mask.nbits);
+               bitmap_or(rec->affinity_mask.bits, rec->affinity_mask.bits,
+                         map->affinity_mask.bits, rec->affinity_mask.nbits);
+               sched_setaffinity(0, MMAP_CPU_MASK_BYTES(&rec->affinity_mask),
+                                 (cpu_set_t *)rec->affinity_mask.bits);
+               if (verbose == 2)
+                       mmap_cpu_mask__scnprintf(&rec->affinity_mask, "thread");
        }
 }
 
@@ -2433,7 +2439,6 @@ int cmd_record(int argc, const char **argv)
 # undef REASON
 #endif
 
-       CPU_ZERO(&rec->affinity_mask);
        rec->opts.affinity = PERF_AFFINITY_SYS;
 
        rec->evlist = evlist__new();
@@ -2499,6 +2504,16 @@ int cmd_record(int argc, const char **argv)
 
        symbol__init(NULL);
 
+       if (rec->opts.affinity != PERF_AFFINITY_SYS) {
+               rec->affinity_mask.nbits = cpu__max_cpu();
+               rec->affinity_mask.bits = bitmap_alloc(rec->affinity_mask.nbits);
+               if (!rec->affinity_mask.bits) {
+                       pr_err("Failed to allocate thread mask for %zd cpus\n", rec->affinity_mask.nbits);
+                       return -ENOMEM;
+               }
+               pr_debug2("thread mask[%zd]: empty\n", rec->affinity_mask.nbits);
+       }
+
        err = record__auxtrace_init(rec);
        if (err)
                goto out;
@@ -2613,6 +2628,7 @@ int cmd_record(int argc, const char **argv)
 
        err = __cmd_record(&record, argc, argv);
 out:
+       bitmap_free(rec->affinity_mask.bits);
        evlist__delete(rec->evlist);
        symbol__exit();
        auxtrace_record__free(rec->itr);
index 2ee4faacca21f53c2ceb7f465d3c82a2a2d8592c..3b664fa673a6ce031b492e84ad2964c3814fb833 100644 (file)
@@ -219,6 +219,8 @@ static void perf_mmap__aio_munmap(struct mmap *map __maybe_unused)
 
 void mmap__munmap(struct mmap *map)
 {
+       bitmap_free(map->affinity_mask.bits);
+
        perf_mmap__aio_munmap(map);
        if (map->data != NULL) {
                munmap(map->data, mmap__mmap_len(map));
@@ -227,7 +229,7 @@ void mmap__munmap(struct mmap *map)
        auxtrace_mmap__munmap(&map->auxtrace_mmap);
 }
 
-static void build_node_mask(int node, cpu_set_t *mask)
+static void build_node_mask(int node, struct mmap_cpu_mask *mask)
 {
        int c, cpu, nr_cpus;
        const struct perf_cpu_map *cpu_map = NULL;
@@ -240,17 +242,23 @@ static void build_node_mask(int node, cpu_set_t *mask)
        for (c = 0; c < nr_cpus; c++) {
                cpu = cpu_map->map[c]; /* map c index to online cpu index */
                if (cpu__get_node(cpu) == node)
-                       CPU_SET(cpu, mask);
+                       set_bit(cpu, mask->bits);
        }
 }
 
-static void perf_mmap__setup_affinity_mask(struct mmap *map, struct mmap_params *mp)
+static int perf_mmap__setup_affinity_mask(struct mmap *map, struct mmap_params *mp)
 {
-       CPU_ZERO(&map->affinity_mask);
+       map->affinity_mask.nbits = cpu__max_cpu();
+       map->affinity_mask.bits = bitmap_alloc(map->affinity_mask.nbits);
+       if (!map->affinity_mask.bits)
+               return -1;
+
        if (mp->affinity == PERF_AFFINITY_NODE && cpu__max_node() > 1)
                build_node_mask(cpu__get_node(map->core.cpu), &map->affinity_mask);
        else if (mp->affinity == PERF_AFFINITY_CPU)
-               CPU_SET(map->core.cpu, &map->affinity_mask);
+               set_bit(map->core.cpu, map->affinity_mask.bits);
+
+       return 0;
 }
 
 int mmap__mmap(struct mmap *map, struct mmap_params *mp, int fd, int cpu)
@@ -261,7 +269,15 @@ int mmap__mmap(struct mmap *map, struct mmap_params *mp, int fd, int cpu)
                return -1;
        }
 
-       perf_mmap__setup_affinity_mask(map, mp);
+       if (mp->affinity != PERF_AFFINITY_SYS &&
+               perf_mmap__setup_affinity_mask(map, mp)) {
+               pr_debug2("failed to alloc mmap affinity mask, error %d\n",
+                         errno);
+               return -1;
+       }
+
+       if (verbose == 2)
+               mmap_cpu_mask__scnprintf(&map->affinity_mask, "mmap");
 
        map->core.flush = mp->flush;
 
index ef51667fabcbe5463b59c90bac1c324e1a211098..9d5f589f02ae70e187539ad08202157c08801771 100644 (file)
@@ -40,7 +40,7 @@ struct mmap {
                int              nr_cblocks;
        } aio;
 #endif
-       cpu_set_t       affinity_mask;
+       struct mmap_cpu_mask    affinity_mask;
        void            *data;
        int             comp_level;
 };