From: Arnaldo Carvalho de Melo <acme@kernel.org>
To: Ingo Molnar <mingo@kernel.org>
Cc: linux-kernel@vger.kernel.org, Wang Nan <wangnan0@huawei.com>,
Alexei Starovoitov <ast@kernel.org>,
Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>,
Zefan Li <lizefan@huawei.com>,
pi3orama@163.com, Arnaldo Carvalho de Melo <acme@redhat.com>
Subject: [PATCH 15/37] perf bpf: Use same BPF program if arguments are identical
Date: Thu, 19 Nov 2015 14:53:01 -0300 [thread overview]
Message-ID: <1447955603-24895-16-git-send-email-acme@kernel.org> (raw)
In-Reply-To: <1447955603-24895-1-git-send-email-acme@kernel.org>
From: Wang Nan <wangnan0@huawei.com>
This patch allows creating only one BPF program for different
'probe_trace_event'(tev) entries generated by one
'perf_probe_event'(pev) if their prologues are identical.
This is done by comparing the argument list of different tev instances,
and the maps type of prologue and tev using a mapping array. This patch
utilizes qsort to sort the tevs. After sorting, tevs with identical
argument lists will be grouped together.
Test result:
Sample BPF program:
#define SEC(NAME) __attribute__((section(NAME), used))
SEC("inlines=no;"
"func=SyS_dup? oldfd")
int func(void *ctx)
{
return 1;
}
It would probe at SyS_dup2 and SyS_dup3, obtaining oldfd as its
argument.
The following cmdline shows a BPF program being loaded into the kernel
by perf:
# perf record -e ./test_bpf_arg.c sleep 4 & sleep 1 && ls /proc/$!/fd/ -l | grep bpf-prog
Before this patch:
# perf record -e ./test_bpf_arg.c sleep 4 & sleep 1 && ls /proc/$!/fd/ -l | grep bpf-prog
[1] 24858
lrwx------ 1 root root 64 Nov 14 04:09 3 -> anon_inode:bpf-prog
lrwx------ 1 root root 64 Nov 14 04:09 4 -> anon_inode:bpf-prog
...
After this patch:
# perf record -e ./test_bpf_arg.c sleep 4 & sleep 1 && ls /proc/$!/fd/ -l | grep bpf-prog
[1] 25699
lrwx------ 1 root root 64 Nov 14 04:10 3 -> anon_inode:bpf-prog
...
Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Link: http://lkml.kernel.org/r/1447749170-175898-3-git-send-email-wangnan0@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/util/bpf-loader.c | 138 ++++++++++++++++++++++++++++++++++++++++---
1 file changed, 131 insertions(+), 7 deletions(-)
diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index 190a1c7f0649..36544e5ece43 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -38,6 +38,8 @@ struct bpf_prog_priv {
struct perf_probe_event pev;
bool need_prologue;
struct bpf_insn *insns_buf;
+ int nr_types;
+ int *type_mapping;
};
static bool libbpf_initialized;
@@ -113,6 +115,7 @@ bpf_prog_priv__clear(struct bpf_program *prog __maybe_unused,
cleanup_perf_probe_events(&priv->pev, 1);
zfree(&priv->insns_buf);
+ zfree(&priv->type_mapping);
free(priv);
}
@@ -381,7 +384,7 @@ preproc_gen_prologue(struct bpf_program *prog, int n,
struct bpf_prog_priv *priv;
struct bpf_insn *buf;
size_t prologue_cnt = 0;
- int err;
+ int i, err;
err = bpf_program__get_private(prog, (void **)&priv);
if (err || !priv)
@@ -389,10 +392,21 @@ preproc_gen_prologue(struct bpf_program *prog, int n,
pev = &priv->pev;
- if (n < 0 || n >= pev->ntevs)
+ if (n < 0 || n >= priv->nr_types)
goto errout;
- tev = &pev->tevs[n];
+ /* Find a tev belongs to that type */
+ for (i = 0; i < pev->ntevs; i++) {
+ if (priv->type_mapping[i] == n)
+ break;
+ }
+
+ if (i >= pev->ntevs) {
+ pr_debug("Internal error: prologue type %d not found\n", n);
+ return -BPF_LOADER_ERRNO__PROLOGUE;
+ }
+
+ tev = &pev->tevs[i];
buf = priv->insns_buf;
err = bpf__gen_prologue(tev->args, tev->nargs,
@@ -423,6 +437,101 @@ errout:
return -BPF_LOADER_ERRNO__PROLOGUE;
}
+/*
+ * compare_tev_args is reflexive, transitive and antisymmetric.
+ * I can proof it but this margin is too narrow to contain.
+ */
+static int compare_tev_args(const void *ptev1, const void *ptev2)
+{
+ int i, ret;
+ const struct probe_trace_event *tev1 =
+ *(const struct probe_trace_event **)ptev1;
+ const struct probe_trace_event *tev2 =
+ *(const struct probe_trace_event **)ptev2;
+
+ ret = tev2->nargs - tev1->nargs;
+ if (ret)
+ return ret;
+
+ for (i = 0; i < tev1->nargs; i++) {
+ struct probe_trace_arg *arg1, *arg2;
+ struct probe_trace_arg_ref *ref1, *ref2;
+
+ arg1 = &tev1->args[i];
+ arg2 = &tev2->args[i];
+
+ ret = strcmp(arg1->value, arg2->value);
+ if (ret)
+ return ret;
+
+ ref1 = arg1->ref;
+ ref2 = arg2->ref;
+
+ while (ref1 && ref2) {
+ ret = ref2->offset - ref1->offset;
+ if (ret)
+ return ret;
+
+ ref1 = ref1->next;
+ ref2 = ref2->next;
+ }
+
+ if (ref1 || ref2)
+ return ref2 ? 1 : -1;
+ }
+
+ return 0;
+}
+
+/*
+ * Assign a type number to each tevs in a pev.
+ * mapping is an array with same slots as tevs in that pev.
+ * nr_types will be set to number of types.
+ */
+static int map_prologue(struct perf_probe_event *pev, int *mapping,
+ int *nr_types)
+{
+ int i, type = 0;
+ struct probe_trace_event **ptevs;
+
+ size_t array_sz = sizeof(*ptevs) * pev->ntevs;
+
+ ptevs = malloc(array_sz);
+ if (!ptevs) {
+ pr_debug("No ehough memory: alloc ptevs failed\n");
+ return -ENOMEM;
+ }
+
+ pr_debug("In map_prologue, ntevs=%d\n", pev->ntevs);
+ for (i = 0; i < pev->ntevs; i++)
+ ptevs[i] = &pev->tevs[i];
+
+ qsort(ptevs, pev->ntevs, sizeof(*ptevs),
+ compare_tev_args);
+
+ for (i = 0; i < pev->ntevs; i++) {
+ int n;
+
+ n = ptevs[i] - pev->tevs;
+ if (i == 0) {
+ mapping[n] = type;
+ pr_debug("mapping[%d]=%d\n", n, type);
+ continue;
+ }
+
+ if (compare_tev_args(ptevs + i, ptevs + i - 1) == 0)
+ mapping[n] = type;
+ else
+ mapping[n] = ++type;
+
+ pr_debug("mapping[%d]=%d\n", n, mapping[n]);
+ }
+ free(ptevs);
+ *nr_types = type + 1;
+
+ return 0;
+}
+
static int hook_load_preprocessor(struct bpf_program *prog)
{
struct perf_probe_event *pev;
@@ -462,7 +571,19 @@ static int hook_load_preprocessor(struct bpf_program *prog)
return -ENOMEM;
}
- err = bpf_program__set_prep(prog, pev->ntevs,
+ priv->type_mapping = malloc(sizeof(int) * pev->ntevs);
+ if (!priv->type_mapping) {
+ pr_debug("No enough memory: alloc type_mapping failed\n");
+ return -ENOMEM;
+ }
+ memset(priv->type_mapping, -1,
+ sizeof(int) * pev->ntevs);
+
+ err = map_prologue(pev, priv->type_mapping, &priv->nr_types);
+ if (err)
+ return err;
+
+ err = bpf_program__set_prep(prog, priv->nr_types,
preproc_gen_prologue);
return err;
}
@@ -596,10 +717,13 @@ int bpf__foreach_tev(struct bpf_object *obj,
for (i = 0; i < pev->ntevs; i++) {
tev = &pev->tevs[i];
- if (priv->need_prologue)
- fd = bpf_program__nth_fd(prog, i);
- else
+ if (priv->need_prologue) {
+ int type = priv->type_mapping[i];
+
+ fd = bpf_program__nth_fd(prog, type);
+ } else {
fd = bpf_program__fd(prog);
+ }
if (fd < 0) {
pr_debug("bpf: failed to get file descriptor\n");
--
2.1.0
next prev parent reply other threads:[~2015-11-19 17:58 UTC|newest]
Thread overview: 51+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-11-19 17:52 [GIT PULL 00/37] perf/core improvements and fixes Arnaldo Carvalho de Melo
2015-11-19 17:52 ` [PATCH 01/37] perf test: Fix build of BPF and LLVM on older glibc libraries Arnaldo Carvalho de Melo
2015-11-19 17:52 ` [PATCH 02/37] tools: Fix selftests_install Makefile rule Arnaldo Carvalho de Melo
2015-11-19 17:52 ` [PATCH 03/37] tools: Adopt memdup() from tools/perf, moving it to tools/lib/string.c Arnaldo Carvalho de Melo
2015-11-19 17:52 ` [PATCH 04/37] tools: Clone the kernel's strtobool function Arnaldo Carvalho de Melo
2015-11-19 17:52 ` [PATCH 05/37] bpf tools: Load a program with different instances using preprocessor Arnaldo Carvalho de Melo
2015-11-19 17:52 ` [PATCH 06/37] perf bpf: Add BPF_PROLOGUE config options for further patches Arnaldo Carvalho de Melo
2015-11-19 17:52 ` [PATCH 07/37] perf bpf: Compile dwarf-regs.c if CONFIG_BPF_PROLOGUE is on Arnaldo Carvalho de Melo
2015-11-19 17:52 ` [PATCH 08/37] perf bpf: Allow BPF program attach to uprobe events Arnaldo Carvalho de Melo
2015-11-19 17:52 ` [PATCH 09/37] perf bpf: Allow attaching BPF programs to modules symbols Arnaldo Carvalho de Melo
2015-11-19 17:52 ` [PATCH 10/37] perf bpf: Allow BPF program config probing options Arnaldo Carvalho de Melo
2015-11-19 17:52 ` [PATCH 11/37] perf bpf: Add prologue for BPF programs for fetching arguments Arnaldo Carvalho de Melo
2015-11-19 17:52 ` [PATCH 12/37] perf bpf: Generate prologue for BPF programs Arnaldo Carvalho de Melo
2015-11-19 17:52 ` [PATCH 13/37] perf test: Test the BPF prologue adding infrastructure Arnaldo Carvalho de Melo
2015-11-19 17:53 ` [PATCH 14/37] perf test: Fix 'perf test BPF' when it fails to find a suitable vmlinux Arnaldo Carvalho de Melo
2015-11-19 17:53 ` Arnaldo Carvalho de Melo [this message]
2015-11-19 17:53 ` [PATCH 16/37] perf tests: Pass the subtest index to each test routine Arnaldo Carvalho de Melo
2015-11-19 17:53 ` [PATCH 17/37] perf test: Print result for each LLVM subtest Arnaldo Carvalho de Melo
2015-11-19 17:53 ` [PATCH 18/37] perf test: Print result for each BPF subtest Arnaldo Carvalho de Melo
2015-11-19 17:53 ` [PATCH 19/37] perf test: Mute test cases error messages if verbose == 0 Arnaldo Carvalho de Melo
2015-11-19 17:53 ` [PATCH 20/37] perf probe: Fix to free temporal Dwarf_Frame Arnaldo Carvalho de Melo
2015-11-19 17:53 ` [PATCH 21/37] perf machine: Fix machine__findnew_module_map to put registered map Arnaldo Carvalho de Melo
2015-11-19 17:53 ` [PATCH 22/37] perf machine: Fix machine__destroy_kernel_maps to drop vmlinux_maps references Arnaldo Carvalho de Melo
2015-11-19 17:53 ` [PATCH 23/37] perf machine: Fix to destroy kernel maps when machine exits Arnaldo Carvalho de Melo
2015-11-19 17:53 ` [PATCH 24/37] perf tools: Make perf_exec_path() always return malloc'd string Arnaldo Carvalho de Melo
2015-11-19 17:53 ` [PATCH 25/37] perf tools: Fix to put new map after inserting to map_groups in dso__load_sym Arnaldo Carvalho de Melo
2015-11-19 17:53 ` [PATCH 26/37] perf tools: Fix __dsos__addnew to put dso after adding it to the list Arnaldo Carvalho de Melo
2015-11-19 17:53 ` [PATCH 27/37] perf tools: Fix machine__create_kernel_maps to put kernel dso refcount Arnaldo Carvalho de Melo
2015-11-19 17:53 ` [PATCH 28/37] perf machine: Fix machine__findnew_module_map to put dso Arnaldo Carvalho de Melo
2015-11-19 17:53 ` [PATCH 29/37] perf report: Support folded callchain mode on --stdio Arnaldo Carvalho de Melo
2015-11-19 17:53 ` [PATCH 30/37] perf callchain: Abstract callchain print function Arnaldo Carvalho de Melo
2015-11-19 17:53 ` [PATCH 31/37] perf callchain: Add count fields to struct callchain_node Arnaldo Carvalho de Melo
2015-11-23 14:35 ` Frederic Weisbecker
2015-11-24 5:15 ` Namhyung Kim
2015-11-19 17:53 ` [PATCH 32/37] perf report: Add callchain value option Arnaldo Carvalho de Melo
2015-11-19 17:53 ` [PATCH 33/37] perf hists browser: Factor out hist_browser__show_callchain_list() Arnaldo Carvalho de Melo
2015-11-19 17:53 ` [PATCH 34/37] perf hists browser: Support flat callchains Arnaldo Carvalho de Melo
2015-11-23 15:16 ` Frederic Weisbecker
2015-11-24 5:27 ` Namhyung Kim
2015-11-24 14:45 ` Arnaldo Carvalho de Melo
2015-11-25 1:26 ` Namhyung Kim
2015-11-25 1:34 ` Arnaldo Carvalho de Melo
2015-11-25 2:10 ` Arnaldo Carvalho de Melo
2015-11-25 21:03 ` Namhyung Kim
2015-11-19 17:53 ` [PATCH 35/37] perf hists browser: Support folded callchains Arnaldo Carvalho de Melo
2015-11-19 17:53 ` [PATCH 36/37] perf ui/gtk: Support flat callchains Arnaldo Carvalho de Melo
2015-11-19 17:53 ` [PATCH 37/37] perf ui/gtk: Support folded callchains Arnaldo Carvalho de Melo
2015-11-20 10:01 ` [GIT PULL 00/37] perf/core improvements and fixes 平松雅巳 / HIRAMATU,MASAMI
2015-11-20 12:08 ` 'Arnaldo Carvalho de Melo'
2015-11-20 16:50 ` 平松雅巳 / HIRAMATU,MASAMI
2015-11-23 8:16 ` Ingo Molnar
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1447955603-24895-16-git-send-email-acme@kernel.org \
--to=acme@kernel.org \
--cc=acme@redhat.com \
--cc=ast@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=lizefan@huawei.com \
--cc=masami.hiramatsu.pt@hitachi.com \
--cc=mingo@kernel.org \
--cc=pi3orama@163.com \
--cc=wangnan0@huawei.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Powered by JetHome