doc/man: remove lttng.1 (built from lttng.1.txt)
[lttng-tools.git] / src / bin / lttng / commands / add_context.c
CommitLineData
d65106b1
DG
1/*
2 * Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
e9492550 3 * Copyright (C) 2016 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
d65106b1 4 *
d14d33bf
AM
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License, version 2 only,
7 * as published by the Free Software Foundation.
d65106b1
DG
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
d14d33bf
AM
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
d65106b1
DG
17 */
18
6c1c0768 19#define _LGPL_SOURCE
90b9a268 20#include <ctype.h>
d65106b1
DG
21#include <popt.h>
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25#include <sys/stat.h>
26#include <sys/types.h>
27#include <unistd.h>
3ecec76a 28#include <assert.h>
d65106b1 29
3301e740
DG
30#include <urcu/list.h>
31
89b72577
JRJ
32#include <common/mi-lttng.h>
33
c399183f 34#include "../command.h"
d65106b1 35
b13d56d7
MD
36#define PRINT_LINE_LEN 80
37
d65106b1 38static char *opt_channel_name;
5440dc42 39static char *opt_session_name;
55cc08a6 40static int opt_kernel;
d65106b1 41static int opt_userspace;
e9492550
JG
42static int opt_jul;
43static int opt_log4j;
d78d6610 44static char *opt_type;
89b72577 45
d65106b1
DG
46enum {
47 OPT_HELP = 1,
48 OPT_TYPE,
eeac7d46 49 OPT_USERSPACE,
e9492550
JG
50 OPT_JUL,
51 OPT_LOG4J,
679b4943 52 OPT_LIST_OPTIONS,
d65106b1
DG
53};
54
cd80958d 55static struct lttng_handle *handle;
89b72577 56static struct mi_writer *writer;
cd80958d 57
90b9a268
DG
58/*
59 * Taken from the LTTng ABI
60 */
61enum context_type {
62 CONTEXT_PID = 0,
aa3514e9 63 CONTEXT_PERF_COUNTER = 1, /* Backward compat. */
95da1297 64 CONTEXT_PROCNAME = 2,
90b9a268
DG
65 CONTEXT_PRIO = 3,
66 CONTEXT_NICE = 4,
67 CONTEXT_VPID = 5,
68 CONTEXT_TID = 6,
69 CONTEXT_VTID = 7,
70 CONTEXT_PPID = 8,
71 CONTEXT_VPPID = 9,
9197c5c4 72 CONTEXT_PTHREAD_ID = 10,
54773d68 73 CONTEXT_HOSTNAME = 11,
7c612c2e 74 CONTEXT_IP = 12,
aa3514e9
MD
75 CONTEXT_PERF_CPU_COUNTER = 13,
76 CONTEXT_PERF_THREAD_COUNTER = 14,
e9492550 77 CONTEXT_APP_CONTEXT = 15,
1ae5e83e
JD
78 CONTEXT_INTERRUPTIBLE = 16,
79 CONTEXT_PREEMPTIBLE = 17,
80 CONTEXT_NEED_RESCHEDULE = 18,
81 CONTEXT_MIGRATABLE = 19,
3301e740
DG
82};
83
90b9a268
DG
84/*
85 * Taken from the Perf ABI (all enum perf_*)
86 */
87enum perf_type {
88 PERF_TYPE_HARDWARE = 0,
89 PERF_TYPE_SOFTWARE = 1,
b13d56d7 90 PERF_TYPE_HW_CACHE = 3,
3301e740
DG
91};
92
90b9a268 93enum perf_count_hard {
b13d56d7
MD
94 PERF_COUNT_HW_CPU_CYCLES = 0,
95 PERF_COUNT_HW_INSTRUCTIONS = 1,
96 PERF_COUNT_HW_CACHE_REFERENCES = 2,
97 PERF_COUNT_HW_CACHE_MISSES = 3,
98 PERF_COUNT_HW_BRANCH_INSTRUCTIONS = 4,
99 PERF_COUNT_HW_BRANCH_MISSES = 5,
100 PERF_COUNT_HW_BUS_CYCLES = 6,
101 PERF_COUNT_HW_STALLED_CYCLES_FRONTEND = 7,
102 PERF_COUNT_HW_STALLED_CYCLES_BACKEND = 8,
90b9a268
DG
103};
104
105enum perf_count_soft {
106 PERF_COUNT_SW_CPU_CLOCK = 0,
107 PERF_COUNT_SW_TASK_CLOCK = 1,
108 PERF_COUNT_SW_PAGE_FAULTS = 2,
109 PERF_COUNT_SW_CONTEXT_SWITCHES = 3,
110 PERF_COUNT_SW_CPU_MIGRATIONS = 4,
111 PERF_COUNT_SW_PAGE_FAULTS_MIN = 5,
112 PERF_COUNT_SW_PAGE_FAULTS_MAJ = 6,
113 PERF_COUNT_SW_ALIGNMENT_FAULTS = 7,
114 PERF_COUNT_SW_EMULATION_FAULTS = 8,
3301e740
DG
115};
116
b13d56d7
MD
117/*
118 * Generalized hardware cache events:
119 *
120 * { L1-D, L1-I, LLC, ITLB, DTLB, BPU } x
121 * { read, write, prefetch } x
122 * { accesses, misses }
123 */
124enum perf_hw_cache_id {
125 PERF_COUNT_HW_CACHE_L1D = 0,
126 PERF_COUNT_HW_CACHE_L1I = 1,
127 PERF_COUNT_HW_CACHE_LL = 2,
128 PERF_COUNT_HW_CACHE_DTLB = 3,
129 PERF_COUNT_HW_CACHE_ITLB = 4,
130 PERF_COUNT_HW_CACHE_BPU = 5,
131
132 PERF_COUNT_HW_CACHE_MAX, /* non-ABI */
133};
134
135enum perf_hw_cache_op_id {
136 PERF_COUNT_HW_CACHE_OP_READ = 0,
137 PERF_COUNT_HW_CACHE_OP_WRITE = 1,
138 PERF_COUNT_HW_CACHE_OP_PREFETCH = 2,
139
140 PERF_COUNT_HW_CACHE_OP_MAX, /* non-ABI */
141};
142
143enum perf_hw_cache_op_result_id {
144 PERF_COUNT_HW_CACHE_RESULT_ACCESS = 0,
145 PERF_COUNT_HW_CACHE_RESULT_MISS = 1,
146
147 PERF_COUNT_HW_CACHE_RESULT_MAX, /* non-ABI */
148};
149
d65106b1
DG
150static struct poptOption long_options[] = {
151 /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
152 {"help", 'h', POPT_ARG_NONE, 0, OPT_HELP, 0, 0},
5440dc42 153 {"session", 's', POPT_ARG_STRING, &opt_session_name, 0, 0, 0},
d65106b1 154 {"channel", 'c', POPT_ARG_STRING, &opt_channel_name, 0, 0, 0},
d65106b1 155 {"kernel", 'k', POPT_ARG_VAL, &opt_kernel, 1, 0, 0},
d78d6610 156 {"userspace", 'u', POPT_ARG_NONE, 0, OPT_USERSPACE, 0, 0},
e9492550
JG
157 {"jul", 'j', POPT_ARG_NONE, 0, OPT_JUL, 0, 0},
158 {"log4j", 'l', POPT_ARG_NONE, 0, OPT_LOG4J, 0, 0},
6caa2bcc 159 {"type", 't', POPT_ARG_STRING, &opt_type, OPT_TYPE, 0, 0},
679b4943 160 {"list-options", 0, POPT_ARG_NONE, NULL, OPT_LIST_OPTIONS, NULL, NULL},
d65106b1
DG
161 {0, 0, 0, 0, 0, 0, 0}
162};
163
90b9a268 164/*
b13d56d7 165 * Context options
90b9a268 166 */
aa3514e9 167#define PERF_HW(optstr, name, type, hide) \
b13d56d7 168 { \
aa3514e9 169 optstr, type, hide, \
b13d56d7
MD
170 .u.perf = { PERF_TYPE_HARDWARE, PERF_COUNT_HW_##name, },\
171 }
90b9a268 172
aa3514e9 173#define PERF_SW(optstr, name, type, hide) \
b13d56d7 174 { \
aa3514e9 175 optstr, type, hide, \
b13d56d7
MD
176 .u.perf = { PERF_TYPE_SOFTWARE, PERF_COUNT_SW_##name, },\
177 }
90b9a268 178
aa3514e9 179#define _PERF_HW_CACHE(optstr, name, type, op, result, hide) \
b13d56d7 180 { \
aa3514e9 181 optstr, type, hide, \
b13d56d7
MD
182 .u.perf = { \
183 PERF_TYPE_HW_CACHE, \
184 (uint64_t) PERF_COUNT_HW_CACHE_##name \
18829107
MD
185 | ((uint64_t) PERF_COUNT_HW_CACHE_OP_##op << 8) \
186 | ((uint64_t) PERF_COUNT_HW_CACHE_RESULT_##result << 16), \
b13d56d7
MD
187 }, \
188 }
189
aa3514e9
MD
190#define PERF_HW_CACHE(optstr, name, type, hide) \
191 _PERF_HW_CACHE(optstr "-loads", name, type, \
192 READ, ACCESS, hide), \
193 _PERF_HW_CACHE(optstr "-load-misses", name, type, \
194 READ, MISS, hide), \
195 _PERF_HW_CACHE(optstr "-stores", name, type, \
196 WRITE, ACCESS, hide), \
197 _PERF_HW_CACHE(optstr "-store-misses", name, type, \
198 WRITE, MISS, hide), \
199 _PERF_HW_CACHE(optstr "-prefetches", name, type, \
200 PREFETCH, ACCESS, hide), \
201 _PERF_HW_CACHE(optstr "-prefetch-misses", name, type, \
202 PREFETCH, MISS, hide)
b13d56d7
MD
203
204static
205const struct ctx_opts {
90b9a268 206 char *symbol;
b13d56d7 207 enum context_type ctx_type;
aa3514e9 208 int hide_help; /* Hide from --help */
b13d56d7
MD
209 union {
210 struct {
211 uint32_t type;
212 uint64_t config;
213 } perf;
e9492550
JG
214 struct {
215 char *provider_name;
216 char *ctx_name;
217 } app_ctx;
b13d56d7
MD
218 } u;
219} ctx_opts[] = {
220 { "pid", CONTEXT_PID },
95da1297 221 { "procname", CONTEXT_PROCNAME },
b13d56d7
MD
222 { "prio", CONTEXT_PRIO },
223 { "nice", CONTEXT_NICE },
224 { "vpid", CONTEXT_VPID },
225 { "tid", CONTEXT_TID },
9197c5c4 226 { "pthread_id", CONTEXT_PTHREAD_ID },
b13d56d7
MD
227 { "vtid", CONTEXT_VTID },
228 { "ppid", CONTEXT_PPID },
229 { "vppid", CONTEXT_VPPID },
54773d68 230 { "hostname", CONTEXT_HOSTNAME },
7c612c2e 231 { "ip", CONTEXT_IP },
1ae5e83e
JD
232 { "interruptible", CONTEXT_INTERRUPTIBLE },
233 { "preemptible", CONTEXT_PREEMPTIBLE },
234 { "need_reschedule", CONTEXT_NEED_RESCHEDULE },
235 { "migratable", CONTEXT_MIGRATABLE },
aa3514e9 236
b13d56d7 237 /* Perf options */
aa3514e9
MD
238
239 /* Perf per-CPU counters */
240 PERF_HW("perf:cpu:cpu-cycles", CPU_CYCLES,
241 CONTEXT_PERF_CPU_COUNTER, 0),
242 PERF_HW("perf:cpu:cycles", CPU_CYCLES,
243 CONTEXT_PERF_CPU_COUNTER, 0),
244 PERF_HW("perf:cpu:stalled-cycles-frontend", STALLED_CYCLES_FRONTEND,
245 CONTEXT_PERF_CPU_COUNTER, 0),
246 PERF_HW("perf:cpu:idle-cycles-frontend", STALLED_CYCLES_FRONTEND,
247 CONTEXT_PERF_CPU_COUNTER, 0),
248 PERF_HW("perf:cpu:stalled-cycles-backend", STALLED_CYCLES_BACKEND,
249 CONTEXT_PERF_CPU_COUNTER, 0),
250 PERF_HW("perf:cpu:idle-cycles-backend", STALLED_CYCLES_BACKEND,
251 CONTEXT_PERF_CPU_COUNTER, 0),
252 PERF_HW("perf:cpu:instructions", INSTRUCTIONS,
253 CONTEXT_PERF_CPU_COUNTER, 0),
254 PERF_HW("perf:cpu:cache-references", CACHE_REFERENCES,
255 CONTEXT_PERF_CPU_COUNTER, 0),
256 PERF_HW("perf:cpu:cache-misses", CACHE_MISSES,
257 CONTEXT_PERF_CPU_COUNTER, 0),
258 PERF_HW("perf:cpu:branch-instructions", BRANCH_INSTRUCTIONS,
259 CONTEXT_PERF_CPU_COUNTER, 0),
260 PERF_HW("perf:cpu:branches", BRANCH_INSTRUCTIONS,
261 CONTEXT_PERF_CPU_COUNTER, 0),
262 PERF_HW("perf:cpu:branch-misses", BRANCH_MISSES,
263 CONTEXT_PERF_CPU_COUNTER, 0),
264 PERF_HW("perf:cpu:bus-cycles", BUS_CYCLES,
265 CONTEXT_PERF_CPU_COUNTER, 0),
266
267 PERF_HW_CACHE("perf:cpu:L1-dcache", L1D,
268 CONTEXT_PERF_CPU_COUNTER, 0),
269 PERF_HW_CACHE("perf:cpu:L1-icache", L1I,
270 CONTEXT_PERF_CPU_COUNTER, 0),
271 PERF_HW_CACHE("perf:cpu:LLC", LL,
272 CONTEXT_PERF_CPU_COUNTER, 0),
273 PERF_HW_CACHE("perf:cpu:dTLB", DTLB,
274 CONTEXT_PERF_CPU_COUNTER, 0),
275 _PERF_HW_CACHE("perf:cpu:iTLB-loads", ITLB,
276 CONTEXT_PERF_CPU_COUNTER, READ, ACCESS, 0),
277 _PERF_HW_CACHE("perf:cpu:iTLB-load-misses", ITLB,
278 CONTEXT_PERF_CPU_COUNTER, READ, MISS, 0),
279 _PERF_HW_CACHE("perf:cpu:branch-loads", BPU,
280 CONTEXT_PERF_CPU_COUNTER, READ, ACCESS, 0),
281 _PERF_HW_CACHE("perf:cpu:branch-load-misses", BPU,
282 CONTEXT_PERF_CPU_COUNTER, READ, MISS, 0),
283
284 PERF_SW("perf:cpu:cpu-clock", CPU_CLOCK,
285 CONTEXT_PERF_CPU_COUNTER, 0),
286 PERF_SW("perf:cpu:task-clock", TASK_CLOCK,
287 CONTEXT_PERF_CPU_COUNTER, 0),
288 PERF_SW("perf:cpu:page-fault", PAGE_FAULTS,
289 CONTEXT_PERF_CPU_COUNTER, 0),
290 PERF_SW("perf:cpu:faults", PAGE_FAULTS,
291 CONTEXT_PERF_CPU_COUNTER, 0),
292 PERF_SW("perf:cpu:major-faults", PAGE_FAULTS_MAJ,
293 CONTEXT_PERF_CPU_COUNTER, 0),
294 PERF_SW("perf:cpu:minor-faults", PAGE_FAULTS_MIN,
295 CONTEXT_PERF_CPU_COUNTER, 0),
296 PERF_SW("perf:cpu:context-switches", CONTEXT_SWITCHES,
297 CONTEXT_PERF_CPU_COUNTER, 0),
298 PERF_SW("perf:cpu:cs", CONTEXT_SWITCHES,
299 CONTEXT_PERF_CPU_COUNTER, 0),
300 PERF_SW("perf:cpu:cpu-migrations", CPU_MIGRATIONS,
301 CONTEXT_PERF_CPU_COUNTER, 0),
302 PERF_SW("perf:cpu:migrations", CPU_MIGRATIONS,
303 CONTEXT_PERF_CPU_COUNTER, 0),
304 PERF_SW("perf:cpu:alignment-faults", ALIGNMENT_FAULTS,
305 CONTEXT_PERF_CPU_COUNTER, 0),
306 PERF_SW("perf:cpu:emulation-faults", EMULATION_FAULTS,
307 CONTEXT_PERF_CPU_COUNTER, 0),
308
309 /* Perf per-thread counters */
310 PERF_HW("perf:thread:cpu-cycles", CPU_CYCLES,
311 CONTEXT_PERF_THREAD_COUNTER, 0),
312 PERF_HW("perf:thread:cycles", CPU_CYCLES,
313 CONTEXT_PERF_THREAD_COUNTER, 0),
314 PERF_HW("perf:thread:stalled-cycles-frontend", STALLED_CYCLES_FRONTEND,
315 CONTEXT_PERF_THREAD_COUNTER, 0),
316 PERF_HW("perf:thread:idle-cycles-frontend", STALLED_CYCLES_FRONTEND,
317 CONTEXT_PERF_THREAD_COUNTER, 0),
318 PERF_HW("perf:thread:stalled-cycles-backend", STALLED_CYCLES_BACKEND,
319 CONTEXT_PERF_THREAD_COUNTER, 0),
320 PERF_HW("perf:thread:idle-cycles-backend", STALLED_CYCLES_BACKEND,
321 CONTEXT_PERF_THREAD_COUNTER, 0),
322 PERF_HW("perf:thread:instructions", INSTRUCTIONS,
323 CONTEXT_PERF_THREAD_COUNTER, 0),
324 PERF_HW("perf:thread:cache-references", CACHE_REFERENCES,
325 CONTEXT_PERF_THREAD_COUNTER, 0),
326 PERF_HW("perf:thread:cache-misses", CACHE_MISSES,
327 CONTEXT_PERF_THREAD_COUNTER, 0),
328 PERF_HW("perf:thread:branch-instructions", BRANCH_INSTRUCTIONS,
329 CONTEXT_PERF_THREAD_COUNTER, 0),
330 PERF_HW("perf:thread:branches", BRANCH_INSTRUCTIONS,
331 CONTEXT_PERF_THREAD_COUNTER, 0),
332 PERF_HW("perf:thread:branch-misses", BRANCH_MISSES,
333 CONTEXT_PERF_THREAD_COUNTER, 0),
334 PERF_HW("perf:thread:bus-cycles", BUS_CYCLES,
335 CONTEXT_PERF_THREAD_COUNTER, 0),
336
337 PERF_HW_CACHE("perf:thread:L1-dcache", L1D,
338 CONTEXT_PERF_THREAD_COUNTER, 0),
339 PERF_HW_CACHE("perf:thread:L1-icache", L1I,
340 CONTEXT_PERF_THREAD_COUNTER, 0),
341 PERF_HW_CACHE("perf:thread:LLC", LL,
342 CONTEXT_PERF_THREAD_COUNTER, 0),
343 PERF_HW_CACHE("perf:thread:dTLB", DTLB,
344 CONTEXT_PERF_THREAD_COUNTER, 0),
345 _PERF_HW_CACHE("perf:thread:iTLB-loads", ITLB,
346 CONTEXT_PERF_THREAD_COUNTER, READ, ACCESS, 0),
347 _PERF_HW_CACHE("perf:thread:iTLB-load-misses", ITLB,
348 CONTEXT_PERF_THREAD_COUNTER, READ, MISS, 0),
349 _PERF_HW_CACHE("perf:thread:branch-loads", BPU,
350 CONTEXT_PERF_THREAD_COUNTER, READ, ACCESS, 0),
351 _PERF_HW_CACHE("perf:thread:branch-load-misses", BPU,
352 CONTEXT_PERF_THREAD_COUNTER, READ, MISS, 0),
353
354 PERF_SW("perf:thread:cpu-clock", CPU_CLOCK,
355 CONTEXT_PERF_THREAD_COUNTER, 0),
356 PERF_SW("perf:thread:task-clock", TASK_CLOCK,
357 CONTEXT_PERF_THREAD_COUNTER, 0),
358 PERF_SW("perf:thread:page-fault", PAGE_FAULTS,
359 CONTEXT_PERF_THREAD_COUNTER, 0),
360 PERF_SW("perf:thread:faults", PAGE_FAULTS,
361 CONTEXT_PERF_THREAD_COUNTER, 0),
362 PERF_SW("perf:thread:major-faults", PAGE_FAULTS_MAJ,
363 CONTEXT_PERF_THREAD_COUNTER, 0),
364 PERF_SW("perf:thread:minor-faults", PAGE_FAULTS_MIN,
365 CONTEXT_PERF_THREAD_COUNTER, 0),
366 PERF_SW("perf:thread:context-switches", CONTEXT_SWITCHES,
367 CONTEXT_PERF_THREAD_COUNTER, 0),
368 PERF_SW("perf:thread:cs", CONTEXT_SWITCHES,
369 CONTEXT_PERF_THREAD_COUNTER, 0),
370 PERF_SW("perf:thread:cpu-migrations", CPU_MIGRATIONS,
371 CONTEXT_PERF_THREAD_COUNTER, 0),
372 PERF_SW("perf:thread:migrations", CPU_MIGRATIONS,
373 CONTEXT_PERF_THREAD_COUNTER, 0),
374 PERF_SW("perf:thread:alignment-faults", ALIGNMENT_FAULTS,
375 CONTEXT_PERF_THREAD_COUNTER, 0),
376 PERF_SW("perf:thread:emulation-faults", EMULATION_FAULTS,
377 CONTEXT_PERF_THREAD_COUNTER, 0),
378
379 /*
380 * Perf per-CPU counters, backward compatibilty for names.
381 * Hidden from help listing.
382 */
383 PERF_HW("perf:cpu-cycles", CPU_CYCLES,
384 CONTEXT_PERF_COUNTER, 1),
385 PERF_HW("perf:cycles", CPU_CYCLES,
386 CONTEXT_PERF_COUNTER, 1),
387 PERF_HW("perf:stalled-cycles-frontend", STALLED_CYCLES_FRONTEND,
388 CONTEXT_PERF_COUNTER, 1),
389 PERF_HW("perf:idle-cycles-frontend", STALLED_CYCLES_FRONTEND,
390 CONTEXT_PERF_COUNTER, 1),
391 PERF_HW("perf:stalled-cycles-backend", STALLED_CYCLES_BACKEND,
392 CONTEXT_PERF_COUNTER, 1),
393 PERF_HW("perf:idle-cycles-backend", STALLED_CYCLES_BACKEND,
394 CONTEXT_PERF_COUNTER, 1),
395 PERF_HW("perf:instructions", INSTRUCTIONS,
396 CONTEXT_PERF_COUNTER, 1),
397 PERF_HW("perf:cache-references", CACHE_REFERENCES,
398 CONTEXT_PERF_COUNTER, 1),
399 PERF_HW("perf:cache-misses", CACHE_MISSES,
400 CONTEXT_PERF_COUNTER, 1),
401 PERF_HW("perf:branch-instructions", BRANCH_INSTRUCTIONS,
402 CONTEXT_PERF_COUNTER, 1),
403 PERF_HW("perf:branches", BRANCH_INSTRUCTIONS,
404 CONTEXT_PERF_COUNTER, 1),
405 PERF_HW("perf:branch-misses", BRANCH_MISSES,
406 CONTEXT_PERF_COUNTER, 1),
407 PERF_HW("perf:bus-cycles", BUS_CYCLES,
408 CONTEXT_PERF_COUNTER, 1),
409
410 PERF_HW_CACHE("perf:L1-dcache", L1D,
411 CONTEXT_PERF_COUNTER, 1),
412 PERF_HW_CACHE("perf:L1-icache", L1I,
413 CONTEXT_PERF_COUNTER, 1),
414 PERF_HW_CACHE("perf:LLC", LL,
415 CONTEXT_PERF_COUNTER, 1),
416 PERF_HW_CACHE("perf:dTLB", DTLB,
417 CONTEXT_PERF_COUNTER, 1),
418 _PERF_HW_CACHE("perf:iTLB-loads", ITLB,
419 CONTEXT_PERF_COUNTER, READ, ACCESS, 1),
420 _PERF_HW_CACHE("perf:iTLB-load-misses", ITLB,
421 CONTEXT_PERF_COUNTER, READ, MISS, 1),
422 _PERF_HW_CACHE("perf:branch-loads", BPU,
423 CONTEXT_PERF_COUNTER, READ, ACCESS, 1),
424 _PERF_HW_CACHE("perf:branch-load-misses", BPU,
425 CONTEXT_PERF_COUNTER, READ, MISS, 1),
426
427 PERF_SW("perf:cpu-clock", CPU_CLOCK,
428 CONTEXT_PERF_COUNTER, 1),
429 PERF_SW("perf:task-clock", TASK_CLOCK,
430 CONTEXT_PERF_COUNTER, 1),
431 PERF_SW("perf:page-fault", PAGE_FAULTS,
432 CONTEXT_PERF_COUNTER, 1),
433 PERF_SW("perf:faults", PAGE_FAULTS,
434 CONTEXT_PERF_COUNTER, 1),
435 PERF_SW("perf:major-faults", PAGE_FAULTS_MAJ,
436 CONTEXT_PERF_COUNTER, 1),
437 PERF_SW("perf:minor-faults", PAGE_FAULTS_MIN,
438 CONTEXT_PERF_COUNTER, 1),
439 PERF_SW("perf:context-switches", CONTEXT_SWITCHES,
440 CONTEXT_PERF_COUNTER, 1),
441 PERF_SW("perf:cs", CONTEXT_SWITCHES,
442 CONTEXT_PERF_COUNTER, 1),
443 PERF_SW("perf:cpu-migrations", CPU_MIGRATIONS,
444 CONTEXT_PERF_COUNTER, 1),
445 PERF_SW("perf:migrations", CPU_MIGRATIONS,
446 CONTEXT_PERF_COUNTER, 1),
447 PERF_SW("perf:alignment-faults", ALIGNMENT_FAULTS,
448 CONTEXT_PERF_COUNTER, 1),
449 PERF_SW("perf:emulation-faults", EMULATION_FAULTS,
450 CONTEXT_PERF_COUNTER, 1),
451
b13d56d7 452 { NULL, -1 }, /* Closure */
90b9a268
DG
453};
454
aa3514e9
MD
455#undef PERF_HW_CACHE
456#undef _PERF_HW_CACHE
b13d56d7
MD
457#undef PERF_SW
458#undef PERF_HW
459
90b9a268 460/*
b13d56d7 461 * Context type for command line option parsing.
90b9a268 462 */
b13d56d7 463struct ctx_type {
e9492550 464 struct ctx_opts *opt;
b13d56d7 465 struct cds_list_head list;
90b9a268
DG
466};
467
468/*
469 * List of context type. Use to enable multiple context on a single command
470 * line entry.
471 */
472struct ctx_type_list {
473 struct cds_list_head head;
474} ctx_type_list = {
475 .head = CDS_LIST_HEAD_INIT(ctx_type_list.head),
476};
477
90b9a268
DG
478/*
479 * Pretty print context type.
480 */
481static void print_ctx_type(FILE *ofp)
482{
b13d56d7
MD
483 const char *indent = " ";
484 int indent_len = strlen(indent);
485 int len, i = 0;
90b9a268 486
76e3c5dd 487 fprintf(ofp, "%s", indent);
b13d56d7 488 len = indent_len;
90b9a268 489 while (ctx_opts[i].symbol != NULL) {
aa3514e9
MD
490 if (!ctx_opts[i].hide_help) {
491 if (len > indent_len) {
492 if (len + strlen(ctx_opts[i].symbol) + 2
493 >= PRINT_LINE_LEN) {
494 fprintf(ofp, ",\n");
495 fprintf(ofp, "%s", indent);
496 len = indent_len;
497 } else {
498 len += fprintf(ofp, ", ");
499 }
90b9a268 500 }
aa3514e9 501 len += fprintf(ofp, "%s", ctx_opts[i].symbol);
90b9a268
DG
502 }
503 i++;
504 }
90b9a268
DG
505}
506
d65106b1
DG
507/*
508 * usage
509 */
510static void usage(FILE *ofp)
511{
32a6298d 512 fprintf(ofp, "usage: lttng add-context -t TYPE [-k|-u] [OPTIONS]\n");
d65106b1 513 fprintf(ofp, "\n");
601d5acf
DG
514 fprintf(ofp, "If no channel is given (-c), the context is added to\n");
515 fprintf(ofp, "all channels.\n");
32a6298d 516 fprintf(ofp, "\n");
601d5acf 517 fprintf(ofp, "Otherwise the context is added only to the channel (-c).\n");
32a6298d
DG
518 fprintf(ofp, "\n");
519 fprintf(ofp, "Exactly one domain (-k or -u) must be specified.\n");
3301e740 520 fprintf(ofp, "\n");
d65106b1
DG
521 fprintf(ofp, "Options:\n");
522 fprintf(ofp, " -h, --help Show this help\n");
679b4943 523 fprintf(ofp, " --list-options Simple listing of options\n");
5eb00805
TD
524 fprintf(ofp, " -s, --session NAME Apply to session name\n");
525 fprintf(ofp, " -c, --channel NAME Apply to channel\n");
af87c45a 526 fprintf(ofp, " -k, --kernel Apply to the kernel tracer\n");
af87c45a 527 fprintf(ofp, " -u, --userspace Apply to the user-space tracer\n");
e9492550
JG
528 fprintf(ofp, " -j, --jul Apply to Java application using JUL\n");
529 fprintf(ofp, " -l, --log4j Apply for Java application using LOG4j\n");
32a6298d
DG
530 fprintf(ofp, "\n");
531 fprintf(ofp, "Context:\n");
b13d56d7 532 fprintf(ofp, " -t, --type TYPE Context type. You can repeat that option on\n");
af87c45a
DG
533 fprintf(ofp, " the command line to specify multiple contexts at once.\n");
534 fprintf(ofp, " (--kernel preempts --userspace)\n");
b13d56d7 535 fprintf(ofp, " TYPE can be one of the strings below:\n");
90b9a268 536 print_ctx_type(ofp);
d65106b1 537 fprintf(ofp, "\n");
c455d428
FD
538 fprintf(ofp, "Note that the vpid, vppid and vtid context types represent the virtual process id,\n"
539 "virtual parent process id and virtual thread id as seen from the current execution context\n"
540 "as opposed to the pid, ppid and tid which are kernel internal data structures.\n\n");
90b9a268 541 fprintf(ofp, "Example:\n");
aa3514e9
MD
542 fprintf(ofp, "This command will add the context information 'prio' and two per-cpu\n"
543 "perf counters (hardware branch misses and cache misses), to all channels\n"
b13d56d7 544 "in the trace data output:\n");
aa3514e9 545 fprintf(ofp, "# lttng add-context -k -t prio -t perf:cpu:branch-misses -t perf:cpu:cache-misses\n");
d65106b1
DG
546 fprintf(ofp, "\n");
547}
548
90b9a268
DG
549/*
550 * Find context numerical value from string.
e9492550
JG
551 *
552 * Return -1 if not found.
90b9a268
DG
553 */
554static int find_ctx_type_idx(const char *opt)
555{
e9492550 556 int ret, i = 0;
90b9a268
DG
557
558 while (ctx_opts[i].symbol != NULL) {
559 if (strcmp(opt, ctx_opts[i].symbol) == 0) {
560 ret = i;
561 goto end;
562 }
563 i++;
564 }
565
e9492550 566 ret = -1;
90b9a268
DG
567end:
568 return ret;
569}
570
e9492550
JG
571static
572enum lttng_domain_type get_domain(void)
573{
574 if (opt_kernel) {
575 return LTTNG_DOMAIN_KERNEL;
576 } else if (opt_userspace) {
577 return LTTNG_DOMAIN_UST;
578 } else if (opt_jul) {
579 return LTTNG_DOMAIN_JUL;
580 } else if (opt_log4j) {
581 return LTTNG_DOMAIN_LOG4J;
582 } else {
583 assert(0);
584 }
585}
586
90b9a268
DG
587/*
588 * Add context to channel or event.
d65106b1 589 */
cd80958d 590static int add_context(char *session_name)
d65106b1 591{
89b72577 592 int ret = CMD_SUCCESS, warn = 0, success = 0;
7d29a247
DG
593 struct lttng_event_context context;
594 struct lttng_domain dom;
3301e740 595 struct ctx_type *type;
b13d56d7 596 char *ptr;
d65106b1 597
441c16a7
MD
598 memset(&context, 0, sizeof(context));
599 memset(&dom, 0, sizeof(dom));
600
e9492550 601 dom.type = get_domain();
cd80958d
DG
602 handle = lttng_create_handle(session_name, &dom);
603 if (handle == NULL) {
af87c45a 604 ret = CMD_ERROR;
cd80958d
DG
605 goto error;
606 }
607
89b72577
JRJ
608 if (lttng_opt_mi) {
609 /* Open a contexts element */
610 ret = mi_lttng_writer_open_element(writer, config_element_contexts);
611 if (ret) {
612 goto error;
613 }
614 }
615
5eb00805 616 /* Iterate over all the context types given */
3301e740 617 cds_list_for_each_entry(type, &ctx_type_list.head, list) {
6775595e 618 context.ctx = (enum lttng_event_context_type) type->opt->ctx_type;
aa3514e9
MD
619 switch (context.ctx) {
620 case LTTNG_EVENT_CONTEXT_PERF_COUNTER:
621 case LTTNG_EVENT_CONTEXT_PERF_CPU_COUNTER:
622 case LTTNG_EVENT_CONTEXT_PERF_THREAD_COUNTER:
b13d56d7
MD
623 context.u.perf_counter.type = type->opt->u.perf.type;
624 context.u.perf_counter.config = type->opt->u.perf.config;
24546386
MD
625 strncpy(context.u.perf_counter.name, type->opt->symbol,
626 LTTNG_SYMBOL_NAME_LEN);
627 context.u.perf_counter.name[LTTNG_SYMBOL_NAME_LEN - 1] = '\0';
b13d56d7
MD
628 /* Replace : and - by _ */
629 while ((ptr = strchr(context.u.perf_counter.name, '-')) != NULL) {
630 *ptr = '_';
3301e740 631 }
b13d56d7
MD
632 while ((ptr = strchr(context.u.perf_counter.name, ':')) != NULL) {
633 *ptr = '_';
3301e740 634 }
aa3514e9 635 break;
e9492550
JG
636 case LTTNG_EVENT_CONTEXT_APP_CONTEXT:
637 context.u.app_ctx.provider_name =
638 type->opt->u.app_ctx.provider_name;
639 context.u.app_ctx.ctx_name =
640 type->opt->u.app_ctx.ctx_name;
641 break;
aa3514e9
MD
642 default:
643 break;
3301e740 644 }
55cc08a6
DG
645 DBG("Adding context...");
646
89b72577
JRJ
647 if (lttng_opt_mi) {
648 /* We leave context open the update the success of the command */
649 ret = mi_lttng_context(writer, &context, 1);
650 if (ret) {
651 ret = CMD_ERROR;
652 goto error;
653 }
654 }
655
601d5acf 656 ret = lttng_add_context(handle, &context, NULL, opt_channel_name);
55cc08a6 657 if (ret < 0) {
b58471ff 658 ERR("%s: %s", type->opt->symbol, lttng_strerror(ret));
d16c1a4c 659 warn = 1;
89b72577 660 success = 0;
d65106b1 661 } else {
601d5acf 662 if (opt_channel_name) {
b58471ff
DG
663 MSG("%s context %s added to channel %s",
664 opt_kernel ? "kernel" : "UST", type->opt->symbol,
665 opt_channel_name);
b58471ff
DG
666 } else {
667 MSG("%s context %s added to all channels",
668 opt_kernel ? "kernel" : "UST", type->opt->symbol)
669 }
89b72577
JRJ
670 success = 1;
671 }
672
673 if (lttng_opt_mi) {
674 /* Is the single operation a success ? */
675 ret = mi_lttng_writer_write_element_bool(writer,
676 mi_lttng_element_success, success);
677 if (ret) {
678 ret = CMD_ERROR;
679 goto error;
680 }
681
682 /* Close the context element */
683 ret = mi_lttng_writer_close_element(writer);
684 if (ret) {
685 ret = CMD_ERROR;
686 goto error;
687 }
688 }
689 }
690
691 if (lttng_opt_mi) {
692 /* Close contexts element */
693 ret = mi_lttng_writer_close_element(writer);
694 if (ret) {
695 goto error;
d65106b1 696 }
d65106b1
DG
697 }
698
af87c45a
DG
699 ret = CMD_SUCCESS;
700
d65106b1 701error:
cd80958d
DG
702 lttng_destroy_handle(handle);
703
d16c1a4c
DG
704 /*
705 * This means that at least one add_context failed and tells the user to
706 * look on stderr for error(s).
707 */
89b72577 708 if (!ret && warn) {
d16c1a4c
DG
709 ret = CMD_WARNING;
710 }
d65106b1
DG
711 return ret;
712}
713
e9492550
JG
714static
715void destroy_ctx_type(struct ctx_type *type)
716{
717 if (!type) {
718 return;
719 }
720 free(type->opt->symbol);
721 free(type->opt);
722 free(type);
723}
724
725static
726struct ctx_type *create_ctx_type(void)
727{
728 struct ctx_type *type = zmalloc(sizeof(*type));
729
730 if (!type) {
731 PERROR("malloc ctx_type");
732 goto end;
733 }
734
735 type->opt = zmalloc(sizeof(*type->opt));
736 if (!type->opt) {
737 PERROR("malloc ctx_type options");
738 destroy_ctx_type(type);
8e32b63b 739 type = NULL;
e9492550
JG
740 goto end;
741 }
742end:
743 return type;
744}
745
746static
747struct ctx_type *get_context_type(const char *ctx)
748{
749 int opt_index;
750 struct ctx_type *type = NULL;
751 const char app_ctx_prefix[] = "$app.";
752 char *provider_name = NULL, *ctx_name = NULL;
753 size_t i, len, colon_pos = 0, provider_name_len, ctx_name_len;
754
755 if (!ctx) {
756 goto not_found;
757 }
758
759 type = create_ctx_type();
760 if (!type) {
761 goto not_found;
762 }
763
764 /* Check if ctx matches a known static context. */
765 opt_index = find_ctx_type_idx(ctx);
766 if (opt_index >= 0) {
767 *type->opt = ctx_opts[opt_index];
768 type->opt->symbol = strdup(ctx_opts[opt_index].symbol);
769 goto found;
770 }
771
772 /*
773 * No match found against static contexts; check if it is an app
774 * context.
775 */
776 len = strlen(ctx);
777 if (len <= sizeof(app_ctx_prefix) - 1) {
778 goto not_found;
779 }
780
781 /* String starts with $app. */
782 if (strncmp(ctx, app_ctx_prefix, sizeof(app_ctx_prefix) - 1)) {
783 goto not_found;
784 }
785
786 /* Validate that the ':' separator is present. */
787 for (i = sizeof(app_ctx_prefix); i < len; i++) {
788 const char c = ctx[i];
789
790 if (c == ':') {
791 colon_pos = i;
792 break;
793 }
794 }
795
796 /*
797 * No colon found or no ctx name ("$app.provider:") or no provider name
798 * given ("$app.:..."), which is invalid.
799 */
800 if (!colon_pos || colon_pos == len ||
801 colon_pos == sizeof(app_ctx_prefix)) {
802 ERR("Invalid application context provided: no provider or context name provided.");
803 goto not_found;
804 }
805
806 provider_name_len = colon_pos - sizeof(app_ctx_prefix) + 2;
807 provider_name = zmalloc(provider_name_len);
808 if (!provider_name) {
809 PERROR("malloc provider_name");
810 goto not_found;
811 }
812 strncpy(provider_name, ctx + sizeof(app_ctx_prefix) - 1,
813 provider_name_len - 1);
814 type->opt->u.app_ctx.provider_name = provider_name;
815
816 ctx_name_len = len - colon_pos;
817 ctx_name = zmalloc(ctx_name_len);
818 if (!ctx_name) {
819 PERROR("malloc ctx_name");
820 goto not_found;
821 }
822 strncpy(ctx_name, ctx + colon_pos + 1, ctx_name_len - 1);
823 type->opt->u.app_ctx.ctx_name = ctx_name;
824 type->opt->ctx_type = CONTEXT_APP_CONTEXT;
825 type->opt->symbol = strdup(ctx);
826found:
827 return type;
828not_found:
829 free(provider_name);
830 free(ctx_name);
831 destroy_ctx_type(type);
832 return NULL;
833}
834
d65106b1 835/*
5eb00805 836 * Add context to channel or event.
d65106b1
DG
837 */
838int cmd_add_context(int argc, const char **argv)
839{
e9492550 840 int opt, ret = CMD_SUCCESS, command_ret = CMD_SUCCESS;
89b72577 841 int success = 1;
d65106b1 842 static poptContext pc;
b13d56d7 843 struct ctx_type *type, *tmptype;
cd80958d 844 char *session_name = NULL;
d65106b1 845
636167b6
DG
846 if (argc < 2) {
847 usage(stderr);
5eb00805 848 ret = CMD_ERROR;
636167b6
DG
849 goto end;
850 }
851
d65106b1
DG
852 pc = poptGetContext(NULL, argc, argv, long_options, 0);
853 poptReadDefaultConfig(pc, 0);
854
855 while ((opt = poptGetNextOpt(pc)) != -1) {
856 switch (opt) {
857 case OPT_HELP:
5eb00805 858 usage(stdout);
d65106b1
DG
859 goto end;
860 case OPT_TYPE:
e9492550
JG
861 {
862 type = get_context_type(opt_type);
863 if (!type) {
6caa2bcc 864 ERR("Unknown context type %s", opt_type);
5eb00805
TD
865 ret = CMD_FATAL;
866 goto end;
867 }
e9492550 868 cds_list_add_tail(&type->list, &ctx_type_list.head);
d65106b1 869 break;
e9492550 870 }
eeac7d46
MD
871 case OPT_USERSPACE:
872 opt_userspace = 1;
eeac7d46 873 break;
e9492550
JG
874 case OPT_JUL:
875 opt_jul = 1;
876 break;
877 case OPT_LOG4J:
878 opt_log4j = 1;
879 break;
679b4943
SM
880 case OPT_LIST_OPTIONS:
881 list_cmd_options(stdout, long_options);
679b4943 882 goto end;
d65106b1
DG
883 default:
884 usage(stderr);
885 ret = CMD_UNDEFINED;
886 goto end;
887 }
888 }
889
e9492550
JG
890 ret = print_missing_or_multiple_domains(opt_kernel + opt_userspace +
891 opt_jul + opt_log4j);
3ecec76a
PP
892 if (ret) {
893 ret = CMD_ERROR;
894 goto end;
895 }
896
ae856491
DG
897 if (!opt_type) {
898 ERR("Missing mandatory -t TYPE");
899 usage(stderr);
900 ret = CMD_ERROR;
901 goto end;
902 }
903
cd80958d
DG
904 if (!opt_session_name) {
905 session_name = get_session_name();
906 if (session_name == NULL) {
5eb00805 907 ret = CMD_ERROR;
cd80958d
DG
908 goto end;
909 }
910 } else {
911 session_name = opt_session_name;
912 }
913
89b72577
JRJ
914 /* Mi check */
915 if (lttng_opt_mi) {
916 writer = mi_lttng_writer_create(fileno(stdout), lttng_opt_mi);
917 if (!writer) {
918 ret = -LTTNG_ERR_NOMEM;
919 goto end;
920 }
921
922 /* Open command element */
923 ret = mi_lttng_writer_command_open(writer,
924 mi_lttng_element_command_add_context);
925 if (ret) {
926 ret = CMD_ERROR;
927 goto end;
928 }
929
930 /* Open output element */
931 ret = mi_lttng_writer_open_element(writer,
932 mi_lttng_element_command_output);
933 if (ret) {
934 ret = CMD_ERROR;
935 goto end;
936 }
937 }
938
939 command_ret = add_context(session_name);
940 if (command_ret) {
941 success = 0;
942 }
943
944 /* Mi closing */
945 if (lttng_opt_mi) {
946 /* Close output element */
947 ret = mi_lttng_writer_close_element(writer);
948 if (ret) {
949 ret = CMD_ERROR;
950 goto end;
951 }
3301e740 952
89b72577
JRJ
953 /* Success ? */
954 ret = mi_lttng_writer_write_element_bool(writer,
955 mi_lttng_element_command_success, success);
956 if (ret) {
957 ret = CMD_ERROR;
958 goto end;
959 }
960
961 /* Command element close */
962 ret = mi_lttng_writer_command_close(writer);
963 if (ret) {
964 ret = CMD_ERROR;
965 goto end;
966 }
967 }
968
969end:
1256f150
DT
970 if (!opt_session_name) {
971 free(session_name);
972 }
973
89b72577
JRJ
974 /* Mi clean-up */
975 if (writer && mi_lttng_writer_destroy(writer)) {
976 /* Preserve original error code */
977 ret = ret ? ret : LTTNG_ERR_MI_IO_FAIL;
978 }
979
3301e740 980 /* Cleanup allocated memory */
b13d56d7 981 cds_list_for_each_entry_safe(type, tmptype, &ctx_type_list.head, list) {
e9492550 982 destroy_ctx_type(type);
3301e740
DG
983 }
984
89b72577
JRJ
985 /* Overwrite ret if an error occurred during add_context() */
986 ret = command_ret ? command_ret : ret;
987
ca1c3607 988 poptFreeContext(pc);
d65106b1
DG
989 return ret;
990}
This page took 0.100659 seconds and 5 git commands to generate.