This patch will make all print functions receive the fp, add the 
fp_selection_helper
function to select the fp(stdout or the dump_event fp) and open the dump file 
for
all print functions. When the perf script is over, closes the dump_event file 
and
calculates its size.

Changes since v4:
- the fp_selection_helper will be invoked by process_event not 
process_sample_event
- replace some printf with fprintf in process_event

Changes since v3:
- free the evsel->priv by zfree()

Changes since v2:
- remove the file_name variable and get the data file name from struct 
perf_session
- remove the per_event_dump_file variable and get the dump_event fp from struct
 perf_evsel
- add the fp_selection_helper function to select the fp(stdout or the dump_event
 fp) and open the dump file for all print functions if evname and last evsel 
name is not
 the same.
- close the dump file for all the evsels and calculate the dump file's size at 
the end of
 the perf script.
- solve the segmentation fault generated by perf script --per-event-dump 
--show-mmap-events

Changes since v1:
- modify the dump file name to <ORIGINAL PERF DATA FILE 
NAME>-script-dump-<EVENT NAME>.txt
 ect. perf.data-script-dump-cycles.txt, perf.data-script-dump-cs.txt
- split the original patch(Make all those related functions receive the file 
pointer)
 to two patches, and this is the second part of the original one.

Signed-off-by: yuzhoujian <yuzhouj...@didichuxing.com>
---
 tools/perf/builtin-script.c | 107 +++++++++++++++++++++++++++++++++++---------
 tools/perf/util/session.c   |  19 ++++++++
 2 files changed, 106 insertions(+), 20 deletions(-)

diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 81f141f..8d98349 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -1431,6 +1431,50 @@ static int data_src__fprintf(u64 data_src, FILE *fp)
        return fprintf(fp, "%-*s", maxlen, out);
 }
 
+static FILE *fp_selection_helper(struct perf_script *script, struct perf_evsel 
*evsel)
+{
+       const char *evname;
+       char *filename;
+       FILE *fp;
+       struct perf_tool *tool = &script->tool;
+       struct perf_script_evsel *ps;
+
+       evname = perf_evsel__name(evsel);
+       if (tool->per_event_dump) {
+               ps = (struct perf_script_evsel *)evsel->priv;
+
+               /* if evname and last evsel name is not the same, opens another 
dump file. */
+               if (evname != tool->last_evsel_name) {
+                       if (asprintf(&filename, "%s%s%s%s", 
script->session->file->path,
+                               "-script-dump-", evname, ".txt") < 0)
+                               BUG_ON("fail to add the suffix for dump file's 
name!\n");
+
+                       fp = fopen(filename, "a+");
+                       if (!fp)
+                               BUG_ON("fail to open the dump file!\n");
+
+                       if (!ps) {
+                               ps = zalloc(sizeof(struct perf_script_evsel));
+                               if (!ps)
+                                       BUG_ON("fail to create a 
perf_script_evsel struct!\n");
+                               ps->samples = 0;
+                       }
+                       ps->filename = filename;
+                       ps->dump_evsel_fp = fp;
+                       tool->last_evsel_name = evname;
+                       evsel->priv = ps;
+               } else {
+                       if (ps->dump_evsel_fp)
+                               fp = ps->dump_evsel_fp;
+                       else
+                               BUG_ON("fail to get the dump file's fp!\n");
+               }
+       } else {
+               fp = stdout;
+       }
+       return fp;
+}
+
 static void process_event(struct perf_script *script,
                          struct perf_sample *sample, struct perf_evsel *evsel,
                          struct addr_location *al,
@@ -1439,15 +1483,25 @@ static void process_event(struct perf_script *script,
        struct thread *thread = al->thread;
        struct perf_event_attr *attr = &evsel->attr;
        unsigned int type = output_type(attr->type);
-       FILE *fp = stdout;
+       struct perf_script_evsel *ps;
+       struct perf_tool *tool = &script->tool;
+       FILE *fp;
+
+       fp = fp_selection_helper(script, evsel);
 
        if (output[type].fields == 0)
                return;
 
+       if (tool->per_event_dump) {
+               ps = (struct perf_script_evsel *)evsel->priv;
+               ps->samples++;
+               evsel->priv = ps;
+       }
+
        perf_sample__fprintf_start(sample, thread, evsel, fp);
 
        if (PRINT_FIELD(PERIOD))
-               printf("%10" PRIu64 " ", sample->period);
+               fprintf(fp, "%10" PRIu64 " ", sample->period);
 
        if (PRINT_FIELD(EVNAME)) {
                const char *evname = perf_evsel__name(evsel);
@@ -1455,7 +1509,7 @@ static void process_event(struct perf_script *script,
                if (!script->name_width)
                        script->name_width = 
perf_evlist__max_name_len(script->session->evlist);
 
-               printf("%*s: ", script->name_width,
+               fprintf(fp, "%*s: ", script->name_width,
                       evname ? evname : "[unknown]");
        }
 
@@ -1513,8 +1567,8 @@ static void process_event(struct perf_script *script,
        perf_sample__fprintf_insn(sample, attr, thread, machine, fp);
 
        if (PRINT_FIELD(PHYS_ADDR))
-               printf("%16" PRIx64, sample->phys_addr);
-       printf("\n");
+               fprintf(fp, "%16" PRIx64, sample->phys_addr);
+       fprintf(fp, "\n");
 }
 
 static struct scripting_ops    *scripting_ops;
@@ -1671,6 +1725,7 @@ static int process_comm_event(struct perf_tool *tool,
        struct perf_script *script = container_of(tool, struct perf_script, 
tool);
        struct perf_session *session = script->session;
        struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, 
sample->id);
+       FILE *fp;
        int ret = -1;
 
        thread = machine__findnew_thread(machine, event->comm.pid, 
event->comm.tid);
@@ -1688,8 +1743,9 @@ static int process_comm_event(struct perf_tool *tool,
                sample->tid = event->comm.tid;
                sample->pid = event->comm.pid;
        }
-       perf_sample__fprintf_start(sample, thread, evsel, stdout);
-       perf_event__fprintf(event, stdout);
+       fp = fp_selection_helper(script, evsel);
+       perf_sample__fprintf_start(sample, thread, evsel, fp);
+       perf_event__fprintf(event, fp);
        ret = 0;
 out:
        thread__put(thread);
@@ -1705,6 +1761,7 @@ static int process_namespaces_event(struct perf_tool 
*tool,
        struct perf_script *script = container_of(tool, struct perf_script, 
tool);
        struct perf_session *session = script->session;
        struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, 
sample->id);
+       FILE *fp;
        int ret = -1;
 
        thread = machine__findnew_thread(machine, event->namespaces.pid,
@@ -1723,8 +1780,9 @@ static int process_namespaces_event(struct perf_tool 
*tool,
                sample->tid = event->namespaces.tid;
                sample->pid = event->namespaces.pid;
        }
-       perf_sample__fprintf_start(sample, thread, evsel, stdout);
-       perf_event__fprintf(event, stdout);
+       fp = fp_selection_helper(script, evsel);
+       perf_sample__fprintf_start(sample, thread, evsel, fp);
+       perf_event__fprintf(event, fp);
        ret = 0;
 out:
        thread__put(thread);
@@ -1740,6 +1798,7 @@ static int process_fork_event(struct perf_tool *tool,
        struct perf_script *script = container_of(tool, struct perf_script, 
tool);
        struct perf_session *session = script->session;
        struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, 
sample->id);
+       FILE *fp;
 
        if (perf_event__process_fork(tool, event, sample, machine) < 0)
                return -1;
@@ -1756,8 +1815,9 @@ static int process_fork_event(struct perf_tool *tool,
                sample->tid = event->fork.tid;
                sample->pid = event->fork.pid;
        }
-       perf_sample__fprintf_start(sample, thread, evsel, stdout);
-       perf_event__fprintf(event, stdout);
+       fp = fp_selection_helper(script, evsel);
+       perf_sample__fprintf_start(sample, thread, evsel, fp);
+       perf_event__fprintf(event, fp);
        thread__put(thread);
 
        return 0;
@@ -1772,6 +1832,7 @@ static int process_exit_event(struct perf_tool *tool,
        struct perf_script *script = container_of(tool, struct perf_script, 
tool);
        struct perf_session *session = script->session;
        struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, 
sample->id);
+       FILE *fp;
 
        thread = machine__findnew_thread(machine, event->fork.pid, 
event->fork.tid);
        if (thread == NULL) {
@@ -1785,8 +1846,9 @@ static int process_exit_event(struct perf_tool *tool,
                sample->tid = event->fork.tid;
                sample->pid = event->fork.pid;
        }
-       perf_sample__fprintf_start(sample, thread, evsel, stdout);
-       perf_event__fprintf(event, stdout);
+       fp = fp_selection_helper(script, evsel);
+       perf_sample__fprintf_start(sample, thread, evsel, fp);
+       perf_event__fprintf(event, fp);
 
        if (perf_event__process_exit(tool, event, sample, machine) < 0)
                err = -1;
@@ -1804,6 +1866,7 @@ static int process_mmap_event(struct perf_tool *tool,
        struct perf_script *script = container_of(tool, struct perf_script, 
tool);
        struct perf_session *session = script->session;
        struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, 
sample->id);
+       FILE *fp;
 
        if (perf_event__process_mmap(tool, event, sample, machine) < 0)
                return -1;
@@ -1820,8 +1883,9 @@ static int process_mmap_event(struct perf_tool *tool,
                sample->tid = event->mmap.tid;
                sample->pid = event->mmap.pid;
        }
-       perf_sample__fprintf_start(sample, thread, evsel, stdout);
-       perf_event__fprintf(event, stdout);
+       fp = fp_selection_helper(script, evsel);
+       perf_sample__fprintf_start(sample, thread, evsel, fp);
+       perf_event__fprintf(event, fp);
        thread__put(thread);
        return 0;
 }
@@ -1835,6 +1899,7 @@ static int process_mmap2_event(struct perf_tool *tool,
        struct perf_script *script = container_of(tool, struct perf_script, 
tool);
        struct perf_session *session = script->session;
        struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, 
sample->id);
+       FILE *fp;
 
        if (perf_event__process_mmap2(tool, event, sample, machine) < 0)
                return -1;
@@ -1851,8 +1916,9 @@ static int process_mmap2_event(struct perf_tool *tool,
                sample->tid = event->mmap2.tid;
                sample->pid = event->mmap2.pid;
        }
-       perf_sample__fprintf_start(sample, thread, evsel, stdout);
-       perf_event__fprintf(event, stdout);
+       fp = fp_selection_helper(script, evsel);
+       perf_sample__fprintf_start(sample, thread, evsel, fp);
+       perf_event__fprintf(event, fp);
        thread__put(thread);
        return 0;
 }
@@ -1866,6 +1932,7 @@ static int process_switch_event(struct perf_tool *tool,
        struct perf_script *script = container_of(tool, struct perf_script, 
tool);
        struct perf_session *session = script->session;
        struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, 
sample->id);
+       FILE *fp;
 
        if (perf_event__process_switch(tool, event, sample, machine) < 0)
                return -1;
@@ -1876,9 +1943,9 @@ static int process_switch_event(struct perf_tool *tool,
                pr_debug("problem processing SWITCH event, skipping it.\n");
                return -1;
        }
-
-       perf_sample__fprintf_start(sample, thread, evsel, stdout);
-       perf_event__fprintf(event, stdout);
+       fp = fp_selection_helper(script, evsel);
+       perf_sample__fprintf_start(sample, thread, evsel, fp);
+       perf_event__fprintf(event, fp);
        thread__put(thread);
        return 0;
 }
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index b3fd62f..0a4784f 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -8,6 +8,8 @@
 #include <unistd.h>
 #include <sys/types.h>
 #include <sys/mman.h>
+#include <sys/stat.h>
+#include <stdio.h>
 
 #include "evlist.h"
 #include "evsel.h"
@@ -1828,6 +1830,9 @@ static int __perf_session__process_events(struct 
perf_session *session,
 {
        struct ordered_events *oe = &session->ordered_events;
        struct perf_tool *tool = session->tool;
+       struct perf_evlist *evlist = session->evlist;
+       struct perf_evsel *evsel;
+       struct perf_script_evsel *ps;
        int fd = perf_data_file__fd(session->file);
        u64 head, page_offset, file_offset, file_pos, size;
        int err, mmap_prot, mmap_flags, map_idx = 0;
@@ -1835,6 +1840,7 @@ static int __perf_session__process_events(struct 
perf_session *session,
        char *buf, *mmaps[NUM_MMAPS];
        union perf_event *event;
        struct ui_progress prog;
+       struct stat statbuf;
        s64 skip;
 
        perf_tool__fill_defaults(tool);
@@ -1940,6 +1946,19 @@ static int __perf_session__process_events(struct 
perf_session *session,
        ordered_events__reinit(&session->ordered_events);
        auxtrace__free_events(session);
        session->one_mmap = false;
+       /* Closes the dump_event file and calculates its size at last. */
+       if (tool->per_event_dump) {
+               evlist__for_each_entry(evlist, evsel) {
+                       ps = (struct perf_script_evsel *)evsel->priv;
+                       if (!ps)
+                               BUG_ON("fail to get the perf_script_evsel\n");
+                       stat(ps->filename, &statbuf);
+                       fprintf(stderr, "[ perf script: Wrote %.3f MB %s (%" 
PRIu64 " samples) ]\n",
+                               statbuf.st_size / 1024.0 / 1024.0, 
ps->filename, ps->samples);
+                       fclose(ps->dump_evsel_fp);
+                       zfree(&evsel->priv);
+               }
+       }
        return err;
 }
 
-- 
1.8.3.1

Reply via email to