Fix: Add vpid, vppid and vtid info in add-context help
[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 34static char *opt_channel_name;
5440dc42 35static char *opt_session_name;
55cc08a6 36static int opt_kernel;
d65106b1 37static int opt_userspace;
d78d6610
DG
38static char *opt_type;
39#if 0
40/* Not implemented yet */
eeac7d46 41static char *opt_cmd_name;
d65106b1 42static pid_t opt_pid;
d78d6610 43#endif
d65106b1
DG
44
45enum {
46 OPT_HELP = 1,
47 OPT_TYPE,
eeac7d46 48 OPT_USERSPACE,
679b4943 49 OPT_LIST_OPTIONS,
d65106b1
DG
50};
51
cd80958d
DG
52static struct lttng_handle *handle;
53
90b9a268
DG
54/*
55 * Taken from the LTTng ABI
56 */
57enum context_type {
58 CONTEXT_PID = 0,
59 CONTEXT_PERF_COUNTER = 1,
95da1297 60 CONTEXT_PROCNAME = 2,
90b9a268
DG
61 CONTEXT_PRIO = 3,
62 CONTEXT_NICE = 4,
63 CONTEXT_VPID = 5,
64 CONTEXT_TID = 6,
65 CONTEXT_VTID = 7,
66 CONTEXT_PPID = 8,
67 CONTEXT_VPPID = 9,
9197c5c4 68 CONTEXT_PTHREAD_ID = 10,
54773d68 69 CONTEXT_HOSTNAME = 11,
7c612c2e 70 CONTEXT_IP = 12,
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 143 {"channel", 'c', POPT_ARG_STRING, &opt_channel_name, 0, 0, 0},
d65106b1 144 {"kernel", 'k', POPT_ARG_VAL, &opt_kernel, 1, 0, 0},
d78d6610 145 {"userspace", 'u', POPT_ARG_NONE, 0, OPT_USERSPACE, 0, 0},
6caa2bcc 146 {"type", 't', POPT_ARG_STRING, &opt_type, OPT_TYPE, 0, 0},
679b4943 147 {"list-options", 0, POPT_ARG_NONE, NULL, OPT_LIST_OPTIONS, NULL, NULL},
d65106b1
DG
148 {0, 0, 0, 0, 0, 0, 0}
149};
150
90b9a268 151/*
b13d56d7 152 * Context options
90b9a268 153 */
b13d56d7
MD
154#define PERF_HW(opt, name) \
155 { \
156 "perf:" #opt, CONTEXT_PERF_COUNTER, \
157 .u.perf = { PERF_TYPE_HARDWARE, PERF_COUNT_HW_##name, },\
158 }
90b9a268 159
b13d56d7
MD
160#define PERF_SW(opt, name) \
161 { \
162 "perf:" #opt, CONTEXT_PERF_COUNTER, \
163 .u.perf = { PERF_TYPE_SOFTWARE, PERF_COUNT_SW_##name, },\
164 }
90b9a268 165
b13d56d7
MD
166#define _PERF_HW_CACHE(optstr, name, op, result) \
167 { \
168 "perf:" optstr, CONTEXT_PERF_COUNTER, \
169 .u.perf = { \
170 PERF_TYPE_HW_CACHE, \
171 (uint64_t) PERF_COUNT_HW_CACHE_##name \
18829107
MD
172 | ((uint64_t) PERF_COUNT_HW_CACHE_OP_##op << 8) \
173 | ((uint64_t) PERF_COUNT_HW_CACHE_RESULT_##result << 16), \
b13d56d7
MD
174 }, \
175 }
176
177#define PERF_HW_CACHE(opt, name) \
178 _PERF_HW_CACHE(#opt "-loads", name, READ, ACCESS), \
179 _PERF_HW_CACHE(#opt "-load-misses", name, READ, MISS), \
180 _PERF_HW_CACHE(#opt "-stores", name, WRITE, ACCESS), \
181 _PERF_HW_CACHE(#opt "-store-misses", name, WRITE, MISS), \
182 _PERF_HW_CACHE(#opt "-prefetches", name, PREFETCH, ACCESS), \
183 _PERF_HW_CACHE(#opt "-prefetch-misses", name, PREFETCH, MISS) \
184
185static
186const struct ctx_opts {
90b9a268 187 char *symbol;
b13d56d7
MD
188 enum context_type ctx_type;
189 union {
190 struct {
191 uint32_t type;
192 uint64_t config;
193 } perf;
194 } u;
195} ctx_opts[] = {
196 { "pid", CONTEXT_PID },
95da1297 197 { "procname", CONTEXT_PROCNAME },
b13d56d7
MD
198 { "prio", CONTEXT_PRIO },
199 { "nice", CONTEXT_NICE },
200 { "vpid", CONTEXT_VPID },
201 { "tid", CONTEXT_TID },
9197c5c4 202 { "pthread_id", CONTEXT_PTHREAD_ID },
b13d56d7
MD
203 { "vtid", CONTEXT_VTID },
204 { "ppid", CONTEXT_PPID },
205 { "vppid", CONTEXT_VPPID },
54773d68 206 { "hostname", CONTEXT_HOSTNAME },
7c612c2e 207 { "ip", CONTEXT_IP },
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");
601d5acf
DG
303 fprintf(ofp, "If no channel is given (-c), the context is added to\n");
304 fprintf(ofp, "all channels.\n");
32a6298d 305 fprintf(ofp, "\n");
601d5acf 306 fprintf(ofp, "Otherwise the context is added only to the channel (-c).\n");
32a6298d
DG
307 fprintf(ofp, "\n");
308 fprintf(ofp, "Exactly one domain (-k or -u) must be specified.\n");
3301e740 309 fprintf(ofp, "\n");
d65106b1
DG
310 fprintf(ofp, "Options:\n");
311 fprintf(ofp, " -h, --help Show this help\n");
679b4943 312 fprintf(ofp, " --list-options Simple listing of options\n");
5eb00805
TD
313 fprintf(ofp, " -s, --session NAME Apply to session name\n");
314 fprintf(ofp, " -c, --channel NAME Apply to channel\n");
af87c45a 315 fprintf(ofp, " -k, --kernel Apply to the kernel tracer\n");
af87c45a 316 fprintf(ofp, " -u, --userspace Apply to the user-space tracer\n");
32a6298d
DG
317 fprintf(ofp, "\n");
318 fprintf(ofp, "Context:\n");
b13d56d7 319 fprintf(ofp, " -t, --type TYPE Context type. You can repeat that option on\n");
af87c45a
DG
320 fprintf(ofp, " the command line to specify multiple contexts at once.\n");
321 fprintf(ofp, " (--kernel preempts --userspace)\n");
b13d56d7 322 fprintf(ofp, " TYPE can be one of the strings below:\n");
90b9a268 323 print_ctx_type(ofp);
d65106b1 324 fprintf(ofp, "\n");
83a1318f
FD
325 fprintf(ofp, "Note that the vpid, vppid and vtid context types represent the virtual process id,\n"
326 "virtual parent process id and virtual thread id as seen from the current execution context\n"
327 "as opposed to the pid, ppid and tid which are kernel internal data structures.\n\n");
90b9a268 328 fprintf(ofp, "Example:\n");
b13d56d7 329 fprintf(ofp, "This command will add the context information 'prio' and two perf\n"
601d5acf 330 "counters (hardware branch misses and cache misses), to all channels\n"
b13d56d7
MD
331 "in the trace data output:\n");
332 fprintf(ofp, "# lttng add-context -k -t prio -t perf:branch-misses -t perf:cache-misses\n");
d65106b1
DG
333 fprintf(ofp, "\n");
334}
335
90b9a268
DG
336/*
337 * Find context numerical value from string.
338 */
339static int find_ctx_type_idx(const char *opt)
340{
341 int ret = -1, i = 0;
342
343 while (ctx_opts[i].symbol != NULL) {
344 if (strcmp(opt, ctx_opts[i].symbol) == 0) {
345 ret = i;
346 goto end;
347 }
348 i++;
349 }
350
351end:
352 return ret;
353}
354
90b9a268
DG
355/*
356 * Add context to channel or event.
d65106b1 357 */
cd80958d 358static int add_context(char *session_name)
d65106b1 359{
d16c1a4c 360 int ret = CMD_SUCCESS, warn = 0;
7d29a247
DG
361 struct lttng_event_context context;
362 struct lttng_domain dom;
3301e740 363 struct ctx_type *type;
b13d56d7 364 char *ptr;
d65106b1 365
441c16a7
MD
366 memset(&context, 0, sizeof(context));
367 memset(&dom, 0, sizeof(dom));
368
cd80958d
DG
369 if (opt_kernel) {
370 dom.type = LTTNG_DOMAIN_KERNEL;
d78d6610 371 } else if (opt_userspace) {
55cc08a6 372 dom.type = LTTNG_DOMAIN_UST;
55cc08a6 373 } else {
e14f64a8 374 ERR("Please specify a tracer (-k/--kernel or -u/--userspace)");
d16c1a4c 375 ret = CMD_ERROR;
55cc08a6 376 goto error;
cd80958d
DG
377 }
378
379 handle = lttng_create_handle(session_name, &dom);
380 if (handle == NULL) {
af87c45a 381 ret = CMD_ERROR;
cd80958d
DG
382 goto error;
383 }
384
5eb00805 385 /* Iterate over all the context types given */
3301e740 386 cds_list_for_each_entry(type, &ctx_type_list.head, list) {
6775595e 387 context.ctx = (enum lttng_event_context_type) type->opt->ctx_type;
b13d56d7
MD
388 if (context.ctx == LTTNG_EVENT_CONTEXT_PERF_COUNTER) {
389 context.u.perf_counter.type = type->opt->u.perf.type;
390 context.u.perf_counter.config = type->opt->u.perf.config;
24546386
MD
391 strncpy(context.u.perf_counter.name, type->opt->symbol,
392 LTTNG_SYMBOL_NAME_LEN);
393 context.u.perf_counter.name[LTTNG_SYMBOL_NAME_LEN - 1] = '\0';
b13d56d7
MD
394 /* Replace : and - by _ */
395 while ((ptr = strchr(context.u.perf_counter.name, '-')) != NULL) {
396 *ptr = '_';
3301e740 397 }
b13d56d7
MD
398 while ((ptr = strchr(context.u.perf_counter.name, ':')) != NULL) {
399 *ptr = '_';
3301e740 400 }
3301e740 401 }
55cc08a6
DG
402 DBG("Adding context...");
403
601d5acf 404 ret = lttng_add_context(handle, &context, NULL, opt_channel_name);
55cc08a6 405 if (ret < 0) {
b58471ff 406 ERR("%s: %s", type->opt->symbol, lttng_strerror(ret));
d16c1a4c 407 warn = 1;
55cc08a6 408 continue;
d65106b1 409 } else {
601d5acf 410 if (opt_channel_name) {
b58471ff
DG
411 MSG("%s context %s added to channel %s",
412 opt_kernel ? "kernel" : "UST", type->opt->symbol,
413 opt_channel_name);
b58471ff
DG
414 } else {
415 MSG("%s context %s added to all channels",
416 opt_kernel ? "kernel" : "UST", type->opt->symbol)
417 }
d65106b1 418 }
d65106b1
DG
419 }
420
af87c45a
DG
421 ret = CMD_SUCCESS;
422
d65106b1 423error:
cd80958d
DG
424 lttng_destroy_handle(handle);
425
d16c1a4c
DG
426 /*
427 * This means that at least one add_context failed and tells the user to
428 * look on stderr for error(s).
429 */
430 if (warn) {
431 ret = CMD_WARNING;
432 }
d65106b1
DG
433 return ret;
434}
435
436/*
5eb00805 437 * Add context to channel or event.
d65106b1
DG
438 */
439int cmd_add_context(int argc, const char **argv)
440{
90b9a268 441 int index, opt, ret = CMD_SUCCESS;
d65106b1 442 static poptContext pc;
b13d56d7 443 struct ctx_type *type, *tmptype;
cd80958d 444 char *session_name = NULL;
d65106b1 445
636167b6
DG
446 if (argc < 2) {
447 usage(stderr);
5eb00805 448 ret = CMD_ERROR;
636167b6
DG
449 goto end;
450 }
451
d65106b1
DG
452 pc = poptGetContext(NULL, argc, argv, long_options, 0);
453 poptReadDefaultConfig(pc, 0);
454
455 while ((opt = poptGetNextOpt(pc)) != -1) {
456 switch (opt) {
457 case OPT_HELP:
5eb00805 458 usage(stdout);
d65106b1
DG
459 goto end;
460 case OPT_TYPE:
af87c45a
DG
461 /*
462 * Look up the index of opt_type in ctx_opts[] first, so we don't
463 * have to free(type) on failure.
464 */
6caa2bcc 465 index = find_ctx_type_idx(opt_type);
b13d56d7 466 if (index < 0) {
6caa2bcc 467 ERR("Unknown context type %s", opt_type);
5eb00805 468 ret = CMD_ERROR;
b13d56d7 469 goto end;
90b9a268 470 }
5eb00805
TD
471
472 type = malloc(sizeof(struct ctx_type));
473 if (type == NULL) {
474 perror("malloc ctx_type");
475 ret = CMD_FATAL;
476 goto end;
477 }
478
b13d56d7 479 type->opt = &ctx_opts[index];
222e461a 480 if (type->opt->symbol == NULL) {
6caa2bcc 481 ERR("Unknown context type %s", opt_type);
5eb00805
TD
482 free(type);
483 ret = CMD_ERROR;
484 goto end;
90b9a268 485 } else {
31746f93 486 cds_list_add_tail(&type->list, &ctx_type_list.head);
90b9a268 487 }
d65106b1 488 break;
eeac7d46
MD
489 case OPT_USERSPACE:
490 opt_userspace = 1;
d78d6610 491#if 0
eeac7d46 492 opt_cmd_name = poptGetOptArg(pc);
d78d6610 493#endif
eeac7d46 494 break;
679b4943
SM
495 case OPT_LIST_OPTIONS:
496 list_cmd_options(stdout, long_options);
679b4943 497 goto end;
d65106b1
DG
498 default:
499 usage(stderr);
500 ret = CMD_UNDEFINED;
501 goto end;
502 }
503 }
504
ae856491
DG
505 if (!opt_type) {
506 ERR("Missing mandatory -t TYPE");
507 usage(stderr);
508 ret = CMD_ERROR;
509 goto end;
510 }
511
cd80958d
DG
512 if (!opt_session_name) {
513 session_name = get_session_name();
514 if (session_name == NULL) {
5eb00805 515 ret = CMD_ERROR;
cd80958d
DG
516 goto end;
517 }
518 } else {
519 session_name = opt_session_name;
520 }
521
522 ret = add_context(session_name);
3301e740 523
1256f150
DT
524 if (!opt_session_name) {
525 free(session_name);
526 }
527
5eb00805 528end:
3301e740 529 /* Cleanup allocated memory */
b13d56d7 530 cds_list_for_each_entry_safe(type, tmptype, &ctx_type_list.head, list) {
3301e740
DG
531 free(type);
532 }
533
ca1c3607 534 poptFreeContext(pc);
d65106b1
DG
535 return ret;
536}
This page took 0.058363 seconds and 4 git commands to generate.