* [PATCH 0/4 v2] perf: Make some functions generic
@ 2014-04-07 18:55 Don Zickus
2014-04-07 18:55 ` [PATCH 1/4 v2] perf: Allow ability to map cpus to nodes easily Don Zickus
` (4 more replies)
0 siblings, 5 replies; 14+ messages in thread
From: Don Zickus @ 2014-04-07 18:55 UTC (permalink / raw)
To: acme; +Cc: LKML, jolsa, namhyung, Don Zickus
This patch just converts some private functions into global ones
that can be used by other tools like the c2c tool I am trying to merge.
Don Zickus (4):
perf: Allow ability to map cpus to nodes easily
perf: Use cpu/possible instead of cpu/kernel_max
perf, kmem: Utilize the new generic cpunode_map
perf, callchain: Add generic report parse callchain callback function
tools/perf/builtin-kmem.c | 78 +----------------------
tools/perf/builtin-report.c | 81 +-----------------------
tools/perf/util/callchain.c | 82 ++++++++++++++++++++++++
tools/perf/util/callchain.h | 1 +
tools/perf/util/cpumap.c | 149 ++++++++++++++++++++++++++++++++++++++++++++
tools/perf/util/cpumap.h | 35 +++++++++++
6 files changed, 273 insertions(+), 153 deletions(-)
--
1.7.11.7
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 1/4 v2] perf: Allow ability to map cpus to nodes easily
2014-04-07 18:55 [PATCH 0/4 v2] perf: Make some functions generic Don Zickus
@ 2014-04-07 18:55 ` Don Zickus
2014-04-10 9:31 ` Jiri Olsa
2014-04-22 18:34 ` [tip:perf/core] perf tools: " tip-bot for Don Zickus
2014-04-07 18:55 ` [PATCH 2/4 v2] perf: Use cpu/possible instead of cpu/kernel_max Don Zickus
` (3 subsequent siblings)
4 siblings, 2 replies; 14+ messages in thread
From: Don Zickus @ 2014-04-07 18:55 UTC (permalink / raw)
To: acme; +Cc: LKML, jolsa, namhyung, Don Zickus
This patch figures out the max number of cpus and nodes that are on the
system and creates a map of cpu to node. This allows us to provide a cpu
and quickly get the node associated with it.
It was mostly copied from builtin-kmem.c and tweaked slightly to use less memory
(use possible cpus instead of max). It also calculates the max number of nodes.
V6: use original kernel_max reference
V5: use sysfs_mountpoint and filename__read_str
V4: fix typos, rename get_max_num
V3: simplify function names
Signed-off-by: Don Zickus <dzickus@redhat.com>
---
tools/perf/util/cpumap.c | 149 +++++++++++++++++++++++++++++++++++++++++++++++
tools/perf/util/cpumap.h | 35 +++++++++++
2 files changed, 184 insertions(+)
diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c
index 7fe4994..1b75434 100644
--- a/tools/perf/util/cpumap.c
+++ b/tools/perf/util/cpumap.c
@@ -317,3 +317,152 @@ int cpu_map__build_core_map(struct cpu_map *cpus, struct cpu_map **corep)
{
return cpu_map__build_map(cpus, corep, cpu_map__get_core);
}
+
+/* setup simple routines to easily access node numbers given a cpu number */
+static int get_max_num(char *path, int *max)
+{
+ size_t num;
+ char *buf;
+ int err = 0;
+
+ if (filename__read_str(path, &buf, &num))
+ return -1;
+
+ buf[num] = '\0';
+
+ /* start on the right, to find highest node num */
+ while (--num) {
+ if ((buf[num] == ',') || (buf[num] == '-')) {
+ num++;
+ break;
+ }
+ }
+ if (sscanf(&buf[num], "%d", max) < 1) {
+ err = -1;
+ goto out;
+ }
+
+ /* convert from 0-based to 1-based */
+ (*max)++;
+
+out:
+ free(buf);
+ return err;
+}
+
+/* Determine highest possible cpu in the system for sparse allocation */
+static void set_max_cpu_num(void)
+{
+ const char *mnt;
+ char path[PATH_MAX];
+ int ret = -1;
+
+ /* set up default */
+ max_cpu_num = 4096;
+
+ mnt = sysfs__mountpoint();
+ if (!mnt)
+ goto out;
+
+ /* get the highest possible cpu number for a sparse allocation */
+ snprintf(path, PATH_MAX, "%s/devices/system/cpu/kernel_max", mnt);
+
+ ret = get_max_num(path, &max_cpu_num);
+
+out:
+ if (ret)
+ pr_err("Failed to read max cpus, using default of %d\n",
+ max_cpu_num);
+ return;
+}
+
+/* Determine highest possible node in the system for sparse allocation */
+static void set_max_node_num(void)
+{
+ const char *mnt;
+ char path[PATH_MAX];
+ int ret = -1;
+
+ /* set up default */
+ max_node_num = 8;
+
+ mnt = sysfs__mountpoint();
+ if (!mnt)
+ goto out;
+
+ /* get the highest possible cpu number for a sparse allocation */
+ snprintf(path, PATH_MAX, "%s/devices/system/node/possible", mnt);
+
+ ret = get_max_num(path, &max_node_num);
+
+out:
+ if (ret)
+ pr_err("Failed to read max nodes, using default of %d\n",
+ max_node_num);
+ return;
+}
+
+static int init_cpunode_map(void)
+{
+ int i;
+
+ set_max_cpu_num();
+ set_max_node_num();
+
+ cpunode_map = calloc(max_cpu_num, sizeof(int));
+ if (!cpunode_map) {
+ pr_err("%s: calloc failed\n", __func__);
+ goto out;
+ }
+
+ for (i = 0; i < max_cpu_num; i++)
+ cpunode_map[i] = -1;
+
+ return 0;
+out:
+ return -1;
+}
+
+int cpu__setup_cpunode_map(void)
+{
+ struct dirent *dent1, *dent2;
+ DIR *dir1, *dir2;
+ unsigned int cpu, mem;
+ char buf[PATH_MAX];
+ char path[PATH_MAX];
+ const char *mnt;
+
+ /* initialize globals */
+ if (init_cpunode_map())
+ return -1;
+
+ mnt = sysfs__mountpoint();
+ if (!mnt)
+ return 0;
+
+ snprintf(path, PATH_MAX, "%s/devices/system/node", mnt);
+ dir1 = opendir(path);
+ if (!dir1)
+ return 0;
+
+ /* walk tree and setup map */
+ while ((dent1 = readdir(dir1)) != NULL) {
+ if (dent1->d_type != DT_DIR ||
+ sscanf(dent1->d_name, "node%u", &mem) < 1)
+ continue;
+
+ snprintf(buf, PATH_MAX, "%s/%s", path, dent1->d_name);
+ dir2 = opendir(buf);
+ if (!dir2)
+ continue;
+ while ((dent2 = readdir(dir2)) != NULL) {
+ if (dent2->d_type != DT_LNK ||
+ sscanf(dent2->d_name, "cpu%u", &cpu) < 1)
+ continue;
+ cpunode_map[cpu] = mem;
+ }
+ closedir(dir2);
+ }
+ closedir(dir1);
+ return 0;
+}
diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h
index b123bb9..61a6548 100644
--- a/tools/perf/util/cpumap.h
+++ b/tools/perf/util/cpumap.h
@@ -4,6 +4,9 @@
#include <stdio.h>
#include <stdbool.h>
+#include "perf.h"
+#include "util/debug.h"
+
struct cpu_map {
int nr;
int map[];
@@ -46,4 +49,36 @@ static inline bool cpu_map__empty(const struct cpu_map *map)
return map ? map->map[0] == -1 : true;
}
+int max_cpu_num;
+int max_node_num;
+int *cpunode_map;
+
+int cpu__setup_cpunode_map(void);
+
+static inline int cpu__max_node(void)
+{
+ if (unlikely(!max_node_num))
+ pr_debug("cpu_map not initialized\n");
+
+ return max_node_num;
+}
+
+static inline int cpu__max_cpu(void)
+{
+ if (unlikely(!max_cpu_num))
+ pr_debug("cpu_map not initialized\n");
+
+ return max_cpu_num;
+}
+
+static inline int cpu__get_node(int cpu)
+{
+ if (unlikely(cpunode_map == NULL)) {
+ pr_debug("cpu_map not initialized\n");
+ return -1;
+ }
+
+ return cpunode_map[cpu];
+}
+
#endif /* __PERF_CPUMAP_H */
--
1.7.11.7
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 2/4 v2] perf: Use cpu/possible instead of cpu/kernel_max
2014-04-07 18:55 [PATCH 0/4 v2] perf: Make some functions generic Don Zickus
2014-04-07 18:55 ` [PATCH 1/4 v2] perf: Allow ability to map cpus to nodes easily Don Zickus
@ 2014-04-07 18:55 ` Don Zickus
2014-04-22 18:34 ` [tip:perf/core] perf tools: Use cpu/possible instead of cpu/ kernel_max tip-bot for Don Zickus
2014-04-07 18:55 ` [PATCH 3/4 v2] perf, kmem: Utilize the new generic cpunode_map Don Zickus
` (2 subsequent siblings)
4 siblings, 1 reply; 14+ messages in thread
From: Don Zickus @ 2014-04-07 18:55 UTC (permalink / raw)
To: acme; +Cc: LKML, jolsa, namhyung, Don Zickus
The system's max configuration is represented by cpu/possible and
cpu/kernel_max can be huge (4096 vs. 128), so save space by keeping
smaller structures.
Signed-off-by: Don Zickus <dzickus@redhat.com>
---
tools/perf/util/cpumap.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c
index 1b75434..22adfd0 100644
--- a/tools/perf/util/cpumap.c
+++ b/tools/perf/util/cpumap.c
@@ -365,7 +365,7 @@ static void set_max_cpu_num(void)
goto out;
/* get the highest possible cpu number for a sparse allocation */
- snprintf(path, PATH_MAX, "%s/devices/system/cpu/kernel_max", mnt);
+ snprintf(path, PATH_MAX, "%s/devices/system/cpu/possible", mnt);
ret = get_max_num(path, &max_cpu_num);
--
1.7.11.7
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 3/4 v2] perf, kmem: Utilize the new generic cpunode_map
2014-04-07 18:55 [PATCH 0/4 v2] perf: Make some functions generic Don Zickus
2014-04-07 18:55 ` [PATCH 1/4 v2] perf: Allow ability to map cpus to nodes easily Don Zickus
2014-04-07 18:55 ` [PATCH 2/4 v2] perf: Use cpu/possible instead of cpu/kernel_max Don Zickus
@ 2014-04-07 18:55 ` Don Zickus
2014-04-22 18:34 ` [tip:perf/core] perf " tip-bot for Don Zickus
2014-04-07 18:55 ` [PATCH 4/4 v2] perf, callchain: Add generic report parse callchain callback function Don Zickus
2014-04-09 0:31 ` [PATCH 0/4 v2] perf: Make some functions generic Namhyung Kim
4 siblings, 1 reply; 14+ messages in thread
From: Don Zickus @ 2014-04-07 18:55 UTC (permalink / raw)
To: acme; +Cc: LKML, jolsa, namhyung, Don Zickus, Li Zefan
Use the previous patch implementation of cpunode_map for builtin-kmem.c
Should not be any functional difference.
Cc: Li Zefan <lizf@cn.fujitsu.com>
Signed-off-by: Don Zickus <dzickus@redhat.com>
---
tools/perf/builtin-kmem.c | 78 ++---------------------------------------------
1 file changed, 3 insertions(+), 75 deletions(-)
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index 929462a..a61783a 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -14,6 +14,7 @@
#include "util/parse-options.h"
#include "util/trace-event.h"
#include "util/data.h"
+#include "util/cpumap.h"
#include "util/debug.h"
@@ -31,9 +32,6 @@ static int caller_lines = -1;
static bool raw_ip;
-static int *cpunode_map;
-static int max_cpu_num;
-
struct alloc_stat {
u64 call_site;
u64 ptr;
@@ -55,76 +53,6 @@ static struct rb_root root_caller_sorted;
static unsigned long total_requested, total_allocated;
static unsigned long nr_allocs, nr_cross_allocs;
-#define PATH_SYS_NODE "/sys/devices/system/node"
-
-static int init_cpunode_map(void)
-{
- FILE *fp;
- int i, err = -1;
-
- fp = fopen("/sys/devices/system/cpu/kernel_max", "r");
- if (!fp) {
- max_cpu_num = 4096;
- return 0;
- }
-
- if (fscanf(fp, "%d", &max_cpu_num) < 1) {
- pr_err("Failed to read 'kernel_max' from sysfs");
- goto out_close;
- }
-
- max_cpu_num++;
-
- cpunode_map = calloc(max_cpu_num, sizeof(int));
- if (!cpunode_map) {
- pr_err("%s: calloc failed\n", __func__);
- goto out_close;
- }
-
- for (i = 0; i < max_cpu_num; i++)
- cpunode_map[i] = -1;
-
- err = 0;
-out_close:
- fclose(fp);
- return err;
-}
-
-static int setup_cpunode_map(void)
-{
- struct dirent *dent1, *dent2;
- DIR *dir1, *dir2;
- unsigned int cpu, mem;
- char buf[PATH_MAX];
-
- if (init_cpunode_map())
- return -1;
-
- dir1 = opendir(PATH_SYS_NODE);
- if (!dir1)
- return 0;
-
- while ((dent1 = readdir(dir1)) != NULL) {
- if (dent1->d_type != DT_DIR ||
- sscanf(dent1->d_name, "node%u", &mem) < 1)
- continue;
-
- snprintf(buf, PATH_MAX, "%s/%s", PATH_SYS_NODE, dent1->d_name);
- dir2 = opendir(buf);
- if (!dir2)
- continue;
- while ((dent2 = readdir(dir2)) != NULL) {
- if (dent2->d_type != DT_LNK ||
- sscanf(dent2->d_name, "cpu%u", &cpu) < 1)
- continue;
- cpunode_map[cpu] = mem;
- }
- closedir(dir2);
- }
- closedir(dir1);
- return 0;
-}
-
static int insert_alloc_stat(unsigned long call_site, unsigned long ptr,
int bytes_req, int bytes_alloc, int cpu)
{
@@ -235,7 +163,7 @@ static int perf_evsel__process_alloc_node_event(struct perf_evsel *evsel,
int ret = perf_evsel__process_alloc_event(evsel, sample);
if (!ret) {
- int node1 = cpunode_map[sample->cpu],
+ int node1 = cpu__get_node(sample->cpu),
node2 = perf_evsel__intval(evsel, sample, "node");
if (node1 != node2)
@@ -770,7 +698,7 @@ int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused)
if (!strncmp(argv[0], "rec", 3)) {
return __cmd_record(argc, argv);
} else if (!strcmp(argv[0], "stat")) {
- if (setup_cpunode_map())
+ if (cpu__setup_cpunode_map())
return -1;
if (list_empty(&caller_sort))
--
1.7.11.7
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 4/4 v2] perf, callchain: Add generic report parse callchain callback function
2014-04-07 18:55 [PATCH 0/4 v2] perf: Make some functions generic Don Zickus
` (2 preceding siblings ...)
2014-04-07 18:55 ` [PATCH 3/4 v2] perf, kmem: Utilize the new generic cpunode_map Don Zickus
@ 2014-04-07 18:55 ` Don Zickus
2014-04-22 18:34 ` [tip:perf/core] perf " tip-bot for Don Zickus
2014-04-09 0:31 ` [PATCH 0/4 v2] perf: Make some functions generic Namhyung Kim
4 siblings, 1 reply; 14+ messages in thread
From: Don Zickus @ 2014-04-07 18:55 UTC (permalink / raw)
To: acme; +Cc: LKML, jolsa, namhyung, Don Zickus
This takes the parse_callchain_opt function and copies it into the
callchain.c file. Now the c2c tool can use it too without duplicating.
Update perf-report to use the new routine too.
V3: rename function
V2: remove commented code, combine with perf-report change
Signed-off-by: Don Zickus <dzickus@redhat.com>
---
tools/perf/builtin-report.c | 81 ++------------------------------------------
tools/perf/util/callchain.c | 82 +++++++++++++++++++++++++++++++++++++++++++++
tools/perf/util/callchain.h | 1 +
3 files changed, 86 insertions(+), 78 deletions(-)
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index c8f2113..189905b 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -573,11 +573,9 @@ static int __cmd_report(struct report *rep)
}
static int
-parse_callchain_opt(const struct option *opt, const char *arg, int unset)
+report_parse_callchain_opt(const struct option *opt, const char *arg, int unset)
{
struct report *rep = (struct report *)opt->value;
- char *tok, *tok2;
- char *endptr;
/*
* --no-call-graph
@@ -587,80 +585,7 @@ parse_callchain_opt(const struct option *opt, const char *arg, int unset)
return 0;
}
- symbol_conf.use_callchain = true;
-
- if (!arg)
- return 0;
-
- tok = strtok((char *)arg, ",");
- if (!tok)
- return -1;
-
- /* get the output mode */
- if (!strncmp(tok, "graph", strlen(arg)))
- callchain_param.mode = CHAIN_GRAPH_ABS;
-
- else if (!strncmp(tok, "flat", strlen(arg)))
- callchain_param.mode = CHAIN_FLAT;
-
- else if (!strncmp(tok, "fractal", strlen(arg)))
- callchain_param.mode = CHAIN_GRAPH_REL;
-
- else if (!strncmp(tok, "none", strlen(arg))) {
- callchain_param.mode = CHAIN_NONE;
- symbol_conf.use_callchain = false;
-
- return 0;
- }
-
- else
- return -1;
-
- /* get the min percentage */
- tok = strtok(NULL, ",");
- if (!tok)
- goto setup;
-
- callchain_param.min_percent = strtod(tok, &endptr);
- if (tok == endptr)
- return -1;
-
- /* get the print limit */
- tok2 = strtok(NULL, ",");
- if (!tok2)
- goto setup;
-
- if (tok2[0] != 'c') {
- callchain_param.print_limit = strtoul(tok2, &endptr, 0);
- tok2 = strtok(NULL, ",");
- if (!tok2)
- goto setup;
- }
-
- /* get the call chain order */
- if (!strncmp(tok2, "caller", strlen("caller")))
- callchain_param.order = ORDER_CALLER;
- else if (!strncmp(tok2, "callee", strlen("callee")))
- callchain_param.order = ORDER_CALLEE;
- else
- return -1;
-
- /* Get the sort key */
- tok2 = strtok(NULL, ",");
- if (!tok2)
- goto setup;
- if (!strncmp(tok2, "function", strlen("function")))
- callchain_param.key = CCKEY_FUNCTION;
- else if (!strncmp(tok2, "address", strlen("address")))
- callchain_param.key = CCKEY_ADDRESS;
- else
- return -1;
-setup:
- if (callchain_register_param(&callchain_param) < 0) {
- pr_err("Can't register callchain params\n");
- return -1;
- }
- return 0;
+ return parse_callchain_report_opt(arg);
}
int
@@ -772,7 +697,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
"Only display entries with parent-match"),
OPT_CALLBACK_DEFAULT('g', "call-graph", &report, "output_type,min_percent[,print_limit],call_order",
"Display callchains using output_type (graph, flat, fractal, or none) , min percent threshold, optional print limit, callchain order, key (function or address). "
- "Default: fractal,0.5,callee,function", &parse_callchain_opt, callchain_default_opt),
+ "Default: fractal,0.5,callee,function", &report_parse_callchain_opt, callchain_default_opt),
OPT_INTEGER(0, "max-stack", &report.max_stack,
"Set the maximum stack depth when parsing the callchain, "
"anything beyond the specified depth will be ignored. "
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index 8d9db45..2fa48a9 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -25,6 +25,88 @@
__thread struct callchain_cursor callchain_cursor;
+int
+parse_callchain_report_opt(const char *arg)
+{
+ char *tok, *tok2;
+ char *endptr;
+
+ symbol_conf.use_callchain = true;
+
+ if (!arg)
+ return 0;
+
+ tok = strtok((char *)arg, ",");
+ if (!tok)
+ return -1;
+
+ /* get the output mode */
+ if (!strncmp(tok, "graph", strlen(arg)))
+ callchain_param.mode = CHAIN_GRAPH_ABS;
+
+ else if (!strncmp(tok, "flat", strlen(arg)))
+ callchain_param.mode = CHAIN_FLAT;
+
+ else if (!strncmp(tok, "fractal", strlen(arg)))
+ callchain_param.mode = CHAIN_GRAPH_REL;
+
+ else if (!strncmp(tok, "none", strlen(arg))) {
+ callchain_param.mode = CHAIN_NONE;
+ symbol_conf.use_callchain = false;
+
+ return 0;
+ }
+
+ else
+ return -1;
+
+ /* get the min percentage */
+ tok = strtok(NULL, ",");
+ if (!tok)
+ goto setup;
+
+ callchain_param.min_percent = strtod(tok, &endptr);
+ if (tok == endptr)
+ return -1;
+
+ /* get the print limit */
+ tok2 = strtok(NULL, ",");
+ if (!tok2)
+ goto setup;
+
+ if (tok2[0] != 'c') {
+ callchain_param.print_limit = strtoul(tok2, &endptr, 0);
+ tok2 = strtok(NULL, ",");
+ if (!tok2)
+ goto setup;
+ }
+
+ /* get the call chain order */
+ if (!strncmp(tok2, "caller", strlen("caller")))
+ callchain_param.order = ORDER_CALLER;
+ else if (!strncmp(tok2, "callee", strlen("callee")))
+ callchain_param.order = ORDER_CALLEE;
+ else
+ return -1;
+
+ /* Get the sort key */
+ tok2 = strtok(NULL, ",");
+ if (!tok2)
+ goto setup;
+ if (!strncmp(tok2, "function", strlen("function")))
+ callchain_param.key = CCKEY_FUNCTION;
+ else if (!strncmp(tok2, "address", strlen("address")))
+ callchain_param.key = CCKEY_ADDRESS;
+ else
+ return -1;
+setup:
+ if (callchain_register_param(&callchain_param) < 0) {
+ pr_err("Can't register callchain params\n");
+ return -1;
+ }
+ return 0;
+}
+
static void
rb_insert_callchain(struct rb_root *root, struct callchain_node *chain,
enum chain_mode mode)
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index 8ad97e9..dda4cf8 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -157,4 +157,5 @@ int sample__resolve_callchain(struct perf_sample *sample, struct symbol **parent
int hist_entry__append_callchain(struct hist_entry *he, struct perf_sample *sample);
extern const char record_callchain_help[];
+int parse_callchain_report_opt(const char *arg);
#endif /* __PERF_CALLCHAIN_H */
--
1.7.11.7
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH 0/4 v2] perf: Make some functions generic
2014-04-07 18:55 [PATCH 0/4 v2] perf: Make some functions generic Don Zickus
` (3 preceding siblings ...)
2014-04-07 18:55 ` [PATCH 4/4 v2] perf, callchain: Add generic report parse callchain callback function Don Zickus
@ 2014-04-09 0:31 ` Namhyung Kim
4 siblings, 0 replies; 14+ messages in thread
From: Namhyung Kim @ 2014-04-09 0:31 UTC (permalink / raw)
To: Don Zickus; +Cc: acme, LKML, jolsa
On Mon, 7 Apr 2014 14:55:20 -0400, Don Zickus wrote:
> This patch just converts some private functions into global ones
> that can be used by other tools like the c2c tool I am trying to merge.
For the series,
Reviewed-by: Namhyung Kim <namhyung@kernel.org>
Thanks,
Namhyung
>
> Don Zickus (4):
> perf: Allow ability to map cpus to nodes easily
> perf: Use cpu/possible instead of cpu/kernel_max
> perf, kmem: Utilize the new generic cpunode_map
> perf, callchain: Add generic report parse callchain callback function
>
> tools/perf/builtin-kmem.c | 78 +----------------------
> tools/perf/builtin-report.c | 81 +-----------------------
> tools/perf/util/callchain.c | 82 ++++++++++++++++++++++++
> tools/perf/util/callchain.h | 1 +
> tools/perf/util/cpumap.c | 149 ++++++++++++++++++++++++++++++++++++++++++++
> tools/perf/util/cpumap.h | 35 +++++++++++
> 6 files changed, 273 insertions(+), 153 deletions(-)
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 1/4 v2] perf: Allow ability to map cpus to nodes easily
2014-04-07 18:55 ` [PATCH 1/4 v2] perf: Allow ability to map cpus to nodes easily Don Zickus
@ 2014-04-10 9:31 ` Jiri Olsa
2014-04-10 13:15 ` Don Zickus
2014-04-22 18:34 ` [tip:perf/core] perf tools: " tip-bot for Don Zickus
1 sibling, 1 reply; 14+ messages in thread
From: Jiri Olsa @ 2014-04-10 9:31 UTC (permalink / raw)
To: Don Zickus; +Cc: acme, LKML, namhyung
On Mon, Apr 07, 2014 at 02:55:21PM -0400, Don Zickus wrote:
SNIP
> +static int init_cpunode_map(void)
> +{
> + int i;
> +
> + set_max_cpu_num();
> + set_max_node_num();
> +
> + cpunode_map = calloc(max_cpu_num, sizeof(int));
> + if (!cpunode_map) {
> + pr_err("%s: calloc failed\n", __func__);
> + goto out;
shuld probably be ^^^:
return -1;
> + }
> +
> + for (i = 0; i < max_cpu_num; i++)
> + cpunode_map[i] = -1;
> +
> + return 0;
> +out:
> + return -1;
and remove 'out' label code
other than that, it seems ok.. I'll queue it
thanks,
jirka
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 1/4 v2] perf: Allow ability to map cpus to nodes easily
2014-04-10 9:31 ` Jiri Olsa
@ 2014-04-10 13:15 ` Don Zickus
2014-04-10 13:24 ` Jiri Olsa
0 siblings, 1 reply; 14+ messages in thread
From: Don Zickus @ 2014-04-10 13:15 UTC (permalink / raw)
To: Jiri Olsa; +Cc: acme, LKML, namhyung
On Thu, Apr 10, 2014 at 11:31:46AM +0200, Jiri Olsa wrote:
> On Mon, Apr 07, 2014 at 02:55:21PM -0400, Don Zickus wrote:
>
> SNIP
>
> > +static int init_cpunode_map(void)
> > +{
> > + int i;
> > +
> > + set_max_cpu_num();
> > + set_max_node_num();
> > +
> > + cpunode_map = calloc(max_cpu_num, sizeof(int));
> > + if (!cpunode_map) {
> > + pr_err("%s: calloc failed\n", __func__);
> > + goto out;
> shuld probably be ^^^:
>
> return -1;
>
> > + }
> > +
> > + for (i = 0; i < max_cpu_num; i++)
> > + cpunode_map[i] = -1;
> > +
> > + return 0;
> > +out:
> > + return -1;
>
> and remove 'out' label code
Sorry, probably leftover code that after snipping and changing didn't get
noticed. Thanks.
>
> other than that, it seems ok.. I'll queue it
I assume you are making the changes locally or should I resubmit?
Cheers,
Don
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 1/4 v2] perf: Allow ability to map cpus to nodes easily
2014-04-10 13:15 ` Don Zickus
@ 2014-04-10 13:24 ` Jiri Olsa
2014-04-10 13:54 ` Don Zickus
0 siblings, 1 reply; 14+ messages in thread
From: Jiri Olsa @ 2014-04-10 13:24 UTC (permalink / raw)
To: Don Zickus; +Cc: acme, LKML, namhyung
On Thu, Apr 10, 2014 at 09:15:15AM -0400, Don Zickus wrote:
> On Thu, Apr 10, 2014 at 11:31:46AM +0200, Jiri Olsa wrote:
> > On Mon, Apr 07, 2014 at 02:55:21PM -0400, Don Zickus wrote:
> >
> > SNIP
> >
> > > +static int init_cpunode_map(void)
> > > +{
> > > + int i;
> > > +
> > > + set_max_cpu_num();
> > > + set_max_node_num();
> > > +
> > > + cpunode_map = calloc(max_cpu_num, sizeof(int));
> > > + if (!cpunode_map) {
> > > + pr_err("%s: calloc failed\n", __func__);
> > > + goto out;
> > shuld probably be ^^^:
> >
> > return -1;
> >
> > > + }
> > > +
> > > + for (i = 0; i < max_cpu_num; i++)
> > > + cpunode_map[i] = -1;
> > > +
> > > + return 0;
> > > +out:
> > > + return -1;
> >
> > and remove 'out' label code
>
> Sorry, probably leftover code that after snipping and changing didn't get
> noticed. Thanks.
>
> >
> > other than that, it seems ok.. I'll queue it
>
> I assume you are making the changes locally or should I resubmit?
yes, I'll do that localy
jirka
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 1/4 v2] perf: Allow ability to map cpus to nodes easily
2014-04-10 13:24 ` Jiri Olsa
@ 2014-04-10 13:54 ` Don Zickus
0 siblings, 0 replies; 14+ messages in thread
From: Don Zickus @ 2014-04-10 13:54 UTC (permalink / raw)
To: Jiri Olsa; +Cc: acme, LKML, namhyung
On Thu, Apr 10, 2014 at 03:24:58PM +0200, Jiri Olsa wrote:
> On Thu, Apr 10, 2014 at 09:15:15AM -0400, Don Zickus wrote:
> > On Thu, Apr 10, 2014 at 11:31:46AM +0200, Jiri Olsa wrote:
> > > On Mon, Apr 07, 2014 at 02:55:21PM -0400, Don Zickus wrote:
> > >
> > > SNIP
> > >
> > > > +static int init_cpunode_map(void)
> > > > +{
> > > > + int i;
> > > > +
> > > > + set_max_cpu_num();
> > > > + set_max_node_num();
> > > > +
> > > > + cpunode_map = calloc(max_cpu_num, sizeof(int));
> > > > + if (!cpunode_map) {
> > > > + pr_err("%s: calloc failed\n", __func__);
> > > > + goto out;
> > > shuld probably be ^^^:
> > >
> > > return -1;
> > >
> > > > + }
> > > > +
> > > > + for (i = 0; i < max_cpu_num; i++)
> > > > + cpunode_map[i] = -1;
> > > > +
> > > > + return 0;
> > > > +out:
> > > > + return -1;
> > >
> > > and remove 'out' label code
> >
> > Sorry, probably leftover code that after snipping and changing didn't get
> > noticed. Thanks.
> >
> > >
> > > other than that, it seems ok.. I'll queue it
> >
> > I assume you are making the changes locally or should I resubmit?
>
> yes, I'll do that localy
Thanks!
Cheers,
Don
^ permalink raw reply [flat|nested] 14+ messages in thread
* [tip:perf/core] perf tools: Allow ability to map cpus to nodes easily
2014-04-07 18:55 ` [PATCH 1/4 v2] perf: Allow ability to map cpus to nodes easily Don Zickus
2014-04-10 9:31 ` Jiri Olsa
@ 2014-04-22 18:34 ` tip-bot for Don Zickus
1 sibling, 0 replies; 14+ messages in thread
From: tip-bot for Don Zickus @ 2014-04-22 18:34 UTC (permalink / raw)
To: linux-tip-commits
Cc: linux-kernel, hpa, mingo, tglx, namhyung, jolsa, dzickus
Commit-ID: 7780c25bae59fd042281710f5e1243268e2c18dc
Gitweb: http://git.kernel.org/tip/7780c25bae59fd042281710f5e1243268e2c18dc
Author: Don Zickus <dzickus@redhat.com>
AuthorDate: Mon, 7 Apr 2014 14:55:21 -0400
Committer: Jiri Olsa <jolsa@redhat.com>
CommitDate: Tue, 22 Apr 2014 17:39:12 +0200
perf tools: Allow ability to map cpus to nodes easily
This patch figures out the max number of cpus and nodes that are on the
system and creates a map of cpu to node. This allows us to provide a cpu
and quickly get the node associated with it.
It was mostly copied from builtin-kmem.c and tweaked slightly to use less memory
(use possible cpus instead of max). It also calculates the max number of nodes.
Signed-off-by: Don Zickus <dzickus@redhat.com>
Reviewed-by: Namhyung Kim <namhyung@kernel.org>
Link: http://lkml.kernel.org/r/1396896924-129847-2-git-send-email-dzickus@redhat.com
[ Removing out label code in init_cpunode_map ]
[ Adding check for snprintf error ]
[ Removing unneeded returns ]
Signed-off-by: Jiri Olsa <jolsa@redhat.com>
---
tools/perf/util/cpumap.c | 160 +++++++++++++++++++++++++++++++++++++++++++++++
tools/perf/util/cpumap.h | 35 +++++++++++
2 files changed, 195 insertions(+)
diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c
index 7fe4994..526da02 100644
--- a/tools/perf/util/cpumap.c
+++ b/tools/perf/util/cpumap.c
@@ -317,3 +317,163 @@ int cpu_map__build_core_map(struct cpu_map *cpus, struct cpu_map **corep)
{
return cpu_map__build_map(cpus, corep, cpu_map__get_core);
}
+
+/* setup simple routines to easily access node numbers given a cpu number */
+static int get_max_num(char *path, int *max)
+{
+ size_t num;
+ char *buf;
+ int err = 0;
+
+ if (filename__read_str(path, &buf, &num))
+ return -1;
+
+ buf[num] = '\0';
+
+ /* start on the right, to find highest node num */
+ while (--num) {
+ if ((buf[num] == ',') || (buf[num] == '-')) {
+ num++;
+ break;
+ }
+ }
+ if (sscanf(&buf[num], "%d", max) < 1) {
+ err = -1;
+ goto out;
+ }
+
+ /* convert from 0-based to 1-based */
+ (*max)++;
+
+out:
+ free(buf);
+ return err;
+}
+
+/* Determine highest possible cpu in the system for sparse allocation */
+static void set_max_cpu_num(void)
+{
+ const char *mnt;
+ char path[PATH_MAX];
+ int ret = -1;
+
+ /* set up default */
+ max_cpu_num = 4096;
+
+ mnt = sysfs__mountpoint();
+ if (!mnt)
+ goto out;
+
+ /* get the highest possible cpu number for a sparse allocation */
+ ret = snprintf(path, PATH_MAX, "%s/devices/system/cpu/kernel_max", mnt);
+ if (ret == PATH_MAX) {
+ pr_err("sysfs path crossed PATH_MAX(%d) size\n", PATH_MAX);
+ goto out;
+ }
+
+ ret = get_max_num(path, &max_cpu_num);
+
+out:
+ if (ret)
+ pr_err("Failed to read max cpus, using default of %d\n", max_cpu_num);
+}
+
+/* Determine highest possible node in the system for sparse allocation */
+static void set_max_node_num(void)
+{
+ const char *mnt;
+ char path[PATH_MAX];
+ int ret = -1;
+
+ /* set up default */
+ max_node_num = 8;
+
+ mnt = sysfs__mountpoint();
+ if (!mnt)
+ goto out;
+
+ /* get the highest possible cpu number for a sparse allocation */
+ ret = snprintf(path, PATH_MAX, "%s/devices/system/node/possible", mnt);
+ if (ret == PATH_MAX) {
+ pr_err("sysfs path crossed PATH_MAX(%d) size\n", PATH_MAX);
+ goto out;
+ }
+
+ ret = get_max_num(path, &max_node_num);
+
+out:
+ if (ret)
+ pr_err("Failed to read max nodes, using default of %d\n", max_node_num);
+}
+
+static int init_cpunode_map(void)
+{
+ int i;
+
+ set_max_cpu_num();
+ set_max_node_num();
+
+ cpunode_map = calloc(max_cpu_num, sizeof(int));
+ if (!cpunode_map) {
+ pr_err("%s: calloc failed\n", __func__);
+ return -1;
+ }
+
+ for (i = 0; i < max_cpu_num; i++)
+ cpunode_map[i] = -1;
+
+ return 0;
+}
+
+int cpu__setup_cpunode_map(void)
+{
+ struct dirent *dent1, *dent2;
+ DIR *dir1, *dir2;
+ unsigned int cpu, mem;
+ char buf[PATH_MAX];
+ char path[PATH_MAX];
+ const char *mnt;
+ int n;
+
+ /* initialize globals */
+ if (init_cpunode_map())
+ return -1;
+
+ mnt = sysfs__mountpoint();
+ if (!mnt)
+ return 0;
+
+ n = snprintf(path, PATH_MAX, "%s/devices/system/node", mnt);
+ if (n == PATH_MAX) {
+ pr_err("sysfs path crossed PATH_MAX(%d) size\n", PATH_MAX);
+ return -1;
+ }
+
+ dir1 = opendir(path);
+ if (!dir1)
+ return 0;
+
+ /* walk tree and setup map */
+ while ((dent1 = readdir(dir1)) != NULL) {
+ if (dent1->d_type != DT_DIR || sscanf(dent1->d_name, "node%u", &mem) < 1)
+ continue;
+
+ n = snprintf(buf, PATH_MAX, "%s/%s", path, dent1->d_name);
+ if (n == PATH_MAX) {
+ pr_err("sysfs path crossed PATH_MAX(%d) size\n", PATH_MAX);
+ continue;
+ }
+
+ dir2 = opendir(buf);
+ if (!dir2)
+ continue;
+ while ((dent2 = readdir(dir2)) != NULL) {
+ if (dent2->d_type != DT_LNK || sscanf(dent2->d_name, "cpu%u", &cpu) < 1)
+ continue;
+ cpunode_map[cpu] = mem;
+ }
+ closedir(dir2);
+ }
+ closedir(dir1);
+ return 0;
+}
diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h
index b123bb9..61a6548 100644
--- a/tools/perf/util/cpumap.h
+++ b/tools/perf/util/cpumap.h
@@ -4,6 +4,9 @@
#include <stdio.h>
#include <stdbool.h>
+#include "perf.h"
+#include "util/debug.h"
+
struct cpu_map {
int nr;
int map[];
@@ -46,4 +49,36 @@ static inline bool cpu_map__empty(const struct cpu_map *map)
return map ? map->map[0] == -1 : true;
}
+int max_cpu_num;
+int max_node_num;
+int *cpunode_map;
+
+int cpu__setup_cpunode_map(void);
+
+static inline int cpu__max_node(void)
+{
+ if (unlikely(!max_node_num))
+ pr_debug("cpu_map not initialized\n");
+
+ return max_node_num;
+}
+
+static inline int cpu__max_cpu(void)
+{
+ if (unlikely(!max_cpu_num))
+ pr_debug("cpu_map not initialized\n");
+
+ return max_cpu_num;
+}
+
+static inline int cpu__get_node(int cpu)
+{
+ if (unlikely(cpunode_map == NULL)) {
+ pr_debug("cpu_map not initialized\n");
+ return -1;
+ }
+
+ return cpunode_map[cpu];
+}
+
#endif /* __PERF_CPUMAP_H */
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [tip:perf/core] perf tools: Use cpu/possible instead of cpu/ kernel_max
2014-04-07 18:55 ` [PATCH 2/4 v2] perf: Use cpu/possible instead of cpu/kernel_max Don Zickus
@ 2014-04-22 18:34 ` tip-bot for Don Zickus
0 siblings, 0 replies; 14+ messages in thread
From: tip-bot for Don Zickus @ 2014-04-22 18:34 UTC (permalink / raw)
To: linux-tip-commits
Cc: linux-kernel, hpa, mingo, tglx, namhyung, jolsa, dzickus
Commit-ID: f5b1f4e483d55a88ed120e2c62b45ba5b939fa72
Gitweb: http://git.kernel.org/tip/f5b1f4e483d55a88ed120e2c62b45ba5b939fa72
Author: Don Zickus <dzickus@redhat.com>
AuthorDate: Mon, 7 Apr 2014 14:55:22 -0400
Committer: Jiri Olsa <jolsa@redhat.com>
CommitDate: Tue, 22 Apr 2014 17:39:16 +0200
perf tools: Use cpu/possible instead of cpu/kernel_max
The system's max configuration is represented by cpu/possible and
cpu/kernel_max can be huge (4096 vs. 128), so save space by keeping
smaller structures.
Signed-off-by: Don Zickus <dzickus@redhat.com>
Reviewed-by: Namhyung Kim <namhyung@kernel.org>
Link: http://lkml.kernel.org/r/1396896924-129847-3-git-send-email-dzickus@redhat.com
Signed-off-by: Jiri Olsa <jolsa@redhat.com>
---
tools/perf/util/cpumap.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c
index 526da02..c4e55b7 100644
--- a/tools/perf/util/cpumap.c
+++ b/tools/perf/util/cpumap.c
@@ -365,7 +365,7 @@ static void set_max_cpu_num(void)
goto out;
/* get the highest possible cpu number for a sparse allocation */
- ret = snprintf(path, PATH_MAX, "%s/devices/system/cpu/kernel_max", mnt);
+ ret = snprintf(path, PATH_MAX, "%s/devices/system/cpu/possible", mnt);
if (ret == PATH_MAX) {
pr_err("sysfs path crossed PATH_MAX(%d) size\n", PATH_MAX);
goto out;
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [tip:perf/core] perf kmem: Utilize the new generic cpunode_map
2014-04-07 18:55 ` [PATCH 3/4 v2] perf, kmem: Utilize the new generic cpunode_map Don Zickus
@ 2014-04-22 18:34 ` tip-bot for Don Zickus
0 siblings, 0 replies; 14+ messages in thread
From: tip-bot for Don Zickus @ 2014-04-22 18:34 UTC (permalink / raw)
To: linux-tip-commits
Cc: linux-kernel, hpa, mingo, lizf, namhyung, jolsa, tglx, dzickus
Commit-ID: 4b6279579c84cca7f162cfbcb98f66418f3062f3
Gitweb: http://git.kernel.org/tip/4b6279579c84cca7f162cfbcb98f66418f3062f3
Author: Don Zickus <dzickus@redhat.com>
AuthorDate: Mon, 7 Apr 2014 14:55:23 -0400
Committer: Jiri Olsa <jolsa@redhat.com>
CommitDate: Tue, 22 Apr 2014 17:39:20 +0200
perf kmem: Utilize the new generic cpunode_map
Use the previous patch implementation of cpunode_map for builtin-kmem.c
Should not be any functional difference.
Signed-off-by: Don Zickus <dzickus@redhat.com>
Reviewed-by: Namhyung Kim <namhyung@kernel.org>
Cc: Li Zefan <lizf@cn.fujitsu.com>
Link: http://lkml.kernel.org/r/1396896924-129847-4-git-send-email-dzickus@redhat.com
Signed-off-by: Jiri Olsa <jolsa@redhat.com>
---
tools/perf/builtin-kmem.c | 78 ++---------------------------------------------
1 file changed, 3 insertions(+), 75 deletions(-)
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index bd91de0..f91fa437 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -14,6 +14,7 @@
#include "util/parse-options.h"
#include "util/trace-event.h"
#include "util/data.h"
+#include "util/cpumap.h"
#include "util/debug.h"
@@ -31,9 +32,6 @@ static int caller_lines = -1;
static bool raw_ip;
-static int *cpunode_map;
-static int max_cpu_num;
-
struct alloc_stat {
u64 call_site;
u64 ptr;
@@ -55,76 +53,6 @@ static struct rb_root root_caller_sorted;
static unsigned long total_requested, total_allocated;
static unsigned long nr_allocs, nr_cross_allocs;
-#define PATH_SYS_NODE "/sys/devices/system/node"
-
-static int init_cpunode_map(void)
-{
- FILE *fp;
- int i, err = -1;
-
- fp = fopen("/sys/devices/system/cpu/kernel_max", "r");
- if (!fp) {
- max_cpu_num = 4096;
- return 0;
- }
-
- if (fscanf(fp, "%d", &max_cpu_num) < 1) {
- pr_err("Failed to read 'kernel_max' from sysfs");
- goto out_close;
- }
-
- max_cpu_num++;
-
- cpunode_map = calloc(max_cpu_num, sizeof(int));
- if (!cpunode_map) {
- pr_err("%s: calloc failed\n", __func__);
- goto out_close;
- }
-
- for (i = 0; i < max_cpu_num; i++)
- cpunode_map[i] = -1;
-
- err = 0;
-out_close:
- fclose(fp);
- return err;
-}
-
-static int setup_cpunode_map(void)
-{
- struct dirent *dent1, *dent2;
- DIR *dir1, *dir2;
- unsigned int cpu, mem;
- char buf[PATH_MAX];
-
- if (init_cpunode_map())
- return -1;
-
- dir1 = opendir(PATH_SYS_NODE);
- if (!dir1)
- return 0;
-
- while ((dent1 = readdir(dir1)) != NULL) {
- if (dent1->d_type != DT_DIR ||
- sscanf(dent1->d_name, "node%u", &mem) < 1)
- continue;
-
- snprintf(buf, PATH_MAX, "%s/%s", PATH_SYS_NODE, dent1->d_name);
- dir2 = opendir(buf);
- if (!dir2)
- continue;
- while ((dent2 = readdir(dir2)) != NULL) {
- if (dent2->d_type != DT_LNK ||
- sscanf(dent2->d_name, "cpu%u", &cpu) < 1)
- continue;
- cpunode_map[cpu] = mem;
- }
- closedir(dir2);
- }
- closedir(dir1);
- return 0;
-}
-
static int insert_alloc_stat(unsigned long call_site, unsigned long ptr,
int bytes_req, int bytes_alloc, int cpu)
{
@@ -235,7 +163,7 @@ static int perf_evsel__process_alloc_node_event(struct perf_evsel *evsel,
int ret = perf_evsel__process_alloc_event(evsel, sample);
if (!ret) {
- int node1 = cpunode_map[sample->cpu],
+ int node1 = cpu__get_node(sample->cpu),
node2 = perf_evsel__intval(evsel, sample, "node");
if (node1 != node2)
@@ -772,7 +700,7 @@ int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused)
if (!strncmp(argv[0], "rec", 3)) {
return __cmd_record(argc, argv);
} else if (!strcmp(argv[0], "stat")) {
- if (setup_cpunode_map())
+ if (cpu__setup_cpunode_map())
return -1;
if (list_empty(&caller_sort))
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [tip:perf/core] perf callchain: Add generic report parse callchain callback function
2014-04-07 18:55 ` [PATCH 4/4 v2] perf, callchain: Add generic report parse callchain callback function Don Zickus
@ 2014-04-22 18:34 ` tip-bot for Don Zickus
0 siblings, 0 replies; 14+ messages in thread
From: tip-bot for Don Zickus @ 2014-04-22 18:34 UTC (permalink / raw)
To: linux-tip-commits
Cc: linux-kernel, hpa, mingo, tglx, namhyung, jolsa, dzickus
Commit-ID: cff6bb46d477383092f46682a0d12e323e4b84d2
Gitweb: http://git.kernel.org/tip/cff6bb46d477383092f46682a0d12e323e4b84d2
Author: Don Zickus <dzickus@redhat.com>
AuthorDate: Mon, 7 Apr 2014 14:55:24 -0400
Committer: Jiri Olsa <jolsa@redhat.com>
CommitDate: Tue, 22 Apr 2014 17:39:24 +0200
perf callchain: Add generic report parse callchain callback function
This takes the parse_callchain_opt function and copies it into the
callchain.c file. Now the c2c tool can use it too without duplicating.
Update perf-report to use the new routine too.
Signed-off-by: Don Zickus <dzickus@redhat.com>
Reviewed-by: Namhyung Kim <namhyung@kernel.org>
Link: http://lkml.kernel.org/r/1396896924-129847-5-git-send-email-dzickus@redhat.com
[ Adding missing braces to multiline if condition ]
Signed-off-by: Jiri Olsa <jolsa@redhat.com>
---
tools/perf/builtin-report.c | 81 ++-------------------------------------------
tools/perf/util/callchain.c | 78 +++++++++++++++++++++++++++++++++++++++++++
tools/perf/util/callchain.h | 1 +
3 files changed, 82 insertions(+), 78 deletions(-)
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index af8cb7a..76e2bb6 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -589,11 +589,9 @@ static int __cmd_report(struct report *rep)
}
static int
-parse_callchain_opt(const struct option *opt, const char *arg, int unset)
+report_parse_callchain_opt(const struct option *opt, const char *arg, int unset)
{
struct report *rep = (struct report *)opt->value;
- char *tok, *tok2;
- char *endptr;
/*
* --no-call-graph
@@ -603,80 +601,7 @@ parse_callchain_opt(const struct option *opt, const char *arg, int unset)
return 0;
}
- symbol_conf.use_callchain = true;
-
- if (!arg)
- return 0;
-
- tok = strtok((char *)arg, ",");
- if (!tok)
- return -1;
-
- /* get the output mode */
- if (!strncmp(tok, "graph", strlen(arg)))
- callchain_param.mode = CHAIN_GRAPH_ABS;
-
- else if (!strncmp(tok, "flat", strlen(arg)))
- callchain_param.mode = CHAIN_FLAT;
-
- else if (!strncmp(tok, "fractal", strlen(arg)))
- callchain_param.mode = CHAIN_GRAPH_REL;
-
- else if (!strncmp(tok, "none", strlen(arg))) {
- callchain_param.mode = CHAIN_NONE;
- symbol_conf.use_callchain = false;
-
- return 0;
- }
-
- else
- return -1;
-
- /* get the min percentage */
- tok = strtok(NULL, ",");
- if (!tok)
- goto setup;
-
- callchain_param.min_percent = strtod(tok, &endptr);
- if (tok == endptr)
- return -1;
-
- /* get the print limit */
- tok2 = strtok(NULL, ",");
- if (!tok2)
- goto setup;
-
- if (tok2[0] != 'c') {
- callchain_param.print_limit = strtoul(tok2, &endptr, 0);
- tok2 = strtok(NULL, ",");
- if (!tok2)
- goto setup;
- }
-
- /* get the call chain order */
- if (!strncmp(tok2, "caller", strlen("caller")))
- callchain_param.order = ORDER_CALLER;
- else if (!strncmp(tok2, "callee", strlen("callee")))
- callchain_param.order = ORDER_CALLEE;
- else
- return -1;
-
- /* Get the sort key */
- tok2 = strtok(NULL, ",");
- if (!tok2)
- goto setup;
- if (!strncmp(tok2, "function", strlen("function")))
- callchain_param.key = CCKEY_FUNCTION;
- else if (!strncmp(tok2, "address", strlen("address")))
- callchain_param.key = CCKEY_ADDRESS;
- else
- return -1;
-setup:
- if (callchain_register_param(&callchain_param) < 0) {
- pr_err("Can't register callchain params\n");
- return -1;
- }
- return 0;
+ return parse_callchain_report_opt(arg);
}
int
@@ -788,7 +713,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
"Only display entries with parent-match"),
OPT_CALLBACK_DEFAULT('g', "call-graph", &report, "output_type,min_percent[,print_limit],call_order",
"Display callchains using output_type (graph, flat, fractal, or none) , min percent threshold, optional print limit, callchain order, key (function or address). "
- "Default: fractal,0.5,callee,function", &parse_callchain_opt, callchain_default_opt),
+ "Default: fractal,0.5,callee,function", &report_parse_callchain_opt, callchain_default_opt),
OPT_INTEGER(0, "max-stack", &report.max_stack,
"Set the maximum stack depth when parsing the callchain, "
"anything beyond the specified depth will be ignored. "
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index 8d9db45..9a42382 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -25,6 +25,84 @@
__thread struct callchain_cursor callchain_cursor;
+int
+parse_callchain_report_opt(const char *arg)
+{
+ char *tok, *tok2;
+ char *endptr;
+
+ symbol_conf.use_callchain = true;
+
+ if (!arg)
+ return 0;
+
+ tok = strtok((char *)arg, ",");
+ if (!tok)
+ return -1;
+
+ /* get the output mode */
+ if (!strncmp(tok, "graph", strlen(arg))) {
+ callchain_param.mode = CHAIN_GRAPH_ABS;
+
+ } else if (!strncmp(tok, "flat", strlen(arg))) {
+ callchain_param.mode = CHAIN_FLAT;
+ } else if (!strncmp(tok, "fractal", strlen(arg))) {
+ callchain_param.mode = CHAIN_GRAPH_REL;
+ } else if (!strncmp(tok, "none", strlen(arg))) {
+ callchain_param.mode = CHAIN_NONE;
+ symbol_conf.use_callchain = false;
+ return 0;
+ } else {
+ return -1;
+ }
+
+ /* get the min percentage */
+ tok = strtok(NULL, ",");
+ if (!tok)
+ goto setup;
+
+ callchain_param.min_percent = strtod(tok, &endptr);
+ if (tok == endptr)
+ return -1;
+
+ /* get the print limit */
+ tok2 = strtok(NULL, ",");
+ if (!tok2)
+ goto setup;
+
+ if (tok2[0] != 'c') {
+ callchain_param.print_limit = strtoul(tok2, &endptr, 0);
+ tok2 = strtok(NULL, ",");
+ if (!tok2)
+ goto setup;
+ }
+
+ /* get the call chain order */
+ if (!strncmp(tok2, "caller", strlen("caller")))
+ callchain_param.order = ORDER_CALLER;
+ else if (!strncmp(tok2, "callee", strlen("callee")))
+ callchain_param.order = ORDER_CALLEE;
+ else
+ return -1;
+
+ /* Get the sort key */
+ tok2 = strtok(NULL, ",");
+ if (!tok2)
+ goto setup;
+ if (!strncmp(tok2, "function", strlen("function")))
+ callchain_param.key = CCKEY_FUNCTION;
+ else if (!strncmp(tok2, "address", strlen("address")))
+ callchain_param.key = CCKEY_ADDRESS;
+ else
+ return -1;
+setup:
+ if (callchain_register_param(&callchain_param) < 0) {
+ pr_err("Can't register callchain params\n");
+ return -1;
+ }
+ return 0;
+}
+
static void
rb_insert_callchain(struct rb_root *root, struct callchain_node *chain,
enum chain_mode mode)
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index 8ad97e9..dda4cf8 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -157,4 +157,5 @@ int sample__resolve_callchain(struct perf_sample *sample, struct symbol **parent
int hist_entry__append_callchain(struct hist_entry *he, struct perf_sample *sample);
extern const char record_callchain_help[];
+int parse_callchain_report_opt(const char *arg);
#endif /* __PERF_CALLCHAIN_H */
^ permalink raw reply related [flat|nested] 14+ messages in thread
end of thread, other threads:[~2014-04-22 18:35 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-04-07 18:55 [PATCH 0/4 v2] perf: Make some functions generic Don Zickus
2014-04-07 18:55 ` [PATCH 1/4 v2] perf: Allow ability to map cpus to nodes easily Don Zickus
2014-04-10 9:31 ` Jiri Olsa
2014-04-10 13:15 ` Don Zickus
2014-04-10 13:24 ` Jiri Olsa
2014-04-10 13:54 ` Don Zickus
2014-04-22 18:34 ` [tip:perf/core] perf tools: " tip-bot for Don Zickus
2014-04-07 18:55 ` [PATCH 2/4 v2] perf: Use cpu/possible instead of cpu/kernel_max Don Zickus
2014-04-22 18:34 ` [tip:perf/core] perf tools: Use cpu/possible instead of cpu/ kernel_max tip-bot for Don Zickus
2014-04-07 18:55 ` [PATCH 3/4 v2] perf, kmem: Utilize the new generic cpunode_map Don Zickus
2014-04-22 18:34 ` [tip:perf/core] perf " tip-bot for Don Zickus
2014-04-07 18:55 ` [PATCH 4/4 v2] perf, callchain: Add generic report parse callchain callback function Don Zickus
2014-04-22 18:34 ` [tip:perf/core] perf " tip-bot for Don Zickus
2014-04-09 0:31 ` [PATCH 0/4 v2] perf: Make some functions generic Namhyung Kim
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.