libperf: Add perf_cpu_map__new()/perf_cpu_map__read() functions

Moving the following functions from tools/perf:

  cpu_map__new()
  cpu_map__read()

to libperf with the following names:

  perf_cpu_map__new()
  perf_cpu_map__read()

Committer notes:

Fixed up this one:

  tools/perf/arch/arm/util/cs-etm.c

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Alexey Budankov <alexey.budankov@linux.intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Michael Petlan <mpetlan@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20190721112506.12306-44-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
Jiri Olsa 2019-07-21 13:24:30 +02:00 committed by Arnaldo Carvalho de Melo
parent 1fc632cef4
commit 9c3516d1b8
37 changed files with 265 additions and 227 deletions

View File

@ -156,7 +156,7 @@ static int cs_etm_set_option(struct auxtrace_record *itr,
{ {
int i, err = -EINVAL; int i, err = -EINVAL;
struct perf_cpu_map *event_cpus = evsel->evlist->cpus; struct perf_cpu_map *event_cpus = evsel->evlist->cpus;
struct perf_cpu_map *online_cpus = cpu_map__new(NULL); struct perf_cpu_map *online_cpus = perf_cpu_map__new(NULL);
/* Set option of each CPU we have */ /* Set option of each CPU we have */
for (i = 0; i < cpu__max_cpu(); i++) { for (i = 0; i < cpu__max_cpu(); i++) {
@ -490,7 +490,7 @@ cs_etm_info_priv_size(struct auxtrace_record *itr __maybe_unused,
int i; int i;
int etmv3 = 0, etmv4 = 0; int etmv3 = 0, etmv4 = 0;
struct perf_cpu_map *event_cpus = evlist->cpus; struct perf_cpu_map *event_cpus = evlist->cpus;
struct perf_cpu_map *online_cpus = cpu_map__new(NULL); struct perf_cpu_map *online_cpus = perf_cpu_map__new(NULL);
/* cpu map is not empty, we have specific CPUs to work with */ /* cpu map is not empty, we have specific CPUs to work with */
if (!cpu_map__empty(event_cpus)) { if (!cpu_map__empty(event_cpus)) {
@ -637,7 +637,7 @@ static int cs_etm_info_fill(struct auxtrace_record *itr,
u64 nr_cpu, type; u64 nr_cpu, type;
struct perf_cpu_map *cpu_map; struct perf_cpu_map *cpu_map;
struct perf_cpu_map *event_cpus = session->evlist->cpus; struct perf_cpu_map *event_cpus = session->evlist->cpus;
struct perf_cpu_map *online_cpus = cpu_map__new(NULL); struct perf_cpu_map *online_cpus = perf_cpu_map__new(NULL);
struct cs_etm_recording *ptr = struct cs_etm_recording *ptr =
container_of(itr, struct cs_etm_recording, itr); container_of(itr, struct cs_etm_recording, itr);
struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu; struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu;

View File

@ -5,6 +5,7 @@
#include <unistd.h> #include <unistd.h>
#include <linux/types.h> #include <linux/types.h>
#include <sys/prctl.h> #include <sys/prctl.h>
#include <perf/cpumap.h>
#include "parse-events.h" #include "parse-events.h"
#include "evlist.h" #include "evlist.h"
@ -65,7 +66,7 @@ int test__perf_time_to_tsc(struct test *test __maybe_unused, int subtest __maybe
threads = thread_map__new(-1, getpid(), UINT_MAX); threads = thread_map__new(-1, getpid(), UINT_MAX);
CHECK_NOT_NULL__(threads); CHECK_NOT_NULL__(threads);
cpus = cpu_map__new(NULL); cpus = perf_cpu_map__new(NULL);
CHECK_NOT_NULL__(cpus); CHECK_NOT_NULL__(cpus);
evlist = evlist__new(); evlist = evlist__new();

View File

@ -20,6 +20,7 @@
#include <sys/resource.h> #include <sys/resource.h>
#include <sys/epoll.h> #include <sys/epoll.h>
#include <sys/eventfd.h> #include <sys/eventfd.h>
#include <perf/cpumap.h>
#include "../util/stat.h" #include "../util/stat.h"
#include <subcmd/parse-options.h> #include <subcmd/parse-options.h>
@ -315,7 +316,7 @@ int bench_epoll_ctl(int argc, const char **argv)
act.sa_sigaction = toggle_done; act.sa_sigaction = toggle_done;
sigaction(SIGINT, &act, NULL); sigaction(SIGINT, &act, NULL);
cpu = cpu_map__new(NULL); cpu = perf_cpu_map__new(NULL);
if (!cpu) if (!cpu)
goto errmem; goto errmem;

View File

@ -75,6 +75,7 @@
#include <sys/epoll.h> #include <sys/epoll.h>
#include <sys/eventfd.h> #include <sys/eventfd.h>
#include <sys/types.h> #include <sys/types.h>
#include <perf/cpumap.h>
#include "../util/stat.h" #include "../util/stat.h"
#include <subcmd/parse-options.h> #include <subcmd/parse-options.h>
@ -429,7 +430,7 @@ int bench_epoll_wait(int argc, const char **argv)
act.sa_sigaction = toggle_done; act.sa_sigaction = toggle_done;
sigaction(SIGINT, &act, NULL); sigaction(SIGINT, &act, NULL);
cpu = cpu_map__new(NULL); cpu = perf_cpu_map__new(NULL);
if (!cpu) if (!cpu)
goto errmem; goto errmem;

View File

@ -20,6 +20,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/zalloc.h> #include <linux/zalloc.h>
#include <sys/time.h> #include <sys/time.h>
#include <perf/cpumap.h>
#include "../util/stat.h" #include "../util/stat.h"
#include <subcmd/parse-options.h> #include <subcmd/parse-options.h>
@ -132,7 +133,7 @@ int bench_futex_hash(int argc, const char **argv)
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
cpu = cpu_map__new(NULL); cpu = perf_cpu_map__new(NULL);
if (!cpu) if (!cpu)
goto errmem; goto errmem;

View File

@ -14,6 +14,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/zalloc.h> #include <linux/zalloc.h>
#include <errno.h> #include <errno.h>
#include <perf/cpumap.h>
#include "bench.h" #include "bench.h"
#include "futex.h" #include "futex.h"
#include "cpumap.h" #include "cpumap.h"
@ -156,7 +157,7 @@ int bench_futex_lock_pi(int argc, const char **argv)
if (argc) if (argc)
goto err; goto err;
cpu = cpu_map__new(NULL); cpu = perf_cpu_map__new(NULL);
if (!cpu) if (!cpu)
err(EXIT_FAILURE, "calloc"); err(EXIT_FAILURE, "calloc");

View File

@ -20,6 +20,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/time64.h> #include <linux/time64.h>
#include <errno.h> #include <errno.h>
#include <perf/cpumap.h>
#include "bench.h" #include "bench.h"
#include "futex.h" #include "futex.h"
#include "cpumap.h" #include "cpumap.h"
@ -123,7 +124,7 @@ int bench_futex_requeue(int argc, const char **argv)
if (argc) if (argc)
goto err; goto err;
cpu = cpu_map__new(NULL); cpu = perf_cpu_map__new(NULL);
if (!cpu) if (!cpu)
err(EXIT_FAILURE, "cpu_map__new"); err(EXIT_FAILURE, "cpu_map__new");

View File

@ -237,7 +237,7 @@ int bench_futex_wake_parallel(int argc, const char **argv)
act.sa_sigaction = toggle_done; act.sa_sigaction = toggle_done;
sigaction(SIGINT, &act, NULL); sigaction(SIGINT, &act, NULL);
cpu = cpu_map__new(NULL); cpu = perf_cpu_map__new(NULL);
if (!cpu) if (!cpu)
err(EXIT_FAILURE, "calloc"); err(EXIT_FAILURE, "calloc");

View File

@ -20,6 +20,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/time64.h> #include <linux/time64.h>
#include <errno.h> #include <errno.h>
#include <perf/cpumap.h>
#include "bench.h" #include "bench.h"
#include "futex.h" #include "futex.h"
#include "cpumap.h" #include "cpumap.h"
@ -131,7 +132,7 @@ int bench_futex_wake(int argc, const char **argv)
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
cpu = cpu_map__new(NULL); cpu = perf_cpu_map__new(NULL);
if (!cpu) if (!cpu)
err(EXIT_FAILURE, "calloc"); err(EXIT_FAILURE, "calloc");

View File

@ -202,7 +202,7 @@ static int set_tracing_cpu(struct perf_ftrace *ftrace)
static int reset_tracing_cpu(void) static int reset_tracing_cpu(void)
{ {
struct perf_cpu_map *cpumap = cpu_map__new(NULL); struct perf_cpu_map *cpumap = perf_cpu_map__new(NULL);
int ret; int ret;
ret = set_tracing_cpumask(cpumap); ret = set_tracing_cpumask(cpumap);

View File

@ -3183,7 +3183,7 @@ static int setup_map_cpus(struct perf_sched *sched)
if (!sched->map.cpus_str) if (!sched->map.cpus_str)
return 0; return 0;
map = cpu_map__new(sched->map.cpus_str); map = perf_cpu_map__new(sched->map.cpus_str);
if (!map) { if (!map) {
pr_err("failed to get cpus map from %s\n", sched->map.cpus_str); pr_err("failed to get cpus map from %s\n", sched->map.cpus_str);
return -1; return -1;
@ -3217,7 +3217,7 @@ static int setup_color_cpus(struct perf_sched *sched)
if (!sched->map.color_cpus_str) if (!sched->map.color_cpus_str)
return 0; return 0;
map = cpu_map__new(sched->map.color_cpus_str); map = perf_cpu_map__new(sched->map.color_cpus_str);
if (!map) { if (!map) {
pr_err("failed to get thread map from %s\n", sched->map.color_cpus_str); pr_err("failed to get thread map from %s\n", sched->map.color_cpus_str);
return -1; return -1;

View File

@ -5,6 +5,10 @@
#include <internal/cpumap.h> #include <internal/cpumap.h>
#include <asm/bug.h> #include <asm/bug.h>
#include <stdio.h> #include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>
#include <limits.h>
struct perf_cpu_map *perf_cpu_map__dummy_new(void) struct perf_cpu_map *perf_cpu_map__dummy_new(void)
{ {
@ -40,3 +44,183 @@ void perf_cpu_map__put(struct perf_cpu_map *map)
if (map && refcount_dec_and_test(&map->refcnt)) if (map && refcount_dec_and_test(&map->refcnt))
cpu_map__delete(map); cpu_map__delete(map);
} }
static struct perf_cpu_map *cpu_map__default_new(void)
{
struct perf_cpu_map *cpus;
int nr_cpus;
nr_cpus = sysconf(_SC_NPROCESSORS_ONLN);
if (nr_cpus < 0)
return NULL;
cpus = malloc(sizeof(*cpus) + nr_cpus * sizeof(int));
if (cpus != NULL) {
int i;
for (i = 0; i < nr_cpus; ++i)
cpus->map[i] = i;
cpus->nr = nr_cpus;
refcount_set(&cpus->refcnt, 1);
}
return cpus;
}
static struct perf_cpu_map *cpu_map__trim_new(int nr_cpus, int *tmp_cpus)
{
size_t payload_size = nr_cpus * sizeof(int);
struct perf_cpu_map *cpus = malloc(sizeof(*cpus) + payload_size);
if (cpus != NULL) {
cpus->nr = nr_cpus;
memcpy(cpus->map, tmp_cpus, payload_size);
refcount_set(&cpus->refcnt, 1);
}
return cpus;
}
struct perf_cpu_map *perf_cpu_map__read(FILE *file)
{
struct perf_cpu_map *cpus = NULL;
int nr_cpus = 0;
int *tmp_cpus = NULL, *tmp;
int max_entries = 0;
int n, cpu, prev;
char sep;
sep = 0;
prev = -1;
for (;;) {
n = fscanf(file, "%u%c", &cpu, &sep);
if (n <= 0)
break;
if (prev >= 0) {
int new_max = nr_cpus + cpu - prev - 1;
if (new_max >= max_entries) {
max_entries = new_max + MAX_NR_CPUS / 2;
tmp = realloc(tmp_cpus, max_entries * sizeof(int));
if (tmp == NULL)
goto out_free_tmp;
tmp_cpus = tmp;
}
while (++prev < cpu)
tmp_cpus[nr_cpus++] = prev;
}
if (nr_cpus == max_entries) {
max_entries += MAX_NR_CPUS;
tmp = realloc(tmp_cpus, max_entries * sizeof(int));
if (tmp == NULL)
goto out_free_tmp;
tmp_cpus = tmp;
}
tmp_cpus[nr_cpus++] = cpu;
if (n == 2 && sep == '-')
prev = cpu;
else
prev = -1;
if (n == 1 || sep == '\n')
break;
}
if (nr_cpus > 0)
cpus = cpu_map__trim_new(nr_cpus, tmp_cpus);
else
cpus = cpu_map__default_new();
out_free_tmp:
free(tmp_cpus);
return cpus;
}
static struct perf_cpu_map *cpu_map__read_all_cpu_map(void)
{
struct perf_cpu_map *cpus = NULL;
FILE *onlnf;
onlnf = fopen("/sys/devices/system/cpu/online", "r");
if (!onlnf)
return cpu_map__default_new();
cpus = perf_cpu_map__read(onlnf);
fclose(onlnf);
return cpus;
}
struct perf_cpu_map *perf_cpu_map__new(const char *cpu_list)
{
struct perf_cpu_map *cpus = NULL;
unsigned long start_cpu, end_cpu = 0;
char *p = NULL;
int i, nr_cpus = 0;
int *tmp_cpus = NULL, *tmp;
int max_entries = 0;
if (!cpu_list)
return cpu_map__read_all_cpu_map();
/*
* must handle the case of empty cpumap to cover
* TOPOLOGY header for NUMA nodes with no CPU
* ( e.g., because of CPU hotplug)
*/
if (!isdigit(*cpu_list) && *cpu_list != '\0')
goto out;
while (isdigit(*cpu_list)) {
p = NULL;
start_cpu = strtoul(cpu_list, &p, 0);
if (start_cpu >= INT_MAX
|| (*p != '\0' && *p != ',' && *p != '-'))
goto invalid;
if (*p == '-') {
cpu_list = ++p;
p = NULL;
end_cpu = strtoul(cpu_list, &p, 0);
if (end_cpu >= INT_MAX || (*p != '\0' && *p != ','))
goto invalid;
if (end_cpu < start_cpu)
goto invalid;
} else {
end_cpu = start_cpu;
}
for (; start_cpu <= end_cpu; start_cpu++) {
/* check for duplicates */
for (i = 0; i < nr_cpus; i++)
if (tmp_cpus[i] == (int)start_cpu)
goto invalid;
if (nr_cpus == max_entries) {
max_entries += MAX_NR_CPUS;
tmp = realloc(tmp_cpus, max_entries * sizeof(int));
if (tmp == NULL)
goto invalid;
tmp_cpus = tmp;
}
tmp_cpus[nr_cpus++] = (int)start_cpu;
}
if (*p)
++p;
cpu_list = p;
}
if (nr_cpus > 0)
cpus = cpu_map__trim_new(nr_cpus, tmp_cpus);
else if (*cpu_list != '\0')
cpus = cpu_map__default_new();
else
cpus = perf_cpu_map__dummy_new();
invalid:
free(tmp_cpus);
out:
return cpus;
}

View File

@ -10,4 +10,8 @@ struct perf_cpu_map {
int map[]; int map[];
}; };
#ifndef MAX_NR_CPUS
#define MAX_NR_CPUS 2048
#endif
#endif /* __LIBPERF_INTERNAL_CPUMAP_H */ #endif /* __LIBPERF_INTERNAL_CPUMAP_H */

View File

@ -3,10 +3,13 @@
#define __LIBPERF_CPUMAP_H #define __LIBPERF_CPUMAP_H
#include <perf/core.h> #include <perf/core.h>
#include <stdio.h>
struct perf_cpu_map; struct perf_cpu_map;
LIBPERF_API struct perf_cpu_map *perf_cpu_map__dummy_new(void); LIBPERF_API struct perf_cpu_map *perf_cpu_map__dummy_new(void);
LIBPERF_API struct perf_cpu_map *perf_cpu_map__new(const char *cpu_list);
LIBPERF_API struct perf_cpu_map *perf_cpu_map__read(FILE *file);
LIBPERF_API struct perf_cpu_map *perf_cpu_map__get(struct perf_cpu_map *map); LIBPERF_API struct perf_cpu_map *perf_cpu_map__get(struct perf_cpu_map *map);
LIBPERF_API void perf_cpu_map__put(struct perf_cpu_map *map); LIBPERF_API void perf_cpu_map__put(struct perf_cpu_map *map);

View File

@ -4,6 +4,8 @@ LIBPERF_0.0.1 {
perf_cpu_map__dummy_new; perf_cpu_map__dummy_new;
perf_cpu_map__get; perf_cpu_map__get;
perf_cpu_map__put; perf_cpu_map__put;
perf_cpu_map__new;
perf_cpu_map__read;
perf_thread_map__new_dummy; perf_thread_map__new_dummy;
perf_thread_map__set_pid; perf_thread_map__set_pid;
perf_thread_map__comm; perf_thread_map__comm;

View File

@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: GPL-2.0
#include <linux/compiler.h> #include <linux/compiler.h>
#include <linux/bitmap.h> #include <linux/bitmap.h>
#include <perf/cpumap.h>
#include "tests.h" #include "tests.h"
#include "cpumap.h" #include "cpumap.h"
#include "debug.h" #include "debug.h"
@ -9,7 +10,7 @@
static unsigned long *get_bitmap(const char *str, int nbits) static unsigned long *get_bitmap(const char *str, int nbits)
{ {
struct perf_cpu_map *map = cpu_map__new(str); struct perf_cpu_map *map = perf_cpu_map__new(str);
unsigned long *bm = NULL; unsigned long *bm = NULL;
int i; int i;

View File

@ -8,6 +8,7 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <sys/param.h> #include <sys/param.h>
#include <perf/cpumap.h>
#include "parse-events.h" #include "parse-events.h"
#include "evlist.h" #include "evlist.h"
@ -613,9 +614,9 @@ static int do_test_code_reading(bool try_kcore)
goto out_put; goto out_put;
} }
cpus = cpu_map__new(NULL); cpus = perf_cpu_map__new(NULL);
if (!cpus) { if (!cpus) {
pr_debug("cpu_map__new failed\n"); pr_debug("perf_cpu_map__new failed\n");
goto out_put; goto out_put;
} }

View File

@ -5,6 +5,7 @@
#include "event.h" #include "event.h"
#include <string.h> #include <string.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <perf/cpumap.h>
#include "debug.h" #include "debug.h"
struct machine; struct machine;
@ -78,7 +79,7 @@ int test__cpu_map_synthesize(struct test *test __maybe_unused, int subtest __may
struct perf_cpu_map *cpus; struct perf_cpu_map *cpus;
/* This one is better stores in mask. */ /* This one is better stores in mask. */
cpus = cpu_map__new("0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19"); cpus = perf_cpu_map__new("0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19");
TEST_ASSERT_VAL("failed to synthesize map", TEST_ASSERT_VAL("failed to synthesize map",
!perf_event__synthesize_cpu_map(NULL, cpus, process_event_mask, NULL)); !perf_event__synthesize_cpu_map(NULL, cpus, process_event_mask, NULL));
@ -86,7 +87,7 @@ int test__cpu_map_synthesize(struct test *test __maybe_unused, int subtest __may
perf_cpu_map__put(cpus); perf_cpu_map__put(cpus);
/* This one is better stores in cpu values. */ /* This one is better stores in cpu values. */
cpus = cpu_map__new("1,256"); cpus = perf_cpu_map__new("1,256");
TEST_ASSERT_VAL("failed to synthesize map", TEST_ASSERT_VAL("failed to synthesize map",
!perf_event__synthesize_cpu_map(NULL, cpus, process_event_cpus, NULL)); !perf_event__synthesize_cpu_map(NULL, cpus, process_event_cpus, NULL));
@ -97,7 +98,7 @@ int test__cpu_map_synthesize(struct test *test __maybe_unused, int subtest __may
static int cpu_map_print(const char *str) static int cpu_map_print(const char *str)
{ {
struct perf_cpu_map *map = cpu_map__new(str); struct perf_cpu_map *map = perf_cpu_map__new(str);
char buf[100]; char buf[100];
if (!map) if (!map)

View File

@ -4,6 +4,7 @@
#include <inttypes.h> #include <inttypes.h>
#include <string.h> #include <string.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <perf/cpumap.h>
#include "tests.h" #include "tests.h"
#include "evlist.h" #include "evlist.h"
#include "evsel.h" #include "evsel.h"
@ -115,9 +116,9 @@ static int attach__cpu_disabled(struct evlist *evlist)
pr_debug("attaching to CPU 0 as enabled\n"); pr_debug("attaching to CPU 0 as enabled\n");
cpus = cpu_map__new("0"); cpus = perf_cpu_map__new("0");
if (cpus == NULL) { if (cpus == NULL) {
pr_debug("failed to call cpu_map__new\n"); pr_debug("failed to call perf_cpu_map__new\n");
return -1; return -1;
} }
@ -144,9 +145,9 @@ static int attach__cpu_enabled(struct evlist *evlist)
pr_debug("attaching to CPU 0 as enabled\n"); pr_debug("attaching to CPU 0 as enabled\n");
cpus = cpu_map__new("0"); cpus = perf_cpu_map__new("0");
if (cpus == NULL) { if (cpus == NULL) {
pr_debug("failed to call cpu_map__new\n"); pr_debug("failed to call perf_cpu_map__new\n");
return -1; return -1;
} }

View File

@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: GPL-2.0
#include <linux/compiler.h> #include <linux/compiler.h>
#include <perf/cpumap.h>
#include "evlist.h" #include "evlist.h"
#include "evsel.h" #include "evsel.h"
#include "machine.h" #include "machine.h"
@ -108,7 +109,7 @@ int test__event_update(struct test *test __maybe_unused, int subtest __maybe_unu
TEST_ASSERT_VAL("failed to synthesize attr update name", TEST_ASSERT_VAL("failed to synthesize attr update name",
!perf_event__synthesize_event_update_name(&tmp.tool, evsel, process_event_name)); !perf_event__synthesize_event_update_name(&tmp.tool, evsel, process_event_name));
evsel->own_cpus = cpu_map__new("1,2,3"); evsel->own_cpus = perf_cpu_map__new("1,2,3");
TEST_ASSERT_VAL("failed to synthesize attr update cpus", TEST_ASSERT_VAL("failed to synthesize attr update cpus",
!perf_event__synthesize_event_update_cpus(&tmp.tool, evsel, process_event_cpus)); !perf_event__synthesize_event_update_cpus(&tmp.tool, evsel, process_event_cpus));

View File

@ -2,6 +2,7 @@
#include <linux/types.h> #include <linux/types.h>
#include <unistd.h> #include <unistd.h>
#include <sys/prctl.h> #include <sys/prctl.h>
#include <perf/cpumap.h>
#include "parse-events.h" #include "parse-events.h"
#include "evlist.h" #include "evlist.h"
@ -75,7 +76,7 @@ int test__keep_tracking(struct test *test __maybe_unused, int subtest __maybe_un
threads = thread_map__new(-1, getpid(), UINT_MAX); threads = thread_map__new(-1, getpid(), UINT_MAX);
CHECK_NOT_NULL__(threads); CHECK_NOT_NULL__(threads);
cpus = cpu_map__new(NULL); cpus = perf_cpu_map__new(NULL);
CHECK_NOT_NULL__(cpus); CHECK_NOT_NULL__(cpus);
evlist = evlist__new(); evlist = evlist__new();

View File

@ -2,6 +2,7 @@
#include <linux/compiler.h> #include <linux/compiler.h>
#include <linux/bitmap.h> #include <linux/bitmap.h>
#include <linux/zalloc.h> #include <linux/zalloc.h>
#include <perf/cpumap.h>
#include "cpumap.h" #include "cpumap.h"
#include "mem2node.h" #include "mem2node.h"
#include "tests.h" #include "tests.h"
@ -19,7 +20,7 @@ static struct node {
static unsigned long *get_bitmap(const char *str, int nbits) static unsigned long *get_bitmap(const char *str, int nbits)
{ {
struct perf_cpu_map *map = cpu_map__new(str); struct perf_cpu_map *map = perf_cpu_map__new(str);
unsigned long *bm = NULL; unsigned long *bm = NULL;
int i; int i;

View File

@ -3,6 +3,7 @@
#include <inttypes.h> #include <inttypes.h>
/* For the CLR_() macros */ /* For the CLR_() macros */
#include <pthread.h> #include <pthread.h>
#include <perf/cpumap.h>
#include "evlist.h" #include "evlist.h"
#include "evsel.h" #include "evsel.h"
@ -46,7 +47,7 @@ int test__basic_mmap(struct test *test __maybe_unused, int subtest __maybe_unuse
return -1; return -1;
} }
cpus = cpu_map__new(NULL); cpus = perf_cpu_map__new(NULL);
if (cpus == NULL) { if (cpus == NULL) {
pr_debug("cpu_map__new\n"); pr_debug("cpu_map__new\n");
goto out_free_threads; goto out_free_threads;

View File

@ -33,7 +33,7 @@ int test__openat_syscall_event_on_all_cpus(struct test *test __maybe_unused, int
return -1; return -1;
} }
cpus = cpu_map__new(NULL); cpus = perf_cpu_map__new(NULL);
if (cpus == NULL) { if (cpus == NULL) {
pr_debug("cpu_map__new\n"); pr_debug("cpu_map__new\n");
goto out_thread_map_delete; goto out_thread_map_delete;

View File

@ -5,6 +5,7 @@
#include <time.h> #include <time.h>
#include <stdlib.h> #include <stdlib.h>
#include <linux/zalloc.h> #include <linux/zalloc.h>
#include <perf/cpumap.h>
#include "parse-events.h" #include "parse-events.h"
#include "evlist.h" #include "evlist.h"
@ -341,9 +342,9 @@ int test__switch_tracking(struct test *test __maybe_unused, int subtest __maybe_
goto out_err; goto out_err;
} }
cpus = cpu_map__new(NULL); cpus = perf_cpu_map__new(NULL);
if (!cpus) { if (!cpus) {
pr_debug("cpu_map__new failed!\n"); pr_debug("perf_cpu_map__new failed!\n");
goto out_err; goto out_err;
} }

View File

@ -2,6 +2,7 @@
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <perf/cpumap.h>
#include "tests.h" #include "tests.h"
#include "util.h" #include "util.h"
#include "session.h" #include "session.h"
@ -126,7 +127,7 @@ int test__session_topology(struct test *test __maybe_unused, int subtest __maybe
if (session_write_header(path)) if (session_write_header(path))
goto free_path; goto free_path;
map = cpu_map__new(NULL); map = perf_cpu_map__new(NULL);
if (map == NULL) { if (map == NULL) {
pr_debug("failed to get system cpumap\n"); pr_debug("failed to get system cpumap\n");
goto free_path; goto free_path;

View File

@ -17,185 +17,6 @@ static int max_present_cpu_num;
static int max_node_num; static int max_node_num;
static int *cpunode_map; static int *cpunode_map;
static struct perf_cpu_map *cpu_map__default_new(void)
{
struct perf_cpu_map *cpus;
int nr_cpus;
nr_cpus = sysconf(_SC_NPROCESSORS_ONLN);
if (nr_cpus < 0)
return NULL;
cpus = malloc(sizeof(*cpus) + nr_cpus * sizeof(int));
if (cpus != NULL) {
int i;
for (i = 0; i < nr_cpus; ++i)
cpus->map[i] = i;
cpus->nr = nr_cpus;
refcount_set(&cpus->refcnt, 1);
}
return cpus;
}
static struct perf_cpu_map *cpu_map__trim_new(int nr_cpus, int *tmp_cpus)
{
size_t payload_size = nr_cpus * sizeof(int);
struct perf_cpu_map *cpus = malloc(sizeof(*cpus) + payload_size);
if (cpus != NULL) {
cpus->nr = nr_cpus;
memcpy(cpus->map, tmp_cpus, payload_size);
refcount_set(&cpus->refcnt, 1);
}
return cpus;
}
struct perf_cpu_map *cpu_map__read(FILE *file)
{
struct perf_cpu_map *cpus = NULL;
int nr_cpus = 0;
int *tmp_cpus = NULL, *tmp;
int max_entries = 0;
int n, cpu, prev;
char sep;
sep = 0;
prev = -1;
for (;;) {
n = fscanf(file, "%u%c", &cpu, &sep);
if (n <= 0)
break;
if (prev >= 0) {
int new_max = nr_cpus + cpu - prev - 1;
if (new_max >= max_entries) {
max_entries = new_max + MAX_NR_CPUS / 2;
tmp = realloc(tmp_cpus, max_entries * sizeof(int));
if (tmp == NULL)
goto out_free_tmp;
tmp_cpus = tmp;
}
while (++prev < cpu)
tmp_cpus[nr_cpus++] = prev;
}
if (nr_cpus == max_entries) {
max_entries += MAX_NR_CPUS;
tmp = realloc(tmp_cpus, max_entries * sizeof(int));
if (tmp == NULL)
goto out_free_tmp;
tmp_cpus = tmp;
}
tmp_cpus[nr_cpus++] = cpu;
if (n == 2 && sep == '-')
prev = cpu;
else
prev = -1;
if (n == 1 || sep == '\n')
break;
}
if (nr_cpus > 0)
cpus = cpu_map__trim_new(nr_cpus, tmp_cpus);
else
cpus = cpu_map__default_new();
out_free_tmp:
free(tmp_cpus);
return cpus;
}
static struct perf_cpu_map *cpu_map__read_all_cpu_map(void)
{
struct perf_cpu_map *cpus = NULL;
FILE *onlnf;
onlnf = fopen("/sys/devices/system/cpu/online", "r");
if (!onlnf)
return cpu_map__default_new();
cpus = cpu_map__read(onlnf);
fclose(onlnf);
return cpus;
}
struct perf_cpu_map *cpu_map__new(const char *cpu_list)
{
struct perf_cpu_map *cpus = NULL;
unsigned long start_cpu, end_cpu = 0;
char *p = NULL;
int i, nr_cpus = 0;
int *tmp_cpus = NULL, *tmp;
int max_entries = 0;
if (!cpu_list)
return cpu_map__read_all_cpu_map();
/*
* must handle the case of empty cpumap to cover
* TOPOLOGY header for NUMA nodes with no CPU
* ( e.g., because of CPU hotplug)
*/
if (!isdigit(*cpu_list) && *cpu_list != '\0')
goto out;
while (isdigit(*cpu_list)) {
p = NULL;
start_cpu = strtoul(cpu_list, &p, 0);
if (start_cpu >= INT_MAX
|| (*p != '\0' && *p != ',' && *p != '-'))
goto invalid;
if (*p == '-') {
cpu_list = ++p;
p = NULL;
end_cpu = strtoul(cpu_list, &p, 0);
if (end_cpu >= INT_MAX || (*p != '\0' && *p != ','))
goto invalid;
if (end_cpu < start_cpu)
goto invalid;
} else {
end_cpu = start_cpu;
}
for (; start_cpu <= end_cpu; start_cpu++) {
/* check for duplicates */
for (i = 0; i < nr_cpus; i++)
if (tmp_cpus[i] == (int)start_cpu)
goto invalid;
if (nr_cpus == max_entries) {
max_entries += MAX_NR_CPUS;
tmp = realloc(tmp_cpus, max_entries * sizeof(int));
if (tmp == NULL)
goto invalid;
tmp_cpus = tmp;
}
tmp_cpus[nr_cpus++] = (int)start_cpu;
}
if (*p)
++p;
cpu_list = p;
}
if (nr_cpus > 0)
cpus = cpu_map__trim_new(nr_cpus, tmp_cpus);
else if (*cpu_list != '\0')
cpus = cpu_map__default_new();
else
cpus = perf_cpu_map__dummy_new();
invalid:
free(tmp_cpus);
out:
return cpus;
}
static struct perf_cpu_map *cpu_map__from_entries(struct cpu_map_entries *cpus) static struct perf_cpu_map *cpu_map__from_entries(struct cpu_map_entries *cpus)
{ {
struct perf_cpu_map *map; struct perf_cpu_map *map;
@ -751,7 +572,7 @@ const struct perf_cpu_map *cpu_map__online(void) /* thread unsafe */
static const struct perf_cpu_map *online = NULL; static const struct perf_cpu_map *online = NULL;
if (!online) if (!online)
online = cpu_map__new(NULL); /* from /sys/devices/system/cpu/online */ online = perf_cpu_map__new(NULL); /* from /sys/devices/system/cpu/online */
return online; return online;
} }

View File

@ -11,10 +11,8 @@
#include "perf.h" #include "perf.h"
#include "util/debug.h" #include "util/debug.h"
struct perf_cpu_map *cpu_map__new(const char *cpu_list);
struct perf_cpu_map *cpu_map__empty_new(int nr); struct perf_cpu_map *cpu_map__empty_new(int nr);
struct perf_cpu_map *cpu_map__new_data(struct cpu_map_data *data); struct perf_cpu_map *cpu_map__new_data(struct cpu_map_data *data);
struct perf_cpu_map *cpu_map__read(FILE *file);
size_t cpu_map__snprint(struct perf_cpu_map *map, char *buf, size_t size); size_t cpu_map__snprint(struct perf_cpu_map *map, char *buf, size_t size);
size_t cpu_map__snprint_mask(struct perf_cpu_map *map, char *buf, size_t size); size_t cpu_map__snprint_mask(struct perf_cpu_map *map, char *buf, size_t size);
size_t cpu_map__fprintf(struct perf_cpu_map *map, FILE *fp); size_t cpu_map__fprintf(struct perf_cpu_map *map, FILE *fp);

View File

@ -5,6 +5,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <api/fs/fs.h> #include <api/fs/fs.h>
#include <linux/zalloc.h> #include <linux/zalloc.h>
#include <perf/cpumap.h>
#include "cputopo.h" #include "cputopo.h"
#include "cpumap.h" #include "cpumap.h"
@ -182,7 +183,7 @@ struct cpu_topology *cpu_topology__new(void)
ncpus = cpu__max_present_cpu(); ncpus = cpu__max_present_cpu();
/* build online CPU map */ /* build online CPU map */
map = cpu_map__new(NULL); map = perf_cpu_map__new(NULL);
if (map == NULL) { if (map == NULL) {
pr_debug("failed to get system cpumap\n"); pr_debug("failed to get system cpumap\n");
return NULL; return NULL;
@ -312,7 +313,7 @@ struct numa_topology *numa_topology__new(void)
if (c) if (c)
*c = '\0'; *c = '\0';
node_map = cpu_map__new(buf); node_map = perf_cpu_map__new(buf);
if (!node_map) if (!node_map)
goto out; goto out;

View File

@ -34,6 +34,7 @@
#include <linux/err.h> #include <linux/err.h>
#include <linux/zalloc.h> #include <linux/zalloc.h>
#include <perf/evlist.h> #include <perf/evlist.h>
#include <perf/cpumap.h>
#ifdef LACKS_SIGQUEUE_PROTOTYPE #ifdef LACKS_SIGQUEUE_PROTOTYPE
int sigqueue(pid_t pid, int sig, const union sigval value); int sigqueue(pid_t pid, int sig, const union sigval value);
@ -1089,7 +1090,7 @@ int perf_evlist__create_maps(struct evlist *evlist, struct target *target)
if (target__uses_dummy_map(target)) if (target__uses_dummy_map(target))
cpus = perf_cpu_map__dummy_new(); cpus = perf_cpu_map__dummy_new();
else else
cpus = cpu_map__new(target->cpu_list); cpus = perf_cpu_map__new(target->cpu_list);
if (!cpus) if (!cpus)
goto out_delete_threads; goto out_delete_threads;
@ -1372,7 +1373,7 @@ static int perf_evlist__create_syswide_maps(struct evlist *evlist)
* error, and we may not want to do that fallback to a * error, and we may not want to do that fallback to a
* default cpu identity map :-\ * default cpu identity map :-\
*/ */
cpus = cpu_map__new(NULL); cpus = perf_cpu_map__new(NULL);
if (!cpus) if (!cpus)
goto out; goto out;

View File

@ -20,6 +20,7 @@
#include <linux/time64.h> #include <linux/time64.h>
#include <dirent.h> #include <dirent.h>
#include <bpf/libbpf.h> #include <bpf/libbpf.h>
#include <perf/cpumap.h>
#include "evlist.h" #include "evlist.h"
#include "evsel.h" #include "evsel.h"
@ -2348,7 +2349,7 @@ static int process_numa_topology(struct feat_fd *ff, void *data __maybe_unused)
if (!str) if (!str)
goto error; goto error;
n->map = cpu_map__new(str); n->map = perf_cpu_map__new(str);
if (!n->map) if (!n->map)
goto error; goto error;

View File

@ -24,6 +24,7 @@
#include "bpf-loader.h" #include "bpf-loader.h"
#include "debug.h" #include "debug.h"
#include <api/fs/tracing_path.h> #include <api/fs/tracing_path.h>
#include <perf/cpumap.h>
#include "parse-events-bison.h" #include "parse-events-bison.h"
#define YY_EXTRA_TYPE int #define YY_EXTRA_TYPE int
#include "parse-events-flex.h" #include "parse-events-flex.h"
@ -323,7 +324,7 @@ __add_event(struct list_head *list, int *idx,
{ {
struct evsel *evsel; struct evsel *evsel;
struct perf_cpu_map *cpus = pmu ? pmu->cpus : struct perf_cpu_map *cpus = pmu ? pmu->cpus :
cpu_list ? cpu_map__new(cpu_list) : NULL; cpu_list ? perf_cpu_map__new(cpu_list) : NULL;
event_attr_init(attr); event_attr_init(attr);

View File

@ -15,6 +15,7 @@
#include <api/fs/fs.h> #include <api/fs/fs.h>
#include <locale.h> #include <locale.h>
#include <regex.h> #include <regex.h>
#include <perf/cpumap.h>
#include "pmu.h" #include "pmu.h"
#include "parse-events.h" #include "parse-events.h"
#include "cpumap.h" #include "cpumap.h"
@ -581,7 +582,7 @@ static struct perf_cpu_map *__pmu_cpumask(const char *path)
if (!file) if (!file)
return NULL; return NULL;
cpus = cpu_map__read(file); cpus = perf_cpu_map__read(file);
fclose(file); fclose(file);
return cpus; return cpus;
} }

View File

@ -4,6 +4,7 @@
#include <inttypes.h> #include <inttypes.h>
#include <poll.h> #include <poll.h>
#include <linux/err.h> #include <linux/err.h>
#include <perf/cpumap.h>
#include "evlist.h" #include "evlist.h"
#include "callchain.h" #include "callchain.h"
#include "evsel.h" #include "evsel.h"
@ -549,7 +550,7 @@ static int pyrf_cpu_map__init(struct pyrf_cpu_map *pcpus,
kwlist, &cpustr)) kwlist, &cpustr))
return -1; return -1;
pcpus->cpus = cpu_map__new(cpustr); pcpus->cpus = perf_cpu_map__new(cpustr);
if (pcpus->cpus == NULL) if (pcpus->cpus == NULL)
return -1; return -1;
return 0; return 0;

View File

@ -6,6 +6,7 @@
#include <errno.h> #include <errno.h>
#include <api/fs/fs.h> #include <api/fs/fs.h>
#include <subcmd/parse-options.h> #include <subcmd/parse-options.h>
#include <perf/cpumap.h>
#include "util.h" #include "util.h"
#include "cloexec.h" #include "cloexec.h"
@ -63,7 +64,7 @@ static bool perf_probe_api(setup_probe_fn_t fn)
struct perf_cpu_map *cpus; struct perf_cpu_map *cpus;
int cpu, ret, i = 0; int cpu, ret, i = 0;
cpus = cpu_map__new(NULL); cpus = perf_cpu_map__new(NULL);
if (!cpus) if (!cpus)
return false; return false;
cpu = cpus->map[0]; cpu = cpus->map[0];
@ -118,7 +119,7 @@ bool perf_can_record_cpu_wide(void)
struct perf_cpu_map *cpus; struct perf_cpu_map *cpus;
int cpu, fd; int cpu, fd;
cpus = cpu_map__new(NULL); cpus = perf_cpu_map__new(NULL);
if (!cpus) if (!cpus)
return false; return false;
cpu = cpus->map[0]; cpu = cpus->map[0];
@ -275,7 +276,7 @@ bool perf_evlist__can_select_event(struct evlist *evlist, const char *str)
evsel = perf_evlist__last(temp_evlist); evsel = perf_evlist__last(temp_evlist);
if (!evlist || cpu_map__empty(evlist->cpus)) { if (!evlist || cpu_map__empty(evlist->cpus)) {
struct perf_cpu_map *cpus = cpu_map__new(NULL); struct perf_cpu_map *cpus = perf_cpu_map__new(NULL);
cpu = cpus ? cpus->map[0] : 0; cpu = cpus ? cpus->map[0] : 0;
perf_cpu_map__put(cpus); perf_cpu_map__put(cpus);

View File

@ -10,6 +10,7 @@
#include <unistd.h> #include <unistd.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <perf/cpumap.h>
#include "evlist.h" #include "evlist.h"
#include "evsel.h" #include "evsel.h"
@ -2289,7 +2290,7 @@ int perf_session__cpu_bitmap(struct perf_session *session,
} }
} }
map = cpu_map__new(cpu_list); map = perf_cpu_map__new(cpu_list);
if (map == NULL) { if (map == NULL) {
pr_err("Invalid cpu_list\n"); pr_err("Invalid cpu_list\n");
return -1; return -1;

View File

@ -16,6 +16,7 @@
#include <linux/bitmap.h> #include <linux/bitmap.h>
#include <linux/time64.h> #include <linux/time64.h>
#include <linux/zalloc.h> #include <linux/zalloc.h>
#include <perf/cpumap.h>
#include "perf.h" #include "perf.h"
#include "svghelper.h" #include "svghelper.h"
@ -731,7 +732,7 @@ static int str_to_bitmap(char *s, cpumask_t *b)
struct perf_cpu_map *m; struct perf_cpu_map *m;
int c; int c;
m = cpu_map__new(s); m = perf_cpu_map__new(s);
if (!m) if (!m)
return -1; return -1;