aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/db-export.c
diff options
context:
space:
mode:
authorAdrian Hunter <adrian.hunter@intel.com>2014-10-23 06:45:13 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2014-10-29 08:32:49 -0400
commit0db15b1e84a59e6e1da5fe6e74c35fe52fa29d92 (patch)
tree58834174c0672d033286fd21757091bcbb97ae45 /tools/perf/util/db-export.c
parent7e4772dc99a3ebfc53708eff262f7a8155485e85 (diff)
perf tools: Add facility to export data in database-friendly way
This patch introduces an abstraction for exporting sample data in a database-friendly way. The abstraction does not implement the actual output. A subsequent patch takes this facility into use for extending the script interface. The abstraction is needed because static data like symbols, dsos, comms etc need to be exported only once. That means allocating them a unique identifier and recording it on each structure. The member 'db_id' is used for that. 'db_id' is just a 64-bit sequence number. Exporting centres around the db_export__sample() function which exports the associated data structures if they have not yet been allocated a db_id. Signed-off-by: Adrian Hunter <adrian.hunter@intel.com> Cc: David Ahern <dsahern@gmail.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Namhyung Kim <namhyung@gmail.com> Cc: Paul Mackerras <paulus@samba.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Stephane Eranian <eranian@google.com> Link: http://lkml.kernel.org/r/1414061124-26830-6-git-send-email-adrian.hunter@intel.com [ committer note: Stash db_id using symbol_conf.priv_size + symbol__priv() and foo->priv areas ] Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/util/db-export.c')
-rw-r--r--tools/perf/util/db-export.c270
1 files changed, 270 insertions, 0 deletions
diff --git a/tools/perf/util/db-export.c b/tools/perf/util/db-export.c
new file mode 100644
index 000000000000..be128b075a32
--- /dev/null
+++ b/tools/perf/util/db-export.c
@@ -0,0 +1,270 @@
1/*
2 * db-export.c: Support for exporting data suitable for import to a database
3 * Copyright (c) 2014, Intel Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 */
15
16#include <errno.h>
17
18#include "evsel.h"
19#include "machine.h"
20#include "thread.h"
21#include "comm.h"
22#include "symbol.h"
23#include "event.h"
24#include "db-export.h"
25
26int db_export__init(struct db_export *dbe)
27{
28 memset(dbe, 0, sizeof(struct db_export));
29 return 0;
30}
31
32void db_export__exit(struct db_export *dbe __maybe_unused)
33{
34}
35
36int db_export__evsel(struct db_export *dbe, struct perf_evsel *evsel)
37{
38 if (evsel->db_id)
39 return 0;
40
41 evsel->db_id = ++dbe->evsel_last_db_id;
42
43 if (dbe->export_evsel)
44 return dbe->export_evsel(dbe, evsel);
45
46 return 0;
47}
48
49int db_export__machine(struct db_export *dbe, struct machine *machine)
50{
51 if (machine->db_id)
52 return 0;
53
54 machine->db_id = ++dbe->machine_last_db_id;
55
56 if (dbe->export_machine)
57 return dbe->export_machine(dbe, machine);
58
59 return 0;
60}
61
62int db_export__thread(struct db_export *dbe, struct thread *thread,
63 struct machine *machine, struct comm *comm)
64{
65 u64 main_thread_db_id = 0;
66 int err;
67
68 if (thread->db_id)
69 return 0;
70
71 thread->db_id = ++dbe->thread_last_db_id;
72
73 if (thread->pid_ != -1) {
74 struct thread *main_thread;
75
76 if (thread->pid_ == thread->tid) {
77 main_thread = thread;
78 } else {
79 main_thread = machine__findnew_thread(machine,
80 thread->pid_,
81 thread->pid_);
82 if (!main_thread)
83 return -ENOMEM;
84 err = db_export__thread(dbe, main_thread, machine,
85 comm);
86 if (err)
87 return err;
88 if (comm) {
89 err = db_export__comm_thread(dbe, comm, thread);
90 if (err)
91 return err;
92 }
93 }
94 main_thread_db_id = main_thread->db_id;
95 }
96
97 if (dbe->export_thread)
98 return dbe->export_thread(dbe, thread, main_thread_db_id,
99 machine);
100
101 return 0;
102}
103
104int db_export__comm(struct db_export *dbe, struct comm *comm,
105 struct thread *main_thread)
106{
107 int err;
108
109 if (comm->db_id)
110 return 0;
111
112 comm->db_id = ++dbe->comm_last_db_id;
113
114 if (dbe->export_comm) {
115 err = dbe->export_comm(dbe, comm);
116 if (err)
117 return err;
118 }
119
120 return db_export__comm_thread(dbe, comm, main_thread);
121}
122
123int db_export__comm_thread(struct db_export *dbe, struct comm *comm,
124 struct thread *thread)
125{
126 u64 db_id;
127
128 db_id = ++dbe->comm_thread_last_db_id;
129
130 if (dbe->export_comm_thread)
131 return dbe->export_comm_thread(dbe, db_id, comm, thread);
132
133 return 0;
134}
135
136int db_export__dso(struct db_export *dbe, struct dso *dso,
137 struct machine *machine)
138{
139 if (dso->db_id)
140 return 0;
141
142 dso->db_id = ++dbe->dso_last_db_id;
143
144 if (dbe->export_dso)
145 return dbe->export_dso(dbe, dso, machine);
146
147 return 0;
148}
149
150int db_export__symbol(struct db_export *dbe, struct symbol *sym,
151 struct dso *dso)
152{
153 u64 *sym_db_id = symbol__priv(sym);
154
155 if (*sym_db_id)
156 return 0;
157
158 *sym_db_id = ++dbe->symbol_last_db_id;
159
160 if (dbe->export_symbol)
161 return dbe->export_symbol(dbe, sym, dso);
162
163 return 0;
164}
165
166static struct thread *get_main_thread(struct machine *machine, struct thread *thread)
167{
168 if (thread->pid_ == thread->tid)
169 return thread;
170
171 if (thread->pid_ == -1)
172 return NULL;
173
174 return machine__find_thread(machine, thread->pid_, thread->pid_);
175}
176
177static int db_ids_from_al(struct db_export *dbe, struct addr_location *al,
178 u64 *dso_db_id, u64 *sym_db_id, u64 *offset)
179{
180 int err;
181
182 if (al->map) {
183 struct dso *dso = al->map->dso;
184
185 err = db_export__dso(dbe, dso, al->machine);
186 if (err)
187 return err;
188 *dso_db_id = dso->db_id;
189
190 if (!al->sym) {
191 al->sym = symbol__new(al->addr, 0, 0, "unknown");
192 if (al->sym)
193 symbols__insert(&dso->symbols[al->map->type],
194 al->sym);
195 }
196
197 if (al->sym) {
198 u64 *db_id = symbol__priv(al->sym);
199
200 err = db_export__symbol(dbe, al->sym, dso);
201 if (err)
202 return err;
203 *sym_db_id = *db_id;
204 *offset = al->addr - al->sym->start;
205 }
206 }
207
208 return 0;
209}
210
211int db_export__sample(struct db_export *dbe, union perf_event *event,
212 struct perf_sample *sample, struct perf_evsel *evsel,
213 struct thread *thread, struct addr_location *al)
214{
215 struct export_sample es = {
216 .event = event,
217 .sample = sample,
218 .evsel = evsel,
219 .thread = thread,
220 .al = al,
221 };
222 struct thread *main_thread;
223 struct comm *comm = NULL;
224 int err;
225
226 err = db_export__evsel(dbe, evsel);
227 if (err)
228 return err;
229
230 err = db_export__machine(dbe, al->machine);
231 if (err)
232 return err;
233
234 main_thread = get_main_thread(al->machine, thread);
235 if (main_thread)
236 comm = machine__thread_exec_comm(al->machine, main_thread);
237
238 err = db_export__thread(dbe, thread, al->machine, comm);
239 if (err)
240 return err;
241
242 if (comm) {
243 err = db_export__comm(dbe, comm, main_thread);
244 if (err)
245 return err;
246 es.comm_db_id = comm->db_id;
247 }
248
249 es.db_id = ++dbe->sample_last_db_id;
250
251 err = db_ids_from_al(dbe, al, &es.dso_db_id, &es.sym_db_id, &es.offset);
252 if (err)
253 return err;
254
255 if ((evsel->attr.sample_type & PERF_SAMPLE_ADDR) &&
256 sample_addr_correlates_sym(&evsel->attr)) {
257 struct addr_location addr_al;
258
259 perf_event__preprocess_sample_addr(event, sample, thread, &addr_al);
260 err = db_ids_from_al(dbe, &addr_al, &es.addr_dso_db_id,
261 &es.addr_sym_db_id, &es.addr_offset);
262 if (err)
263 return err;
264 }
265
266 if (dbe->export_sample)
267 return dbe->export_sample(dbe, &es);
268
269 return 0;
270}