2 * Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
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.
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.
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.
25 #include <sys/types.h>
29 #include <urcu/list.h>
31 #include <common/mi-lttng.h>
33 #include "../command.h"
35 #define PRINT_LINE_LEN 80
37 static char *opt_channel_name
;
38 static char *opt_session_name
;
39 static int opt_kernel
;
40 static int opt_userspace
;
41 static char *opt_type
;
50 static struct lttng_handle
*handle
;
51 static struct mi_writer
*writer
;
54 * Taken from the LTTng ABI
58 CONTEXT_PERF_COUNTER
= 1, /* Backward compat. */
67 CONTEXT_PTHREAD_ID
= 10,
68 CONTEXT_HOSTNAME
= 11,
70 CONTEXT_PERF_CPU_COUNTER
= 13,
71 CONTEXT_PERF_THREAD_COUNTER
= 14,
75 * Taken from the Perf ABI (all enum perf_*)
78 PERF_TYPE_HARDWARE
= 0,
79 PERF_TYPE_SOFTWARE
= 1,
80 PERF_TYPE_HW_CACHE
= 3,
83 enum perf_count_hard
{
84 PERF_COUNT_HW_CPU_CYCLES
= 0,
85 PERF_COUNT_HW_INSTRUCTIONS
= 1,
86 PERF_COUNT_HW_CACHE_REFERENCES
= 2,
87 PERF_COUNT_HW_CACHE_MISSES
= 3,
88 PERF_COUNT_HW_BRANCH_INSTRUCTIONS
= 4,
89 PERF_COUNT_HW_BRANCH_MISSES
= 5,
90 PERF_COUNT_HW_BUS_CYCLES
= 6,
91 PERF_COUNT_HW_STALLED_CYCLES_FRONTEND
= 7,
92 PERF_COUNT_HW_STALLED_CYCLES_BACKEND
= 8,
95 enum perf_count_soft
{
96 PERF_COUNT_SW_CPU_CLOCK
= 0,
97 PERF_COUNT_SW_TASK_CLOCK
= 1,
98 PERF_COUNT_SW_PAGE_FAULTS
= 2,
99 PERF_COUNT_SW_CONTEXT_SWITCHES
= 3,
100 PERF_COUNT_SW_CPU_MIGRATIONS
= 4,
101 PERF_COUNT_SW_PAGE_FAULTS_MIN
= 5,
102 PERF_COUNT_SW_PAGE_FAULTS_MAJ
= 6,
103 PERF_COUNT_SW_ALIGNMENT_FAULTS
= 7,
104 PERF_COUNT_SW_EMULATION_FAULTS
= 8,
108 * Generalized hardware cache events:
110 * { L1-D, L1-I, LLC, ITLB, DTLB, BPU } x
111 * { read, write, prefetch } x
112 * { accesses, misses }
114 enum perf_hw_cache_id
{
115 PERF_COUNT_HW_CACHE_L1D
= 0,
116 PERF_COUNT_HW_CACHE_L1I
= 1,
117 PERF_COUNT_HW_CACHE_LL
= 2,
118 PERF_COUNT_HW_CACHE_DTLB
= 3,
119 PERF_COUNT_HW_CACHE_ITLB
= 4,
120 PERF_COUNT_HW_CACHE_BPU
= 5,
122 PERF_COUNT_HW_CACHE_MAX
, /* non-ABI */
125 enum perf_hw_cache_op_id
{
126 PERF_COUNT_HW_CACHE_OP_READ
= 0,
127 PERF_COUNT_HW_CACHE_OP_WRITE
= 1,
128 PERF_COUNT_HW_CACHE_OP_PREFETCH
= 2,
130 PERF_COUNT_HW_CACHE_OP_MAX
, /* non-ABI */
133 enum perf_hw_cache_op_result_id
{
134 PERF_COUNT_HW_CACHE_RESULT_ACCESS
= 0,
135 PERF_COUNT_HW_CACHE_RESULT_MISS
= 1,
137 PERF_COUNT_HW_CACHE_RESULT_MAX
, /* non-ABI */
140 static struct poptOption long_options
[] = {
141 /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
142 {"help", 'h', POPT_ARG_NONE
, 0, OPT_HELP
, 0, 0},
143 {"session", 's', POPT_ARG_STRING
, &opt_session_name
, 0, 0, 0},
144 {"channel", 'c', POPT_ARG_STRING
, &opt_channel_name
, 0, 0, 0},
145 {"kernel", 'k', POPT_ARG_VAL
, &opt_kernel
, 1, 0, 0},
146 {"userspace", 'u', POPT_ARG_NONE
, 0, OPT_USERSPACE
, 0, 0},
147 {"type", 't', POPT_ARG_STRING
, &opt_type
, OPT_TYPE
, 0, 0},
148 {"list-options", 0, POPT_ARG_NONE
, NULL
, OPT_LIST_OPTIONS
, NULL
, NULL
},
149 {0, 0, 0, 0, 0, 0, 0}
155 #define PERF_HW(optstr, name, type, hide) \
157 optstr, type, hide, \
158 .u.perf = { PERF_TYPE_HARDWARE, PERF_COUNT_HW_##name, },\
161 #define PERF_SW(optstr, name, type, hide) \
163 optstr, type, hide, \
164 .u.perf = { PERF_TYPE_SOFTWARE, PERF_COUNT_SW_##name, },\
167 #define _PERF_HW_CACHE(optstr, name, type, op, result, hide) \
169 optstr, type, hide, \
171 PERF_TYPE_HW_CACHE, \
172 (uint64_t) PERF_COUNT_HW_CACHE_##name \
173 | ((uint64_t) PERF_COUNT_HW_CACHE_OP_##op << 8) \
174 | ((uint64_t) PERF_COUNT_HW_CACHE_RESULT_##result << 16), \
178 #define PERF_HW_CACHE(optstr, name, type, hide) \
179 _PERF_HW_CACHE(optstr "-loads", name, type, \
180 READ, ACCESS, hide), \
181 _PERF_HW_CACHE(optstr "-load-misses", name, type, \
183 _PERF_HW_CACHE(optstr "-stores", name, type, \
184 WRITE, ACCESS, hide), \
185 _PERF_HW_CACHE(optstr "-store-misses", name, type, \
186 WRITE, MISS, hide), \
187 _PERF_HW_CACHE(optstr "-prefetches", name, type, \
188 PREFETCH, ACCESS, hide), \
189 _PERF_HW_CACHE(optstr "-prefetch-misses", name, type, \
190 PREFETCH, MISS, hide)
193 const struct ctx_opts
{
195 enum context_type ctx_type
;
196 int hide_help
; /* Hide from --help */
204 { "pid", CONTEXT_PID
},
205 { "procname", CONTEXT_PROCNAME
},
206 { "prio", CONTEXT_PRIO
},
207 { "nice", CONTEXT_NICE
},
208 { "vpid", CONTEXT_VPID
},
209 { "tid", CONTEXT_TID
},
210 { "pthread_id", CONTEXT_PTHREAD_ID
},
211 { "vtid", CONTEXT_VTID
},
212 { "ppid", CONTEXT_PPID
},
213 { "vppid", CONTEXT_VPPID
},
214 { "hostname", CONTEXT_HOSTNAME
},
215 { "ip", CONTEXT_IP
},
219 /* Perf per-CPU counters */
220 PERF_HW("perf:cpu:cpu-cycles", CPU_CYCLES
,
221 CONTEXT_PERF_CPU_COUNTER
, 0),
222 PERF_HW("perf:cpu:cycles", CPU_CYCLES
,
223 CONTEXT_PERF_CPU_COUNTER
, 0),
224 PERF_HW("perf:cpu:stalled-cycles-frontend", STALLED_CYCLES_FRONTEND
,
225 CONTEXT_PERF_CPU_COUNTER
, 0),
226 PERF_HW("perf:cpu:idle-cycles-frontend", STALLED_CYCLES_FRONTEND
,
227 CONTEXT_PERF_CPU_COUNTER
, 0),
228 PERF_HW("perf:cpu:stalled-cycles-backend", STALLED_CYCLES_BACKEND
,
229 CONTEXT_PERF_CPU_COUNTER
, 0),
230 PERF_HW("perf:cpu:idle-cycles-backend", STALLED_CYCLES_BACKEND
,
231 CONTEXT_PERF_CPU_COUNTER
, 0),
232 PERF_HW("perf:cpu:instructions", INSTRUCTIONS
,
233 CONTEXT_PERF_CPU_COUNTER
, 0),
234 PERF_HW("perf:cpu:cache-references", CACHE_REFERENCES
,
235 CONTEXT_PERF_CPU_COUNTER
, 0),
236 PERF_HW("perf:cpu:cache-misses", CACHE_MISSES
,
237 CONTEXT_PERF_CPU_COUNTER
, 0),
238 PERF_HW("perf:cpu:branch-instructions", BRANCH_INSTRUCTIONS
,
239 CONTEXT_PERF_CPU_COUNTER
, 0),
240 PERF_HW("perf:cpu:branches", BRANCH_INSTRUCTIONS
,
241 CONTEXT_PERF_CPU_COUNTER
, 0),
242 PERF_HW("perf:cpu:branch-misses", BRANCH_MISSES
,
243 CONTEXT_PERF_CPU_COUNTER
, 0),
244 PERF_HW("perf:cpu:bus-cycles", BUS_CYCLES
,
245 CONTEXT_PERF_CPU_COUNTER
, 0),
247 PERF_HW_CACHE("perf:cpu:L1-dcache", L1D
,
248 CONTEXT_PERF_CPU_COUNTER
, 0),
249 PERF_HW_CACHE("perf:cpu:L1-icache", L1I
,
250 CONTEXT_PERF_CPU_COUNTER
, 0),
251 PERF_HW_CACHE("perf:cpu:LLC", LL
,
252 CONTEXT_PERF_CPU_COUNTER
, 0),
253 PERF_HW_CACHE("perf:cpu:dTLB", DTLB
,
254 CONTEXT_PERF_CPU_COUNTER
, 0),
255 _PERF_HW_CACHE("perf:cpu:iTLB-loads", ITLB
,
256 CONTEXT_PERF_CPU_COUNTER
, READ
, ACCESS
, 0),
257 _PERF_HW_CACHE("perf:cpu:iTLB-load-misses", ITLB
,
258 CONTEXT_PERF_CPU_COUNTER
, READ
, MISS
, 0),
259 _PERF_HW_CACHE("perf:cpu:branch-loads", BPU
,
260 CONTEXT_PERF_CPU_COUNTER
, READ
, ACCESS
, 0),
261 _PERF_HW_CACHE("perf:cpu:branch-load-misses", BPU
,
262 CONTEXT_PERF_CPU_COUNTER
, READ
, MISS
, 0),
264 PERF_SW("perf:cpu:cpu-clock", CPU_CLOCK
,
265 CONTEXT_PERF_CPU_COUNTER
, 0),
266 PERF_SW("perf:cpu:task-clock", TASK_CLOCK
,
267 CONTEXT_PERF_CPU_COUNTER
, 0),
268 PERF_SW("perf:cpu:page-fault", PAGE_FAULTS
,
269 CONTEXT_PERF_CPU_COUNTER
, 0),
270 PERF_SW("perf:cpu:faults", PAGE_FAULTS
,
271 CONTEXT_PERF_CPU_COUNTER
, 0),
272 PERF_SW("perf:cpu:major-faults", PAGE_FAULTS_MAJ
,
273 CONTEXT_PERF_CPU_COUNTER
, 0),
274 PERF_SW("perf:cpu:minor-faults", PAGE_FAULTS_MIN
,
275 CONTEXT_PERF_CPU_COUNTER
, 0),
276 PERF_SW("perf:cpu:context-switches", CONTEXT_SWITCHES
,
277 CONTEXT_PERF_CPU_COUNTER
, 0),
278 PERF_SW("perf:cpu:cs", CONTEXT_SWITCHES
,
279 CONTEXT_PERF_CPU_COUNTER
, 0),
280 PERF_SW("perf:cpu:cpu-migrations", CPU_MIGRATIONS
,
281 CONTEXT_PERF_CPU_COUNTER
, 0),
282 PERF_SW("perf:cpu:migrations", CPU_MIGRATIONS
,
283 CONTEXT_PERF_CPU_COUNTER
, 0),
284 PERF_SW("perf:cpu:alignment-faults", ALIGNMENT_FAULTS
,
285 CONTEXT_PERF_CPU_COUNTER
, 0),
286 PERF_SW("perf:cpu:emulation-faults", EMULATION_FAULTS
,
287 CONTEXT_PERF_CPU_COUNTER
, 0),
289 /* Perf per-thread counters */
290 PERF_HW("perf:thread:cpu-cycles", CPU_CYCLES
,
291 CONTEXT_PERF_THREAD_COUNTER
, 0),
292 PERF_HW("perf:thread:cycles", CPU_CYCLES
,
293 CONTEXT_PERF_THREAD_COUNTER
, 0),
294 PERF_HW("perf:thread:stalled-cycles-frontend", STALLED_CYCLES_FRONTEND
,
295 CONTEXT_PERF_THREAD_COUNTER
, 0),
296 PERF_HW("perf:thread:idle-cycles-frontend", STALLED_CYCLES_FRONTEND
,
297 CONTEXT_PERF_THREAD_COUNTER
, 0),
298 PERF_HW("perf:thread:stalled-cycles-backend", STALLED_CYCLES_BACKEND
,
299 CONTEXT_PERF_THREAD_COUNTER
, 0),
300 PERF_HW("perf:thread:idle-cycles-backend", STALLED_CYCLES_BACKEND
,
301 CONTEXT_PERF_THREAD_COUNTER
, 0),
302 PERF_HW("perf:thread:instructions", INSTRUCTIONS
,
303 CONTEXT_PERF_THREAD_COUNTER
, 0),
304 PERF_HW("perf:thread:cache-references", CACHE_REFERENCES
,
305 CONTEXT_PERF_THREAD_COUNTER
, 0),
306 PERF_HW("perf:thread:cache-misses", CACHE_MISSES
,
307 CONTEXT_PERF_THREAD_COUNTER
, 0),
308 PERF_HW("perf:thread:branch-instructions", BRANCH_INSTRUCTIONS
,
309 CONTEXT_PERF_THREAD_COUNTER
, 0),
310 PERF_HW("perf:thread:branches", BRANCH_INSTRUCTIONS
,
311 CONTEXT_PERF_THREAD_COUNTER
, 0),
312 PERF_HW("perf:thread:branch-misses", BRANCH_MISSES
,
313 CONTEXT_PERF_THREAD_COUNTER
, 0),
314 PERF_HW("perf:thread:bus-cycles", BUS_CYCLES
,
315 CONTEXT_PERF_THREAD_COUNTER
, 0),
317 PERF_HW_CACHE("perf:thread:L1-dcache", L1D
,
318 CONTEXT_PERF_THREAD_COUNTER
, 0),
319 PERF_HW_CACHE("perf:thread:L1-icache", L1I
,
320 CONTEXT_PERF_THREAD_COUNTER
, 0),
321 PERF_HW_CACHE("perf:thread:LLC", LL
,
322 CONTEXT_PERF_THREAD_COUNTER
, 0),
323 PERF_HW_CACHE("perf:thread:dTLB", DTLB
,
324 CONTEXT_PERF_THREAD_COUNTER
, 0),
325 _PERF_HW_CACHE("perf:thread:iTLB-loads", ITLB
,
326 CONTEXT_PERF_THREAD_COUNTER
, READ
, ACCESS
, 0),
327 _PERF_HW_CACHE("perf:thread:iTLB-load-misses", ITLB
,
328 CONTEXT_PERF_THREAD_COUNTER
, READ
, MISS
, 0),
329 _PERF_HW_CACHE("perf:thread:branch-loads", BPU
,
330 CONTEXT_PERF_THREAD_COUNTER
, READ
, ACCESS
, 0),
331 _PERF_HW_CACHE("perf:thread:branch-load-misses", BPU
,
332 CONTEXT_PERF_THREAD_COUNTER
, READ
, MISS
, 0),
334 PERF_SW("perf:thread:cpu-clock", CPU_CLOCK
,
335 CONTEXT_PERF_THREAD_COUNTER
, 0),
336 PERF_SW("perf:thread:task-clock", TASK_CLOCK
,
337 CONTEXT_PERF_THREAD_COUNTER
, 0),
338 PERF_SW("perf:thread:page-fault", PAGE_FAULTS
,
339 CONTEXT_PERF_THREAD_COUNTER
, 0),
340 PERF_SW("perf:thread:faults", PAGE_FAULTS
,
341 CONTEXT_PERF_THREAD_COUNTER
, 0),
342 PERF_SW("perf:thread:major-faults", PAGE_FAULTS_MAJ
,
343 CONTEXT_PERF_THREAD_COUNTER
, 0),
344 PERF_SW("perf:thread:minor-faults", PAGE_FAULTS_MIN
,
345 CONTEXT_PERF_THREAD_COUNTER
, 0),
346 PERF_SW("perf:thread:context-switches", CONTEXT_SWITCHES
,
347 CONTEXT_PERF_THREAD_COUNTER
, 0),
348 PERF_SW("perf:thread:cs", CONTEXT_SWITCHES
,
349 CONTEXT_PERF_THREAD_COUNTER
, 0),
350 PERF_SW("perf:thread:cpu-migrations", CPU_MIGRATIONS
,
351 CONTEXT_PERF_THREAD_COUNTER
, 0),
352 PERF_SW("perf:thread:migrations", CPU_MIGRATIONS
,
353 CONTEXT_PERF_THREAD_COUNTER
, 0),
354 PERF_SW("perf:thread:alignment-faults", ALIGNMENT_FAULTS
,
355 CONTEXT_PERF_THREAD_COUNTER
, 0),
356 PERF_SW("perf:thread:emulation-faults", EMULATION_FAULTS
,
357 CONTEXT_PERF_THREAD_COUNTER
, 0),
360 * Perf per-CPU counters, backward compatibilty for names.
361 * Hidden from help listing.
363 PERF_HW("perf:cpu-cycles", CPU_CYCLES
,
364 CONTEXT_PERF_COUNTER
, 1),
365 PERF_HW("perf:cycles", CPU_CYCLES
,
366 CONTEXT_PERF_COUNTER
, 1),
367 PERF_HW("perf:stalled-cycles-frontend", STALLED_CYCLES_FRONTEND
,
368 CONTEXT_PERF_COUNTER
, 1),
369 PERF_HW("perf:idle-cycles-frontend", STALLED_CYCLES_FRONTEND
,
370 CONTEXT_PERF_COUNTER
, 1),
371 PERF_HW("perf:stalled-cycles-backend", STALLED_CYCLES_BACKEND
,
372 CONTEXT_PERF_COUNTER
, 1),
373 PERF_HW("perf:idle-cycles-backend", STALLED_CYCLES_BACKEND
,
374 CONTEXT_PERF_COUNTER
, 1),
375 PERF_HW("perf:instructions", INSTRUCTIONS
,
376 CONTEXT_PERF_COUNTER
, 1),
377 PERF_HW("perf:cache-references", CACHE_REFERENCES
,
378 CONTEXT_PERF_COUNTER
, 1),
379 PERF_HW("perf:cache-misses", CACHE_MISSES
,
380 CONTEXT_PERF_COUNTER
, 1),
381 PERF_HW("perf:branch-instructions", BRANCH_INSTRUCTIONS
,
382 CONTEXT_PERF_COUNTER
, 1),
383 PERF_HW("perf:branches", BRANCH_INSTRUCTIONS
,
384 CONTEXT_PERF_COUNTER
, 1),
385 PERF_HW("perf:branch-misses", BRANCH_MISSES
,
386 CONTEXT_PERF_COUNTER
, 1),
387 PERF_HW("perf:bus-cycles", BUS_CYCLES
,
388 CONTEXT_PERF_COUNTER
, 1),
390 PERF_HW_CACHE("perf:L1-dcache", L1D
,
391 CONTEXT_PERF_COUNTER
, 1),
392 PERF_HW_CACHE("perf:L1-icache", L1I
,
393 CONTEXT_PERF_COUNTER
, 1),
394 PERF_HW_CACHE("perf:LLC", LL
,
395 CONTEXT_PERF_COUNTER
, 1),
396 PERF_HW_CACHE("perf:dTLB", DTLB
,
397 CONTEXT_PERF_COUNTER
, 1),
398 _PERF_HW_CACHE("perf:iTLB-loads", ITLB
,
399 CONTEXT_PERF_COUNTER
, READ
, ACCESS
, 1),
400 _PERF_HW_CACHE("perf:iTLB-load-misses", ITLB
,
401 CONTEXT_PERF_COUNTER
, READ
, MISS
, 1),
402 _PERF_HW_CACHE("perf:branch-loads", BPU
,
403 CONTEXT_PERF_COUNTER
, READ
, ACCESS
, 1),
404 _PERF_HW_CACHE("perf:branch-load-misses", BPU
,
405 CONTEXT_PERF_COUNTER
, READ
, MISS
, 1),
407 PERF_SW("perf:cpu-clock", CPU_CLOCK
,
408 CONTEXT_PERF_COUNTER
, 1),
409 PERF_SW("perf:task-clock", TASK_CLOCK
,
410 CONTEXT_PERF_COUNTER
, 1),
411 PERF_SW("perf:page-fault", PAGE_FAULTS
,
412 CONTEXT_PERF_COUNTER
, 1),
413 PERF_SW("perf:faults", PAGE_FAULTS
,
414 CONTEXT_PERF_COUNTER
, 1),
415 PERF_SW("perf:major-faults", PAGE_FAULTS_MAJ
,
416 CONTEXT_PERF_COUNTER
, 1),
417 PERF_SW("perf:minor-faults", PAGE_FAULTS_MIN
,
418 CONTEXT_PERF_COUNTER
, 1),
419 PERF_SW("perf:context-switches", CONTEXT_SWITCHES
,
420 CONTEXT_PERF_COUNTER
, 1),
421 PERF_SW("perf:cs", CONTEXT_SWITCHES
,
422 CONTEXT_PERF_COUNTER
, 1),
423 PERF_SW("perf:cpu-migrations", CPU_MIGRATIONS
,
424 CONTEXT_PERF_COUNTER
, 1),
425 PERF_SW("perf:migrations", CPU_MIGRATIONS
,
426 CONTEXT_PERF_COUNTER
, 1),
427 PERF_SW("perf:alignment-faults", ALIGNMENT_FAULTS
,
428 CONTEXT_PERF_COUNTER
, 1),
429 PERF_SW("perf:emulation-faults", EMULATION_FAULTS
,
430 CONTEXT_PERF_COUNTER
, 1),
432 { NULL
, -1 }, /* Closure */
436 #undef _PERF_HW_CACHE
441 * Context type for command line option parsing.
444 const struct ctx_opts
*opt
;
445 struct cds_list_head list
;
449 * List of context type. Use to enable multiple context on a single command
452 struct ctx_type_list
{
453 struct cds_list_head head
;
455 .head
= CDS_LIST_HEAD_INIT(ctx_type_list
.head
),
459 * Pretty print context type.
461 static void print_ctx_type(FILE *ofp
)
463 const char *indent
= " ";
464 int indent_len
= strlen(indent
);
467 fprintf(ofp
, "%s", indent
);
469 while (ctx_opts
[i
].symbol
!= NULL
) {
470 if (!ctx_opts
[i
].hide_help
) {
471 if (len
> indent_len
) {
472 if (len
+ strlen(ctx_opts
[i
].symbol
) + 2
475 fprintf(ofp
, "%s", indent
);
478 len
+= fprintf(ofp
, ", ");
481 len
+= fprintf(ofp
, "%s", ctx_opts
[i
].symbol
);
490 static void usage(FILE *ofp
)
492 fprintf(ofp
, "usage: lttng add-context -t TYPE [-k|-u] [OPTIONS]\n");
494 fprintf(ofp
, "If no channel is given (-c), the context is added to\n");
495 fprintf(ofp
, "all channels.\n");
497 fprintf(ofp
, "Otherwise the context is added only to the channel (-c).\n");
499 fprintf(ofp
, "Exactly one domain (-k or -u) must be specified.\n");
501 fprintf(ofp
, "Options:\n");
502 fprintf(ofp
, " -h, --help Show this help\n");
503 fprintf(ofp
, " --list-options Simple listing of options\n");
504 fprintf(ofp
, " -s, --session NAME Apply to session name\n");
505 fprintf(ofp
, " -c, --channel NAME Apply to channel\n");
506 fprintf(ofp
, " -k, --kernel Apply to the kernel tracer\n");
507 fprintf(ofp
, " -u, --userspace Apply to the user-space tracer\n");
509 fprintf(ofp
, "Context:\n");
510 fprintf(ofp
, " -t, --type TYPE Context type. You can repeat that option on\n");
511 fprintf(ofp
, " the command line to specify multiple contexts at once.\n");
512 fprintf(ofp
, " (--kernel preempts --userspace)\n");
513 fprintf(ofp
, " TYPE can be one of the strings below:\n");
516 fprintf(ofp
, "Note that the vpid, vppid and vtid context types represent the virtual process id,\n"
517 "virtual parent process id and virtual thread id as seen from the current execution context\n"
518 "as opposed to the pid, ppid and tid which are kernel internal data structures.\n\n");
519 fprintf(ofp
, "Example:\n");
520 fprintf(ofp
, "This command will add the context information 'prio' and two per-cpu\n"
521 "perf counters (hardware branch misses and cache misses), to all channels\n"
522 "in the trace data output:\n");
523 fprintf(ofp
, "# lttng add-context -k -t prio -t perf:cpu:branch-misses -t perf:cpu:cache-misses\n");
528 * Find context numerical value from string.
530 static int find_ctx_type_idx(const char *opt
)
534 while (ctx_opts
[i
].symbol
!= NULL
) {
535 if (strcmp(opt
, ctx_opts
[i
].symbol
) == 0) {
547 * Add context to channel or event.
549 static int add_context(char *session_name
)
551 int ret
= CMD_SUCCESS
, warn
= 0, success
= 0;
552 struct lttng_event_context context
;
553 struct lttng_domain dom
;
554 struct ctx_type
*type
;
557 memset(&context
, 0, sizeof(context
));
558 memset(&dom
, 0, sizeof(dom
));
561 dom
.type
= LTTNG_DOMAIN_KERNEL
;
562 } else if (opt_userspace
) {
563 dom
.type
= LTTNG_DOMAIN_UST
;
568 handle
= lttng_create_handle(session_name
, &dom
);
569 if (handle
== NULL
) {
575 /* Open a contexts element */
576 ret
= mi_lttng_writer_open_element(writer
, config_element_contexts
);
582 /* Iterate over all the context types given */
583 cds_list_for_each_entry(type
, &ctx_type_list
.head
, list
) {
584 context
.ctx
= (enum lttng_event_context_type
) type
->opt
->ctx_type
;
585 switch (context
.ctx
) {
586 case LTTNG_EVENT_CONTEXT_PERF_COUNTER
:
587 case LTTNG_EVENT_CONTEXT_PERF_CPU_COUNTER
:
588 case LTTNG_EVENT_CONTEXT_PERF_THREAD_COUNTER
:
589 context
.u
.perf_counter
.type
= type
->opt
->u
.perf
.type
;
590 context
.u
.perf_counter
.config
= type
->opt
->u
.perf
.config
;
591 strncpy(context
.u
.perf_counter
.name
, type
->opt
->symbol
,
592 LTTNG_SYMBOL_NAME_LEN
);
593 context
.u
.perf_counter
.name
[LTTNG_SYMBOL_NAME_LEN
- 1] = '\0';
594 /* Replace : and - by _ */
595 while ((ptr
= strchr(context
.u
.perf_counter
.name
, '-')) != NULL
) {
598 while ((ptr
= strchr(context
.u
.perf_counter
.name
, ':')) != NULL
) {
605 DBG("Adding context...");
608 /* We leave context open the update the success of the command */
609 ret
= mi_lttng_context(writer
, &context
, 1);
616 ret
= lttng_add_context(handle
, &context
, NULL
, opt_channel_name
);
618 ERR("%s: %s", type
->opt
->symbol
, lttng_strerror(ret
));
622 if (opt_channel_name
) {
623 MSG("%s context %s added to channel %s",
624 opt_kernel
? "kernel" : "UST", type
->opt
->symbol
,
627 MSG("%s context %s added to all channels",
628 opt_kernel
? "kernel" : "UST", type
->opt
->symbol
)
634 /* Is the single operation a success ? */
635 ret
= mi_lttng_writer_write_element_bool(writer
,
636 mi_lttng_element_success
, success
);
642 /* Close the context element */
643 ret
= mi_lttng_writer_close_element(writer
);
652 /* Close contexts element */
653 ret
= mi_lttng_writer_close_element(writer
);
662 lttng_destroy_handle(handle
);
665 * This means that at least one add_context failed and tells the user to
666 * look on stderr for error(s).
675 * Add context to channel or event.
677 int cmd_add_context(int argc
, const char **argv
)
679 int index
, opt
, ret
= CMD_SUCCESS
, command_ret
= CMD_SUCCESS
;
681 static poptContext pc
;
682 struct ctx_type
*type
, *tmptype
;
683 char *session_name
= NULL
;
691 pc
= poptGetContext(NULL
, argc
, argv
, long_options
, 0);
692 poptReadDefaultConfig(pc
, 0);
694 while ((opt
= poptGetNextOpt(pc
)) != -1) {
701 * Look up the index of opt_type in ctx_opts[] first, so we don't
702 * have to free(type) on failure.
704 index
= find_ctx_type_idx(opt_type
);
706 ERR("Unknown context type %s", opt_type
);
711 type
= zmalloc(sizeof(struct ctx_type
));
713 PERROR("malloc ctx_type");
718 type
->opt
= &ctx_opts
[index
];
719 if (type
->opt
->symbol
== NULL
) {
720 ERR("Unknown context type %s", opt_type
);
725 cds_list_add_tail(&type
->list
, &ctx_type_list
.head
);
731 case OPT_LIST_OPTIONS
:
732 list_cmd_options(stdout
, long_options
);
741 ret
= print_missing_or_multiple_domains(opt_kernel
+ opt_userspace
);
749 ERR("Missing mandatory -t TYPE");
755 if (!opt_session_name
) {
756 session_name
= get_session_name();
757 if (session_name
== NULL
) {
762 session_name
= opt_session_name
;
767 writer
= mi_lttng_writer_create(fileno(stdout
), lttng_opt_mi
);
769 ret
= -LTTNG_ERR_NOMEM
;
773 /* Open command element */
774 ret
= mi_lttng_writer_command_open(writer
,
775 mi_lttng_element_command_add_context
);
781 /* Open output element */
782 ret
= mi_lttng_writer_open_element(writer
,
783 mi_lttng_element_command_output
);
790 command_ret
= add_context(session_name
);
797 /* Close output element */
798 ret
= mi_lttng_writer_close_element(writer
);
805 ret
= mi_lttng_writer_write_element_bool(writer
,
806 mi_lttng_element_command_success
, success
);
812 /* Command element close */
813 ret
= mi_lttng_writer_command_close(writer
);
821 if (!opt_session_name
) {
826 if (writer
&& mi_lttng_writer_destroy(writer
)) {
827 /* Preserve original error code */
828 ret
= ret
? ret
: LTTNG_ERR_MI_IO_FAIL
;
831 /* Cleanup allocated memory */
832 cds_list_for_each_entry_safe(type
, tmptype
, &ctx_type_list
.head
, list
) {
836 /* Overwrite ret if an error occurred during add_context() */
837 ret
= command_ret
? command_ret
: ret
;