Add UST overlap tests
[lttng-tools.git] / src / bin / lttng / commands / add_context.c
CommitLineData
d65106b1
DG
1/*
2 * Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
3 *
d14d33bf
AM
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License, version 2 only,
6 * as published by the Free Software Foundation.
d65106b1
DG
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
d14d33bf
AM
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
d65106b1
DG
16 */
17
18#define _GNU_SOURCE
90b9a268 19#include <ctype.h>
d65106b1
DG
20#include <popt.h>
21#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
24#include <sys/stat.h>
25#include <sys/types.h>
26#include <unistd.h>
27
3301e740
DG
28#include <urcu/list.h>
29
c399183f 30#include "../command.h"
d65106b1 31
b13d56d7
MD
32#define PRINT_LINE_LEN 80
33
d65106b1
DG
34static char *opt_event_name;
35static char *opt_channel_name;
5440dc42 36static char *opt_session_name;
55cc08a6 37static int opt_kernel;
d65106b1 38static int opt_userspace;
d78d6610
DG
39static char *opt_type;
40#if 0
41/* Not implemented yet */
eeac7d46 42static char *opt_cmd_name;
d65106b1 43static pid_t opt_pid;
d78d6610 44#endif
d65106b1
DG
45
46enum {
47 OPT_HELP = 1,
48 OPT_TYPE,
eeac7d46 49 OPT_USERSPACE,
679b4943 50 OPT_LIST_OPTIONS,
d65106b1
DG
51};
52
cd80958d
DG
53static struct lttng_handle *handle;
54
90b9a268
DG
55/*
56 * Taken from the LTTng ABI
57 */
58enum context_type {
59 CONTEXT_PID = 0,
60 CONTEXT_PERF_COUNTER = 1,
95da1297 61 CONTEXT_PROCNAME = 2,
90b9a268
DG
62 CONTEXT_PRIO = 3,
63 CONTEXT_NICE = 4,
64 CONTEXT_VPID = 5,
65 CONTEXT_TID = 6,
66 CONTEXT_VTID = 7,
67 CONTEXT_PPID = 8,
68 CONTEXT_VPPID = 9,
9197c5c4 69 CONTEXT_PTHREAD_ID = 10,
54773d68 70 CONTEXT_HOSTNAME = 11,
3301e740
DG
71};
72
90b9a268
DG
73/*
74 * Taken from the Perf ABI (all enum perf_*)
75 */
76enum perf_type {
77 PERF_TYPE_HARDWARE = 0,
78 PERF_TYPE_SOFTWARE = 1,
b13d56d7 79 PERF_TYPE_HW_CACHE = 3,
3301e740
DG
80};
81
90b9a268 82enum perf_count_hard {
b13d56d7
MD
83 PERF_COUNT_HW_CPU_CYCLES = 0,
84 PERF_COUNT_HW_INSTRUCTIONS = 1,
85 PERF_COUNT_HW_CACHE_REFERENCES = 2,
86 PERF_COUNT_HW_CACHE_MISSES = 3,
87 PERF_COUNT_HW_BRANCH_INSTRUCTIONS = 4,
88 PERF_COUNT_HW_BRANCH_MISSES = 5,
89 PERF_COUNT_HW_BUS_CYCLES = 6,
90 PERF_COUNT_HW_STALLED_CYCLES_FRONTEND = 7,
91 PERF_COUNT_HW_STALLED_CYCLES_BACKEND = 8,
90b9a268
DG
92};
93
94enum perf_count_soft {
95 PERF_COUNT_SW_CPU_CLOCK = 0,
96 PERF_COUNT_SW_TASK_CLOCK = 1,
97 PERF_COUNT_SW_PAGE_FAULTS = 2,
98 PERF_COUNT_SW_CONTEXT_SWITCHES = 3,
99 PERF_COUNT_SW_CPU_MIGRATIONS = 4,
100 PERF_COUNT_SW_PAGE_FAULTS_MIN = 5,
101 PERF_COUNT_SW_PAGE_FAULTS_MAJ = 6,
102 PERF_COUNT_SW_ALIGNMENT_FAULTS = 7,
103 PERF_COUNT_SW_EMULATION_FAULTS = 8,
3301e740
DG
104};
105
b13d56d7
MD
106/*
107 * Generalized hardware cache events:
108 *
109 * { L1-D, L1-I, LLC, ITLB, DTLB, BPU } x
110 * { read, write, prefetch } x
111 * { accesses, misses }
112 */
113enum perf_hw_cache_id {
114 PERF_COUNT_HW_CACHE_L1D = 0,
115 PERF_COUNT_HW_CACHE_L1I = 1,
116 PERF_COUNT_HW_CACHE_LL = 2,
117 PERF_COUNT_HW_CACHE_DTLB = 3,
118 PERF_COUNT_HW_CACHE_ITLB = 4,
119 PERF_COUNT_HW_CACHE_BPU = 5,
120
121 PERF_COUNT_HW_CACHE_MAX, /* non-ABI */
122};
123
124enum perf_hw_cache_op_id {
125 PERF_COUNT_HW_CACHE_OP_READ = 0,
126 PERF_COUNT_HW_CACHE_OP_WRITE = 1,
127 PERF_COUNT_HW_CACHE_OP_PREFETCH = 2,
128
129 PERF_COUNT_HW_CACHE_OP_MAX, /* non-ABI */
130};
131
132enum perf_hw_cache_op_result_id {
133 PERF_COUNT_HW_CACHE_RESULT_ACCESS = 0,
134 PERF_COUNT_HW_CACHE_RESULT_MISS = 1,
135
136 PERF_COUNT_HW_CACHE_RESULT_MAX, /* non-ABI */
137};
138
d65106b1
DG
139static struct poptOption long_options[] = {
140 /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
141 {"help", 'h', POPT_ARG_NONE, 0, OPT_HELP, 0, 0},
5440dc42 142 {"session", 's', POPT_ARG_STRING, &opt_session_name, 0, 0, 0},
d65106b1
DG
143 {"channel", 'c', POPT_ARG_STRING, &opt_channel_name, 0, 0, 0},
144 {"event", 'e', POPT_ARG_STRING, &opt_event_name, 0, 0, 0},
145 {"kernel", 'k', POPT_ARG_VAL, &opt_kernel, 1, 0, 0},
d78d6610 146 {"userspace", 'u', POPT_ARG_NONE, 0, OPT_USERSPACE, 0, 0},
6caa2bcc 147 {"type", 't', POPT_ARG_STRING, &opt_type, OPT_TYPE, 0, 0},
679b4943 148 {"list-options", 0, POPT_ARG_NONE, NULL, OPT_LIST_OPTIONS, NULL, NULL},
d65106b1
DG
149 {0, 0, 0, 0, 0, 0, 0}
150};
151
90b9a268 152/*
b13d56d7 153 * Context options
90b9a268 154 */
b13d56d7
MD
155#define PERF_HW(opt, name) \
156 { \
157 "perf:" #opt, CONTEXT_PERF_COUNTER, \
158 .u.perf = { PERF_TYPE_HARDWARE, PERF_COUNT_HW_##name, },\
159 }
90b9a268 160
b13d56d7
MD
161#define PERF_SW(opt, name) \
162 { \
163 "perf:" #opt, CONTEXT_PERF_COUNTER, \
164 .u.perf = { PERF_TYPE_SOFTWARE, PERF_COUNT_SW_##name, },\
165 }
90b9a268 166
b13d56d7
MD
167#define _PERF_HW_CACHE(optstr, name, op, result) \
168 { \
169 "perf:" optstr, CONTEXT_PERF_COUNTER, \
170 .u.perf = { \
171 PERF_TYPE_HW_CACHE, \
172 (uint64_t) PERF_COUNT_HW_CACHE_##name \
18829107
MD
173 | ((uint64_t) PERF_COUNT_HW_CACHE_OP_##op << 8) \
174 | ((uint64_t) PERF_COUNT_HW_CACHE_RESULT_##result << 16), \
b13d56d7
MD
175 }, \
176 }
177
178#define PERF_HW_CACHE(opt, name) \
179 _PERF_HW_CACHE(#opt "-loads", name, READ, ACCESS), \
180 _PERF_HW_CACHE(#opt "-load-misses", name, READ, MISS), \
181 _PERF_HW_CACHE(#opt "-stores", name, WRITE, ACCESS), \
182 _PERF_HW_CACHE(#opt "-store-misses", name, WRITE, MISS), \
183 _PERF_HW_CACHE(#opt "-prefetches", name, PREFETCH, ACCESS), \
184 _PERF_HW_CACHE(#opt "-prefetch-misses", name, PREFETCH, MISS) \
185
186static
187const struct ctx_opts {
90b9a268 188 char *symbol;
b13d56d7
MD
189 enum context_type ctx_type;
190 union {
191 struct {
192 uint32_t type;
193 uint64_t config;
194 } perf;
195 } u;
196} ctx_opts[] = {
197 { "pid", CONTEXT_PID },
95da1297 198 { "procname", CONTEXT_PROCNAME },
b13d56d7
MD
199 { "prio", CONTEXT_PRIO },
200 { "nice", CONTEXT_NICE },
201 { "vpid", CONTEXT_VPID },
202 { "tid", CONTEXT_TID },
9197c5c4 203 { "pthread_id", CONTEXT_PTHREAD_ID },
b13d56d7
MD
204 { "vtid", CONTEXT_VTID },
205 { "ppid", CONTEXT_PPID },
206 { "vppid", CONTEXT_VPPID },
54773d68 207 { "hostname", CONTEXT_HOSTNAME },
b13d56d7
MD
208 /* Perf options */
209 PERF_HW(cpu-cycles, CPU_CYCLES),
210 PERF_HW(cycles, CPU_CYCLES),
211 PERF_HW(stalled-cycles-frontend, STALLED_CYCLES_FRONTEND),
212 PERF_HW(idle-cycles-frontend, STALLED_CYCLES_FRONTEND),
213 PERF_HW(stalled-cycles-backend, STALLED_CYCLES_BACKEND),
214 PERF_HW(idle-cycles-backend, STALLED_CYCLES_BACKEND),
215 PERF_HW(instructions, INSTRUCTIONS),
216 PERF_HW(cache-references, CACHE_REFERENCES),
217 PERF_HW(cache-misses, CACHE_MISSES),
218 PERF_HW(branch-instructions, BRANCH_INSTRUCTIONS),
219 PERF_HW(branches, BRANCH_INSTRUCTIONS),
220 PERF_HW(branch-misses, BRANCH_MISSES),
221 PERF_HW(bus-cycles, BUS_CYCLES),
222
223 PERF_HW_CACHE(L1-dcache, L1D),
224 PERF_HW_CACHE(L1-icache, L1I),
225 PERF_HW_CACHE(LLC, LL),
226 PERF_HW_CACHE(dTLB, DTLB),
227 _PERF_HW_CACHE("iTLB-loads", ITLB, READ, ACCESS),
228 _PERF_HW_CACHE("iTLB-load-misses", ITLB, READ, MISS),
229 _PERF_HW_CACHE("branch-loads", BPU, READ, ACCESS),
230 _PERF_HW_CACHE("branch-load-misses", BPU, READ, MISS),
231
232
233 PERF_SW(cpu-clock, CPU_CLOCK),
234 PERF_SW(task-clock, TASK_CLOCK),
235 PERF_SW(page-fault, PAGE_FAULTS),
236 PERF_SW(faults, PAGE_FAULTS),
237 PERF_SW(major-faults, PAGE_FAULTS_MAJ),
238 PERF_SW(minor-faults, PAGE_FAULTS_MIN),
239 PERF_SW(context-switches, CONTEXT_SWITCHES),
240 PERF_SW(cs, CONTEXT_SWITCHES),
241 PERF_SW(cpu-migrations, CPU_MIGRATIONS),
242 PERF_SW(migrations, CPU_MIGRATIONS),
243 PERF_SW(alignment-faults, ALIGNMENT_FAULTS),
244 PERF_SW(emulation-faults, EMULATION_FAULTS),
245 { NULL, -1 }, /* Closure */
90b9a268
DG
246};
247
b13d56d7
MD
248#undef PERF_SW
249#undef PERF_HW
250
90b9a268 251/*
b13d56d7 252 * Context type for command line option parsing.
90b9a268 253 */
b13d56d7
MD
254struct ctx_type {
255 const struct ctx_opts *opt;
256 struct cds_list_head list;
90b9a268
DG
257};
258
259/*
260 * List of context type. Use to enable multiple context on a single command
261 * line entry.
262 */
263struct ctx_type_list {
264 struct cds_list_head head;
265} ctx_type_list = {
266 .head = CDS_LIST_HEAD_INIT(ctx_type_list.head),
267};
268
90b9a268
DG
269/*
270 * Pretty print context type.
271 */
272static void print_ctx_type(FILE *ofp)
273{
b13d56d7
MD
274 const char *indent = " ";
275 int indent_len = strlen(indent);
276 int len, i = 0;
90b9a268 277
76e3c5dd 278 fprintf(ofp, "%s", indent);
b13d56d7 279 len = indent_len;
90b9a268 280 while (ctx_opts[i].symbol != NULL) {
b13d56d7
MD
281 if (len > indent_len) {
282 if (len + strlen(ctx_opts[i].symbol) + 2
283 >= PRINT_LINE_LEN) {
284 fprintf(ofp, ",\n");
76e3c5dd 285 fprintf(ofp, "%s", indent);
b13d56d7
MD
286 len = indent_len;
287 } else {
288 len += fprintf(ofp, ", ");
90b9a268
DG
289 }
290 }
b13d56d7 291 len += fprintf(ofp, "%s", ctx_opts[i].symbol);
90b9a268
DG
292 i++;
293 }
90b9a268
DG
294}
295
d65106b1
DG
296/*
297 * usage
298 */
299static void usage(FILE *ofp)
300{
32a6298d 301 fprintf(ofp, "usage: lttng add-context -t TYPE [-k|-u] [OPTIONS]\n");
d65106b1 302 fprintf(ofp, "\n");
b13d56d7 303 fprintf(ofp, "If no channel and no event is given (-c/-e), the context\n");
32a6298d
DG
304 fprintf(ofp, "is added to all events and all channels.\n");
305 fprintf(ofp, "\n");
306 fprintf(ofp, "Otherwise the context is added only to the channel (-c)\n");
af87c45a 307 fprintf(ofp, "and/or event (-e) indicated.\n");
32a6298d
DG
308 fprintf(ofp, "\n");
309 fprintf(ofp, "Exactly one domain (-k or -u) must be specified.\n");
3301e740 310 fprintf(ofp, "\n");
d65106b1
DG
311 fprintf(ofp, "Options:\n");
312 fprintf(ofp, " -h, --help Show this help\n");
679b4943 313 fprintf(ofp, " --list-options Simple listing of options\n");
5eb00805
TD
314 fprintf(ofp, " -s, --session NAME Apply to session name\n");
315 fprintf(ofp, " -c, --channel NAME Apply to channel\n");
316 fprintf(ofp, " -e, --event NAME Apply to event\n");
af87c45a 317 fprintf(ofp, " -k, --kernel Apply to the kernel tracer\n");
af87c45a 318 fprintf(ofp, " -u, --userspace Apply to the user-space tracer\n");
32a6298d
DG
319 fprintf(ofp, "\n");
320 fprintf(ofp, "Context:\n");
b13d56d7 321 fprintf(ofp, " -t, --type TYPE Context type. You can repeat that option on\n");
af87c45a
DG
322 fprintf(ofp, " the command line to specify multiple contexts at once.\n");
323 fprintf(ofp, " (--kernel preempts --userspace)\n");
b13d56d7 324 fprintf(ofp, " TYPE can be one of the strings below:\n");
90b9a268 325 print_ctx_type(ofp);
d65106b1 326 fprintf(ofp, "\n");
90b9a268 327 fprintf(ofp, "Example:\n");
b13d56d7 328 fprintf(ofp, "This command will add the context information 'prio' and two perf\n"
af87c45a 329 "counters (hardware branch misses and cache misses), to all events\n"
b13d56d7
MD
330 "in the trace data output:\n");
331 fprintf(ofp, "# lttng add-context -k -t prio -t perf:branch-misses -t perf:cache-misses\n");
d65106b1
DG
332 fprintf(ofp, "\n");
333}
334
90b9a268
DG
335/*
336 * Find context numerical value from string.
337 */
338static int find_ctx_type_idx(const char *opt)
339{
340 int ret = -1, i = 0;
341
342 while (ctx_opts[i].symbol != NULL) {
343 if (strcmp(opt, ctx_opts[i].symbol) == 0) {
344 ret = i;
345 goto end;
346 }
347 i++;
348 }
349
350end:
351 return ret;
352}
353
90b9a268
DG
354/*
355 * Add context to channel or event.
d65106b1 356 */
cd80958d 357static int add_context(char *session_name)
d65106b1 358{
d16c1a4c 359 int ret = CMD_SUCCESS, warn = 0;
7d29a247
DG
360 struct lttng_event_context context;
361 struct lttng_domain dom;
3301e740 362 struct ctx_type *type;
b13d56d7 363 char *ptr;
d65106b1 364
441c16a7
MD
365 memset(&context, 0, sizeof(context));
366 memset(&dom, 0, sizeof(dom));
367
cd80958d
DG
368 if (opt_kernel) {
369 dom.type = LTTNG_DOMAIN_KERNEL;
d78d6610 370 } else if (opt_userspace) {
55cc08a6 371 dom.type = LTTNG_DOMAIN_UST;
55cc08a6 372 } else {
e14f64a8 373 ERR("Please specify a tracer (-k/--kernel or -u/--userspace)");
d16c1a4c 374 ret = CMD_ERROR;
55cc08a6 375 goto error;
cd80958d
DG
376 }
377
378 handle = lttng_create_handle(session_name, &dom);
379 if (handle == NULL) {
af87c45a 380 ret = CMD_ERROR;
cd80958d
DG
381 goto error;
382 }
383
5eb00805 384 /* Iterate over all the context types given */
3301e740 385 cds_list_for_each_entry(type, &ctx_type_list.head, list) {
6775595e 386 context.ctx = (enum lttng_event_context_type) type->opt->ctx_type;
b13d56d7
MD
387 if (context.ctx == LTTNG_EVENT_CONTEXT_PERF_COUNTER) {
388 context.u.perf_counter.type = type->opt->u.perf.type;
389 context.u.perf_counter.config = type->opt->u.perf.config;
d7b91b3c 390 strcpy(context.u.perf_counter.name, type->opt->symbol);
b13d56d7
MD
391 /* Replace : and - by _ */
392 while ((ptr = strchr(context.u.perf_counter.name, '-')) != NULL) {
393 *ptr = '_';
3301e740 394 }
b13d56d7
MD
395 while ((ptr = strchr(context.u.perf_counter.name, ':')) != NULL) {
396 *ptr = '_';
3301e740 397 }
3301e740 398 }
55cc08a6
DG
399 DBG("Adding context...");
400
401 ret = lttng_add_context(handle, &context, opt_event_name,
402 opt_channel_name);
403 if (ret < 0) {
b58471ff 404 ERR("%s: %s", type->opt->symbol, lttng_strerror(ret));
d16c1a4c 405 warn = 1;
55cc08a6 406 continue;
d65106b1 407 } else {
b58471ff
DG
408 if (opt_channel_name && opt_event_name) {
409 MSG("%s context %s added to event %s channel %s",
410 opt_kernel ? "kernel" : "UST", type->opt->symbol,
411 opt_channel_name, opt_event_name);
412 } else if (opt_channel_name && !opt_event_name) {
413 MSG("%s context %s added to channel %s",
414 opt_kernel ? "kernel" : "UST", type->opt->symbol,
415 opt_channel_name);
416 } else if (!opt_channel_name && opt_event_name) {
417 MSG("%s context %s added to event %s",
418 opt_kernel ? "kernel" : "UST", type->opt->symbol,
419 opt_event_name);
420 } else {
421 MSG("%s context %s added to all channels",
422 opt_kernel ? "kernel" : "UST", type->opt->symbol)
423 }
d65106b1 424 }
d65106b1
DG
425 }
426
af87c45a
DG
427 ret = CMD_SUCCESS;
428
d65106b1 429error:
cd80958d
DG
430 lttng_destroy_handle(handle);
431
d16c1a4c
DG
432 /*
433 * This means that at least one add_context failed and tells the user to
434 * look on stderr for error(s).
435 */
436 if (warn) {
437 ret = CMD_WARNING;
438 }
d65106b1
DG
439 return ret;
440}
441
442/*
5eb00805 443 * Add context to channel or event.
d65106b1
DG
444 */
445int cmd_add_context(int argc, const char **argv)
446{
90b9a268 447 int index, opt, ret = CMD_SUCCESS;
d65106b1 448 static poptContext pc;
b13d56d7 449 struct ctx_type *type, *tmptype;
cd80958d 450 char *session_name = NULL;
d65106b1 451
636167b6
DG
452 if (argc < 2) {
453 usage(stderr);
5eb00805 454 ret = CMD_ERROR;
636167b6
DG
455 goto end;
456 }
457
d65106b1
DG
458 pc = poptGetContext(NULL, argc, argv, long_options, 0);
459 poptReadDefaultConfig(pc, 0);
460
461 while ((opt = poptGetNextOpt(pc)) != -1) {
462 switch (opt) {
463 case OPT_HELP:
5eb00805 464 usage(stdout);
d65106b1
DG
465 goto end;
466 case OPT_TYPE:
af87c45a
DG
467 /*
468 * Look up the index of opt_type in ctx_opts[] first, so we don't
469 * have to free(type) on failure.
470 */
6caa2bcc 471 index = find_ctx_type_idx(opt_type);
b13d56d7 472 if (index < 0) {
6caa2bcc 473 ERR("Unknown context type %s", opt_type);
5eb00805 474 ret = CMD_ERROR;
b13d56d7 475 goto end;
90b9a268 476 }
5eb00805
TD
477
478 type = malloc(sizeof(struct ctx_type));
479 if (type == NULL) {
480 perror("malloc ctx_type");
481 ret = CMD_FATAL;
482 goto end;
483 }
484
b13d56d7
MD
485 type->opt = &ctx_opts[index];
486 if (type->opt->ctx_type == -1) {
6caa2bcc 487 ERR("Unknown context type %s", opt_type);
5eb00805
TD
488 free(type);
489 ret = CMD_ERROR;
490 goto end;
90b9a268
DG
491 } else {
492 cds_list_add(&type->list, &ctx_type_list.head);
493 }
d65106b1 494 break;
eeac7d46
MD
495 case OPT_USERSPACE:
496 opt_userspace = 1;
d78d6610 497#if 0
eeac7d46 498 opt_cmd_name = poptGetOptArg(pc);
d78d6610 499#endif
eeac7d46 500 break;
679b4943
SM
501 case OPT_LIST_OPTIONS:
502 list_cmd_options(stdout, long_options);
679b4943 503 goto end;
d65106b1
DG
504 default:
505 usage(stderr);
506 ret = CMD_UNDEFINED;
507 goto end;
508 }
509 }
510
ae856491
DG
511 if (!opt_type) {
512 ERR("Missing mandatory -t TYPE");
513 usage(stderr);
514 ret = CMD_ERROR;
515 goto end;
516 }
517
cd80958d
DG
518 if (!opt_session_name) {
519 session_name = get_session_name();
520 if (session_name == NULL) {
5eb00805 521 ret = CMD_ERROR;
cd80958d
DG
522 goto end;
523 }
524 } else {
525 session_name = opt_session_name;
526 }
527
528 ret = add_context(session_name);
3301e740 529
1256f150
DT
530 if (!opt_session_name) {
531 free(session_name);
532 }
533
5eb00805 534end:
3301e740 535 /* Cleanup allocated memory */
b13d56d7 536 cds_list_for_each_entry_safe(type, tmptype, &ctx_type_list.head, list) {
3301e740
DG
537 free(type);
538 }
539
ca1c3607 540 poptFreeContext(pc);
d65106b1
DG
541 return ret;
542}
This page took 0.060735 seconds and 5 git commands to generate.