Fix: error on no/multiple domain options
[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
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;
d78d6610 42static char *opt_type;
89b72577 43
d65106b1
DG
44enum {
45 OPT_HELP = 1,
46 OPT_TYPE,
eeac7d46 47 OPT_USERSPACE,
679b4943 48 OPT_LIST_OPTIONS,
d65106b1
DG
49};
50
cd80958d 51static struct lttng_handle *handle;
89b72577 52static struct mi_writer *writer;
cd80958d 53
90b9a268
DG
54/*
55 * Taken from the LTTng ABI
56 */
57enum context_type {
58 CONTEXT_PID = 0,
aa3514e9 59 CONTEXT_PERF_COUNTER = 1, /* Backward compat. */
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,
aa3514e9
MD
71 CONTEXT_PERF_CPU_COUNTER = 13,
72 CONTEXT_PERF_THREAD_COUNTER = 14,
3301e740
DG
73};
74
90b9a268
DG
75/*
76 * Taken from the Perf ABI (all enum perf_*)
77 */
78enum perf_type {
79 PERF_TYPE_HARDWARE = 0,
80 PERF_TYPE_SOFTWARE = 1,
b13d56d7 81 PERF_TYPE_HW_CACHE = 3,
3301e740
DG
82};
83
90b9a268 84enum perf_count_hard {
b13d56d7
MD
85 PERF_COUNT_HW_CPU_CYCLES = 0,
86 PERF_COUNT_HW_INSTRUCTIONS = 1,
87 PERF_COUNT_HW_CACHE_REFERENCES = 2,
88 PERF_COUNT_HW_CACHE_MISSES = 3,
89 PERF_COUNT_HW_BRANCH_INSTRUCTIONS = 4,
90 PERF_COUNT_HW_BRANCH_MISSES = 5,
91 PERF_COUNT_HW_BUS_CYCLES = 6,
92 PERF_COUNT_HW_STALLED_CYCLES_FRONTEND = 7,
93 PERF_COUNT_HW_STALLED_CYCLES_BACKEND = 8,
90b9a268
DG
94};
95
96enum perf_count_soft {
97 PERF_COUNT_SW_CPU_CLOCK = 0,
98 PERF_COUNT_SW_TASK_CLOCK = 1,
99 PERF_COUNT_SW_PAGE_FAULTS = 2,
100 PERF_COUNT_SW_CONTEXT_SWITCHES = 3,
101 PERF_COUNT_SW_CPU_MIGRATIONS = 4,
102 PERF_COUNT_SW_PAGE_FAULTS_MIN = 5,
103 PERF_COUNT_SW_PAGE_FAULTS_MAJ = 6,
104 PERF_COUNT_SW_ALIGNMENT_FAULTS = 7,
105 PERF_COUNT_SW_EMULATION_FAULTS = 8,
3301e740
DG
106};
107
b13d56d7
MD
108/*
109 * Generalized hardware cache events:
110 *
111 * { L1-D, L1-I, LLC, ITLB, DTLB, BPU } x
112 * { read, write, prefetch } x
113 * { accesses, misses }
114 */
115enum perf_hw_cache_id {
116 PERF_COUNT_HW_CACHE_L1D = 0,
117 PERF_COUNT_HW_CACHE_L1I = 1,
118 PERF_COUNT_HW_CACHE_LL = 2,
119 PERF_COUNT_HW_CACHE_DTLB = 3,
120 PERF_COUNT_HW_CACHE_ITLB = 4,
121 PERF_COUNT_HW_CACHE_BPU = 5,
122
123 PERF_COUNT_HW_CACHE_MAX, /* non-ABI */
124};
125
126enum perf_hw_cache_op_id {
127 PERF_COUNT_HW_CACHE_OP_READ = 0,
128 PERF_COUNT_HW_CACHE_OP_WRITE = 1,
129 PERF_COUNT_HW_CACHE_OP_PREFETCH = 2,
130
131 PERF_COUNT_HW_CACHE_OP_MAX, /* non-ABI */
132};
133
134enum perf_hw_cache_op_result_id {
135 PERF_COUNT_HW_CACHE_RESULT_ACCESS = 0,
136 PERF_COUNT_HW_CACHE_RESULT_MISS = 1,
137
138 PERF_COUNT_HW_CACHE_RESULT_MAX, /* non-ABI */
139};
140
d65106b1
DG
141static struct poptOption long_options[] = {
142 /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
143 {"help", 'h', POPT_ARG_NONE, 0, OPT_HELP, 0, 0},
5440dc42 144 {"session", 's', POPT_ARG_STRING, &opt_session_name, 0, 0, 0},
d65106b1 145 {"channel", 'c', POPT_ARG_STRING, &opt_channel_name, 0, 0, 0},
d65106b1 146 {"kernel", 'k', POPT_ARG_VAL, &opt_kernel, 1, 0, 0},
d78d6610 147 {"userspace", 'u', POPT_ARG_NONE, 0, OPT_USERSPACE, 0, 0},
6caa2bcc 148 {"type", 't', POPT_ARG_STRING, &opt_type, OPT_TYPE, 0, 0},
679b4943 149 {"list-options", 0, POPT_ARG_NONE, NULL, OPT_LIST_OPTIONS, NULL, NULL},
d65106b1
DG
150 {0, 0, 0, 0, 0, 0, 0}
151};
152
90b9a268 153/*
b13d56d7 154 * Context options
90b9a268 155 */
aa3514e9 156#define PERF_HW(optstr, name, type, hide) \
b13d56d7 157 { \
aa3514e9 158 optstr, type, hide, \
b13d56d7
MD
159 .u.perf = { PERF_TYPE_HARDWARE, PERF_COUNT_HW_##name, },\
160 }
90b9a268 161
aa3514e9 162#define PERF_SW(optstr, name, type, hide) \
b13d56d7 163 { \
aa3514e9 164 optstr, type, hide, \
b13d56d7
MD
165 .u.perf = { PERF_TYPE_SOFTWARE, PERF_COUNT_SW_##name, },\
166 }
90b9a268 167
aa3514e9 168#define _PERF_HW_CACHE(optstr, name, type, op, result, hide) \
b13d56d7 169 { \
aa3514e9 170 optstr, type, hide, \
b13d56d7
MD
171 .u.perf = { \
172 PERF_TYPE_HW_CACHE, \
173 (uint64_t) PERF_COUNT_HW_CACHE_##name \
18829107
MD
174 | ((uint64_t) PERF_COUNT_HW_CACHE_OP_##op << 8) \
175 | ((uint64_t) PERF_COUNT_HW_CACHE_RESULT_##result << 16), \
b13d56d7
MD
176 }, \
177 }
178
aa3514e9
MD
179#define PERF_HW_CACHE(optstr, name, type, hide) \
180 _PERF_HW_CACHE(optstr "-loads", name, type, \
181 READ, ACCESS, hide), \
182 _PERF_HW_CACHE(optstr "-load-misses", name, type, \
183 READ, MISS, hide), \
184 _PERF_HW_CACHE(optstr "-stores", name, type, \
185 WRITE, ACCESS, hide), \
186 _PERF_HW_CACHE(optstr "-store-misses", name, type, \
187 WRITE, MISS, hide), \
188 _PERF_HW_CACHE(optstr "-prefetches", name, type, \
189 PREFETCH, ACCESS, hide), \
190 _PERF_HW_CACHE(optstr "-prefetch-misses", name, type, \
191 PREFETCH, MISS, hide)
b13d56d7
MD
192
193static
194const struct ctx_opts {
90b9a268 195 char *symbol;
b13d56d7 196 enum context_type ctx_type;
aa3514e9 197 int hide_help; /* Hide from --help */
b13d56d7
MD
198 union {
199 struct {
200 uint32_t type;
201 uint64_t config;
202 } perf;
203 } u;
204} ctx_opts[] = {
205 { "pid", CONTEXT_PID },
95da1297 206 { "procname", CONTEXT_PROCNAME },
b13d56d7
MD
207 { "prio", CONTEXT_PRIO },
208 { "nice", CONTEXT_NICE },
209 { "vpid", CONTEXT_VPID },
210 { "tid", CONTEXT_TID },
9197c5c4 211 { "pthread_id", CONTEXT_PTHREAD_ID },
b13d56d7
MD
212 { "vtid", CONTEXT_VTID },
213 { "ppid", CONTEXT_PPID },
214 { "vppid", CONTEXT_VPPID },
54773d68 215 { "hostname", CONTEXT_HOSTNAME },
7c612c2e 216 { "ip", CONTEXT_IP },
aa3514e9 217
b13d56d7 218 /* Perf options */
aa3514e9
MD
219
220 /* Perf per-CPU counters */
221 PERF_HW("perf:cpu:cpu-cycles", CPU_CYCLES,
222 CONTEXT_PERF_CPU_COUNTER, 0),
223 PERF_HW("perf:cpu:cycles", CPU_CYCLES,
224 CONTEXT_PERF_CPU_COUNTER, 0),
225 PERF_HW("perf:cpu:stalled-cycles-frontend", STALLED_CYCLES_FRONTEND,
226 CONTEXT_PERF_CPU_COUNTER, 0),
227 PERF_HW("perf:cpu:idle-cycles-frontend", STALLED_CYCLES_FRONTEND,
228 CONTEXT_PERF_CPU_COUNTER, 0),
229 PERF_HW("perf:cpu:stalled-cycles-backend", STALLED_CYCLES_BACKEND,
230 CONTEXT_PERF_CPU_COUNTER, 0),
231 PERF_HW("perf:cpu:idle-cycles-backend", STALLED_CYCLES_BACKEND,
232 CONTEXT_PERF_CPU_COUNTER, 0),
233 PERF_HW("perf:cpu:instructions", INSTRUCTIONS,
234 CONTEXT_PERF_CPU_COUNTER, 0),
235 PERF_HW("perf:cpu:cache-references", CACHE_REFERENCES,
236 CONTEXT_PERF_CPU_COUNTER, 0),
237 PERF_HW("perf:cpu:cache-misses", CACHE_MISSES,
238 CONTEXT_PERF_CPU_COUNTER, 0),
239 PERF_HW("perf:cpu:branch-instructions", BRANCH_INSTRUCTIONS,
240 CONTEXT_PERF_CPU_COUNTER, 0),
241 PERF_HW("perf:cpu:branches", BRANCH_INSTRUCTIONS,
242 CONTEXT_PERF_CPU_COUNTER, 0),
243 PERF_HW("perf:cpu:branch-misses", BRANCH_MISSES,
244 CONTEXT_PERF_CPU_COUNTER, 0),
245 PERF_HW("perf:cpu:bus-cycles", BUS_CYCLES,
246 CONTEXT_PERF_CPU_COUNTER, 0),
247
248 PERF_HW_CACHE("perf:cpu:L1-dcache", L1D,
249 CONTEXT_PERF_CPU_COUNTER, 0),
250 PERF_HW_CACHE("perf:cpu:L1-icache", L1I,
251 CONTEXT_PERF_CPU_COUNTER, 0),
252 PERF_HW_CACHE("perf:cpu:LLC", LL,
253 CONTEXT_PERF_CPU_COUNTER, 0),
254 PERF_HW_CACHE("perf:cpu:dTLB", DTLB,
255 CONTEXT_PERF_CPU_COUNTER, 0),
256 _PERF_HW_CACHE("perf:cpu:iTLB-loads", ITLB,
257 CONTEXT_PERF_CPU_COUNTER, READ, ACCESS, 0),
258 _PERF_HW_CACHE("perf:cpu:iTLB-load-misses", ITLB,
259 CONTEXT_PERF_CPU_COUNTER, READ, MISS, 0),
260 _PERF_HW_CACHE("perf:cpu:branch-loads", BPU,
261 CONTEXT_PERF_CPU_COUNTER, READ, ACCESS, 0),
262 _PERF_HW_CACHE("perf:cpu:branch-load-misses", BPU,
263 CONTEXT_PERF_CPU_COUNTER, READ, MISS, 0),
264
265 PERF_SW("perf:cpu:cpu-clock", CPU_CLOCK,
266 CONTEXT_PERF_CPU_COUNTER, 0),
267 PERF_SW("perf:cpu:task-clock", TASK_CLOCK,
268 CONTEXT_PERF_CPU_COUNTER, 0),
269 PERF_SW("perf:cpu:page-fault", PAGE_FAULTS,
270 CONTEXT_PERF_CPU_COUNTER, 0),
271 PERF_SW("perf:cpu:faults", PAGE_FAULTS,
272 CONTEXT_PERF_CPU_COUNTER, 0),
273 PERF_SW("perf:cpu:major-faults", PAGE_FAULTS_MAJ,
274 CONTEXT_PERF_CPU_COUNTER, 0),
275 PERF_SW("perf:cpu:minor-faults", PAGE_FAULTS_MIN,
276 CONTEXT_PERF_CPU_COUNTER, 0),
277 PERF_SW("perf:cpu:context-switches", CONTEXT_SWITCHES,
278 CONTEXT_PERF_CPU_COUNTER, 0),
279 PERF_SW("perf:cpu:cs", CONTEXT_SWITCHES,
280 CONTEXT_PERF_CPU_COUNTER, 0),
281 PERF_SW("perf:cpu:cpu-migrations", CPU_MIGRATIONS,
282 CONTEXT_PERF_CPU_COUNTER, 0),
283 PERF_SW("perf:cpu:migrations", CPU_MIGRATIONS,
284 CONTEXT_PERF_CPU_COUNTER, 0),
285 PERF_SW("perf:cpu:alignment-faults", ALIGNMENT_FAULTS,
286 CONTEXT_PERF_CPU_COUNTER, 0),
287 PERF_SW("perf:cpu:emulation-faults", EMULATION_FAULTS,
288 CONTEXT_PERF_CPU_COUNTER, 0),
289
290 /* Perf per-thread counters */
291 PERF_HW("perf:thread:cpu-cycles", CPU_CYCLES,
292 CONTEXT_PERF_THREAD_COUNTER, 0),
293 PERF_HW("perf:thread:cycles", CPU_CYCLES,
294 CONTEXT_PERF_THREAD_COUNTER, 0),
295 PERF_HW("perf:thread:stalled-cycles-frontend", STALLED_CYCLES_FRONTEND,
296 CONTEXT_PERF_THREAD_COUNTER, 0),
297 PERF_HW("perf:thread:idle-cycles-frontend", STALLED_CYCLES_FRONTEND,
298 CONTEXT_PERF_THREAD_COUNTER, 0),
299 PERF_HW("perf:thread:stalled-cycles-backend", STALLED_CYCLES_BACKEND,
300 CONTEXT_PERF_THREAD_COUNTER, 0),
301 PERF_HW("perf:thread:idle-cycles-backend", STALLED_CYCLES_BACKEND,
302 CONTEXT_PERF_THREAD_COUNTER, 0),
303 PERF_HW("perf:thread:instructions", INSTRUCTIONS,
304 CONTEXT_PERF_THREAD_COUNTER, 0),
305 PERF_HW("perf:thread:cache-references", CACHE_REFERENCES,
306 CONTEXT_PERF_THREAD_COUNTER, 0),
307 PERF_HW("perf:thread:cache-misses", CACHE_MISSES,
308 CONTEXT_PERF_THREAD_COUNTER, 0),
309 PERF_HW("perf:thread:branch-instructions", BRANCH_INSTRUCTIONS,
310 CONTEXT_PERF_THREAD_COUNTER, 0),
311 PERF_HW("perf:thread:branches", BRANCH_INSTRUCTIONS,
312 CONTEXT_PERF_THREAD_COUNTER, 0),
313 PERF_HW("perf:thread:branch-misses", BRANCH_MISSES,
314 CONTEXT_PERF_THREAD_COUNTER, 0),
315 PERF_HW("perf:thread:bus-cycles", BUS_CYCLES,
316 CONTEXT_PERF_THREAD_COUNTER, 0),
317
318 PERF_HW_CACHE("perf:thread:L1-dcache", L1D,
319 CONTEXT_PERF_THREAD_COUNTER, 0),
320 PERF_HW_CACHE("perf:thread:L1-icache", L1I,
321 CONTEXT_PERF_THREAD_COUNTER, 0),
322 PERF_HW_CACHE("perf:thread:LLC", LL,
323 CONTEXT_PERF_THREAD_COUNTER, 0),
324 PERF_HW_CACHE("perf:thread:dTLB", DTLB,
325 CONTEXT_PERF_THREAD_COUNTER, 0),
326 _PERF_HW_CACHE("perf:thread:iTLB-loads", ITLB,
327 CONTEXT_PERF_THREAD_COUNTER, READ, ACCESS, 0),
328 _PERF_HW_CACHE("perf:thread:iTLB-load-misses", ITLB,
329 CONTEXT_PERF_THREAD_COUNTER, READ, MISS, 0),
330 _PERF_HW_CACHE("perf:thread:branch-loads", BPU,
331 CONTEXT_PERF_THREAD_COUNTER, READ, ACCESS, 0),
332 _PERF_HW_CACHE("perf:thread:branch-load-misses", BPU,
333 CONTEXT_PERF_THREAD_COUNTER, READ, MISS, 0),
334
335 PERF_SW("perf:thread:cpu-clock", CPU_CLOCK,
336 CONTEXT_PERF_THREAD_COUNTER, 0),
337 PERF_SW("perf:thread:task-clock", TASK_CLOCK,
338 CONTEXT_PERF_THREAD_COUNTER, 0),
339 PERF_SW("perf:thread:page-fault", PAGE_FAULTS,
340 CONTEXT_PERF_THREAD_COUNTER, 0),
341 PERF_SW("perf:thread:faults", PAGE_FAULTS,
342 CONTEXT_PERF_THREAD_COUNTER, 0),
343 PERF_SW("perf:thread:major-faults", PAGE_FAULTS_MAJ,
344 CONTEXT_PERF_THREAD_COUNTER, 0),
345 PERF_SW("perf:thread:minor-faults", PAGE_FAULTS_MIN,
346 CONTEXT_PERF_THREAD_COUNTER, 0),
347 PERF_SW("perf:thread:context-switches", CONTEXT_SWITCHES,
348 CONTEXT_PERF_THREAD_COUNTER, 0),
349 PERF_SW("perf:thread:cs", CONTEXT_SWITCHES,
350 CONTEXT_PERF_THREAD_COUNTER, 0),
351 PERF_SW("perf:thread:cpu-migrations", CPU_MIGRATIONS,
352 CONTEXT_PERF_THREAD_COUNTER, 0),
353 PERF_SW("perf:thread:migrations", CPU_MIGRATIONS,
354 CONTEXT_PERF_THREAD_COUNTER, 0),
355 PERF_SW("perf:thread:alignment-faults", ALIGNMENT_FAULTS,
356 CONTEXT_PERF_THREAD_COUNTER, 0),
357 PERF_SW("perf:thread:emulation-faults", EMULATION_FAULTS,
358 CONTEXT_PERF_THREAD_COUNTER, 0),
359
360 /*
361 * Perf per-CPU counters, backward compatibilty for names.
362 * Hidden from help listing.
363 */
364 PERF_HW("perf:cpu-cycles", CPU_CYCLES,
365 CONTEXT_PERF_COUNTER, 1),
366 PERF_HW("perf:cycles", CPU_CYCLES,
367 CONTEXT_PERF_COUNTER, 1),
368 PERF_HW("perf:stalled-cycles-frontend", STALLED_CYCLES_FRONTEND,
369 CONTEXT_PERF_COUNTER, 1),
370 PERF_HW("perf:idle-cycles-frontend", STALLED_CYCLES_FRONTEND,
371 CONTEXT_PERF_COUNTER, 1),
372 PERF_HW("perf:stalled-cycles-backend", STALLED_CYCLES_BACKEND,
373 CONTEXT_PERF_COUNTER, 1),
374 PERF_HW("perf:idle-cycles-backend", STALLED_CYCLES_BACKEND,
375 CONTEXT_PERF_COUNTER, 1),
376 PERF_HW("perf:instructions", INSTRUCTIONS,
377 CONTEXT_PERF_COUNTER, 1),
378 PERF_HW("perf:cache-references", CACHE_REFERENCES,
379 CONTEXT_PERF_COUNTER, 1),
380 PERF_HW("perf:cache-misses", CACHE_MISSES,
381 CONTEXT_PERF_COUNTER, 1),
382 PERF_HW("perf:branch-instructions", BRANCH_INSTRUCTIONS,
383 CONTEXT_PERF_COUNTER, 1),
384 PERF_HW("perf:branches", BRANCH_INSTRUCTIONS,
385 CONTEXT_PERF_COUNTER, 1),
386 PERF_HW("perf:branch-misses", BRANCH_MISSES,
387 CONTEXT_PERF_COUNTER, 1),
388 PERF_HW("perf:bus-cycles", BUS_CYCLES,
389 CONTEXT_PERF_COUNTER, 1),
390
391 PERF_HW_CACHE("perf:L1-dcache", L1D,
392 CONTEXT_PERF_COUNTER, 1),
393 PERF_HW_CACHE("perf:L1-icache", L1I,
394 CONTEXT_PERF_COUNTER, 1),
395 PERF_HW_CACHE("perf:LLC", LL,
396 CONTEXT_PERF_COUNTER, 1),
397 PERF_HW_CACHE("perf:dTLB", DTLB,
398 CONTEXT_PERF_COUNTER, 1),
399 _PERF_HW_CACHE("perf:iTLB-loads", ITLB,
400 CONTEXT_PERF_COUNTER, READ, ACCESS, 1),
401 _PERF_HW_CACHE("perf:iTLB-load-misses", ITLB,
402 CONTEXT_PERF_COUNTER, READ, MISS, 1),
403 _PERF_HW_CACHE("perf:branch-loads", BPU,
404 CONTEXT_PERF_COUNTER, READ, ACCESS, 1),
405 _PERF_HW_CACHE("perf:branch-load-misses", BPU,
406 CONTEXT_PERF_COUNTER, READ, MISS, 1),
407
408 PERF_SW("perf:cpu-clock", CPU_CLOCK,
409 CONTEXT_PERF_COUNTER, 1),
410 PERF_SW("perf:task-clock", TASK_CLOCK,
411 CONTEXT_PERF_COUNTER, 1),
412 PERF_SW("perf:page-fault", PAGE_FAULTS,
413 CONTEXT_PERF_COUNTER, 1),
414 PERF_SW("perf:faults", PAGE_FAULTS,
415 CONTEXT_PERF_COUNTER, 1),
416 PERF_SW("perf:major-faults", PAGE_FAULTS_MAJ,
417 CONTEXT_PERF_COUNTER, 1),
418 PERF_SW("perf:minor-faults", PAGE_FAULTS_MIN,
419 CONTEXT_PERF_COUNTER, 1),
420 PERF_SW("perf:context-switches", CONTEXT_SWITCHES,
421 CONTEXT_PERF_COUNTER, 1),
422 PERF_SW("perf:cs", CONTEXT_SWITCHES,
423 CONTEXT_PERF_COUNTER, 1),
424 PERF_SW("perf:cpu-migrations", CPU_MIGRATIONS,
425 CONTEXT_PERF_COUNTER, 1),
426 PERF_SW("perf:migrations", CPU_MIGRATIONS,
427 CONTEXT_PERF_COUNTER, 1),
428 PERF_SW("perf:alignment-faults", ALIGNMENT_FAULTS,
429 CONTEXT_PERF_COUNTER, 1),
430 PERF_SW("perf:emulation-faults", EMULATION_FAULTS,
431 CONTEXT_PERF_COUNTER, 1),
432
b13d56d7 433 { NULL, -1 }, /* Closure */
90b9a268
DG
434};
435
aa3514e9
MD
436#undef PERF_HW_CACHE
437#undef _PERF_HW_CACHE
b13d56d7
MD
438#undef PERF_SW
439#undef PERF_HW
440
90b9a268 441/*
b13d56d7 442 * Context type for command line option parsing.
90b9a268 443 */
b13d56d7
MD
444struct ctx_type {
445 const struct ctx_opts *opt;
446 struct cds_list_head list;
90b9a268
DG
447};
448
449/*
450 * List of context type. Use to enable multiple context on a single command
451 * line entry.
452 */
453struct ctx_type_list {
454 struct cds_list_head head;
455} ctx_type_list = {
456 .head = CDS_LIST_HEAD_INIT(ctx_type_list.head),
457};
458
90b9a268
DG
459/*
460 * Pretty print context type.
461 */
462static void print_ctx_type(FILE *ofp)
463{
b13d56d7
MD
464 const char *indent = " ";
465 int indent_len = strlen(indent);
466 int len, i = 0;
90b9a268 467
76e3c5dd 468 fprintf(ofp, "%s", indent);
b13d56d7 469 len = indent_len;
90b9a268 470 while (ctx_opts[i].symbol != NULL) {
aa3514e9
MD
471 if (!ctx_opts[i].hide_help) {
472 if (len > indent_len) {
473 if (len + strlen(ctx_opts[i].symbol) + 2
474 >= PRINT_LINE_LEN) {
475 fprintf(ofp, ",\n");
476 fprintf(ofp, "%s", indent);
477 len = indent_len;
478 } else {
479 len += fprintf(ofp, ", ");
480 }
90b9a268 481 }
aa3514e9 482 len += fprintf(ofp, "%s", ctx_opts[i].symbol);
90b9a268
DG
483 }
484 i++;
485 }
90b9a268
DG
486}
487
d65106b1
DG
488/*
489 * usage
490 */
491static void usage(FILE *ofp)
492{
32a6298d 493 fprintf(ofp, "usage: lttng add-context -t TYPE [-k|-u] [OPTIONS]\n");
d65106b1 494 fprintf(ofp, "\n");
601d5acf
DG
495 fprintf(ofp, "If no channel is given (-c), the context is added to\n");
496 fprintf(ofp, "all channels.\n");
32a6298d 497 fprintf(ofp, "\n");
601d5acf 498 fprintf(ofp, "Otherwise the context is added only to the channel (-c).\n");
32a6298d
DG
499 fprintf(ofp, "\n");
500 fprintf(ofp, "Exactly one domain (-k or -u) must be specified.\n");
3301e740 501 fprintf(ofp, "\n");
d65106b1
DG
502 fprintf(ofp, "Options:\n");
503 fprintf(ofp, " -h, --help Show this help\n");
679b4943 504 fprintf(ofp, " --list-options Simple listing of options\n");
5eb00805
TD
505 fprintf(ofp, " -s, --session NAME Apply to session name\n");
506 fprintf(ofp, " -c, --channel NAME Apply to channel\n");
af87c45a 507 fprintf(ofp, " -k, --kernel Apply to the kernel tracer\n");
af87c45a 508 fprintf(ofp, " -u, --userspace Apply to the user-space tracer\n");
32a6298d
DG
509 fprintf(ofp, "\n");
510 fprintf(ofp, "Context:\n");
b13d56d7 511 fprintf(ofp, " -t, --type TYPE Context type. You can repeat that option on\n");
af87c45a
DG
512 fprintf(ofp, " the command line to specify multiple contexts at once.\n");
513 fprintf(ofp, " (--kernel preempts --userspace)\n");
b13d56d7 514 fprintf(ofp, " TYPE can be one of the strings below:\n");
90b9a268 515 print_ctx_type(ofp);
d65106b1 516 fprintf(ofp, "\n");
c455d428
FD
517 fprintf(ofp, "Note that the vpid, vppid and vtid context types represent the virtual process id,\n"
518 "virtual parent process id and virtual thread id as seen from the current execution context\n"
519 "as opposed to the pid, ppid and tid which are kernel internal data structures.\n\n");
90b9a268 520 fprintf(ofp, "Example:\n");
aa3514e9
MD
521 fprintf(ofp, "This command will add the context information 'prio' and two per-cpu\n"
522 "perf counters (hardware branch misses and cache misses), to all channels\n"
b13d56d7 523 "in the trace data output:\n");
aa3514e9 524 fprintf(ofp, "# lttng add-context -k -t prio -t perf:cpu:branch-misses -t perf:cpu:cache-misses\n");
d65106b1
DG
525 fprintf(ofp, "\n");
526}
527
90b9a268
DG
528/*
529 * Find context numerical value from string.
530 */
531static int find_ctx_type_idx(const char *opt)
532{
533 int ret = -1, i = 0;
534
535 while (ctx_opts[i].symbol != NULL) {
536 if (strcmp(opt, ctx_opts[i].symbol) == 0) {
537 ret = i;
538 goto end;
539 }
540 i++;
541 }
542
543end:
544 return ret;
545}
546
90b9a268
DG
547/*
548 * Add context to channel or event.
d65106b1 549 */
cd80958d 550static int add_context(char *session_name)
d65106b1 551{
89b72577 552 int ret = CMD_SUCCESS, warn = 0, success = 0;
7d29a247
DG
553 struct lttng_event_context context;
554 struct lttng_domain dom;
3301e740 555 struct ctx_type *type;
b13d56d7 556 char *ptr;
d65106b1 557
441c16a7
MD
558 memset(&context, 0, sizeof(context));
559 memset(&dom, 0, sizeof(dom));
560
cd80958d
DG
561 if (opt_kernel) {
562 dom.type = LTTNG_DOMAIN_KERNEL;
d78d6610 563 } else if (opt_userspace) {
55cc08a6 564 dom.type = LTTNG_DOMAIN_UST;
55cc08a6 565 } else {
3ecec76a 566 assert(0);
cd80958d
DG
567 }
568
569 handle = lttng_create_handle(session_name, &dom);
570 if (handle == NULL) {
af87c45a 571 ret = CMD_ERROR;
cd80958d
DG
572 goto error;
573 }
574
89b72577
JRJ
575 if (lttng_opt_mi) {
576 /* Open a contexts element */
577 ret = mi_lttng_writer_open_element(writer, config_element_contexts);
578 if (ret) {
579 goto error;
580 }
581 }
582
5eb00805 583 /* Iterate over all the context types given */
3301e740 584 cds_list_for_each_entry(type, &ctx_type_list.head, list) {
6775595e 585 context.ctx = (enum lttng_event_context_type) type->opt->ctx_type;
aa3514e9
MD
586 switch (context.ctx) {
587 case LTTNG_EVENT_CONTEXT_PERF_COUNTER:
588 case LTTNG_EVENT_CONTEXT_PERF_CPU_COUNTER:
589 case LTTNG_EVENT_CONTEXT_PERF_THREAD_COUNTER:
b13d56d7
MD
590 context.u.perf_counter.type = type->opt->u.perf.type;
591 context.u.perf_counter.config = type->opt->u.perf.config;
24546386
MD
592 strncpy(context.u.perf_counter.name, type->opt->symbol,
593 LTTNG_SYMBOL_NAME_LEN);
594 context.u.perf_counter.name[LTTNG_SYMBOL_NAME_LEN - 1] = '\0';
b13d56d7
MD
595 /* Replace : and - by _ */
596 while ((ptr = strchr(context.u.perf_counter.name, '-')) != NULL) {
597 *ptr = '_';
3301e740 598 }
b13d56d7
MD
599 while ((ptr = strchr(context.u.perf_counter.name, ':')) != NULL) {
600 *ptr = '_';
3301e740 601 }
aa3514e9
MD
602 break;
603 default:
604 break;
3301e740 605 }
55cc08a6
DG
606 DBG("Adding context...");
607
89b72577
JRJ
608 if (lttng_opt_mi) {
609 /* We leave context open the update the success of the command */
610 ret = mi_lttng_context(writer, &context, 1);
611 if (ret) {
612 ret = CMD_ERROR;
613 goto error;
614 }
615 }
616
601d5acf 617 ret = lttng_add_context(handle, &context, NULL, opt_channel_name);
55cc08a6 618 if (ret < 0) {
b58471ff 619 ERR("%s: %s", type->opt->symbol, lttng_strerror(ret));
d16c1a4c 620 warn = 1;
89b72577 621 success = 0;
d65106b1 622 } else {
601d5acf 623 if (opt_channel_name) {
b58471ff
DG
624 MSG("%s context %s added to channel %s",
625 opt_kernel ? "kernel" : "UST", type->opt->symbol,
626 opt_channel_name);
b58471ff
DG
627 } else {
628 MSG("%s context %s added to all channels",
629 opt_kernel ? "kernel" : "UST", type->opt->symbol)
630 }
89b72577
JRJ
631 success = 1;
632 }
633
634 if (lttng_opt_mi) {
635 /* Is the single operation a success ? */
636 ret = mi_lttng_writer_write_element_bool(writer,
637 mi_lttng_element_success, success);
638 if (ret) {
639 ret = CMD_ERROR;
640 goto error;
641 }
642
643 /* Close the context element */
644 ret = mi_lttng_writer_close_element(writer);
645 if (ret) {
646 ret = CMD_ERROR;
647 goto error;
648 }
649 }
650 }
651
652 if (lttng_opt_mi) {
653 /* Close contexts element */
654 ret = mi_lttng_writer_close_element(writer);
655 if (ret) {
656 goto error;
d65106b1 657 }
d65106b1
DG
658 }
659
af87c45a
DG
660 ret = CMD_SUCCESS;
661
d65106b1 662error:
cd80958d
DG
663 lttng_destroy_handle(handle);
664
d16c1a4c
DG
665 /*
666 * This means that at least one add_context failed and tells the user to
667 * look on stderr for error(s).
668 */
89b72577 669 if (!ret && warn) {
d16c1a4c
DG
670 ret = CMD_WARNING;
671 }
d65106b1
DG
672 return ret;
673}
674
675/*
5eb00805 676 * Add context to channel or event.
d65106b1
DG
677 */
678int cmd_add_context(int argc, const char **argv)
679{
89b72577
JRJ
680 int index, opt, ret = CMD_SUCCESS, command_ret = CMD_SUCCESS;
681 int success = 1;
d65106b1 682 static poptContext pc;
b13d56d7 683 struct ctx_type *type, *tmptype;
cd80958d 684 char *session_name = NULL;
d65106b1 685
636167b6
DG
686 if (argc < 2) {
687 usage(stderr);
5eb00805 688 ret = CMD_ERROR;
636167b6
DG
689 goto end;
690 }
691
d65106b1
DG
692 pc = poptGetContext(NULL, argc, argv, long_options, 0);
693 poptReadDefaultConfig(pc, 0);
694
695 while ((opt = poptGetNextOpt(pc)) != -1) {
696 switch (opt) {
697 case OPT_HELP:
5eb00805 698 usage(stdout);
d65106b1
DG
699 goto end;
700 case OPT_TYPE:
af87c45a
DG
701 /*
702 * Look up the index of opt_type in ctx_opts[] first, so we don't
703 * have to free(type) on failure.
704 */
6caa2bcc 705 index = find_ctx_type_idx(opt_type);
b13d56d7 706 if (index < 0) {
6caa2bcc 707 ERR("Unknown context type %s", opt_type);
5eb00805 708 ret = CMD_ERROR;
b13d56d7 709 goto end;
90b9a268 710 }
5eb00805 711
98cf2db1 712 type = zmalloc(sizeof(struct ctx_type));
5eb00805 713 if (type == NULL) {
6f04ed72 714 PERROR("malloc ctx_type");
5eb00805
TD
715 ret = CMD_FATAL;
716 goto end;
717 }
718
b13d56d7 719 type->opt = &ctx_opts[index];
109be0da 720 if (type->opt->symbol == NULL) {
6caa2bcc 721 ERR("Unknown context type %s", opt_type);
5eb00805
TD
722 free(type);
723 ret = CMD_ERROR;
724 goto end;
90b9a268 725 } else {
31746f93 726 cds_list_add_tail(&type->list, &ctx_type_list.head);
90b9a268 727 }
d65106b1 728 break;
eeac7d46
MD
729 case OPT_USERSPACE:
730 opt_userspace = 1;
eeac7d46 731 break;
679b4943
SM
732 case OPT_LIST_OPTIONS:
733 list_cmd_options(stdout, long_options);
679b4943 734 goto end;
d65106b1
DG
735 default:
736 usage(stderr);
737 ret = CMD_UNDEFINED;
738 goto end;
739 }
740 }
741
3ecec76a
PP
742 ret = print_missing_or_multiple_domains(opt_kernel + opt_userspace);
743
744 if (ret) {
745 ret = CMD_ERROR;
746 goto end;
747 }
748
ae856491
DG
749 if (!opt_type) {
750 ERR("Missing mandatory -t TYPE");
751 usage(stderr);
752 ret = CMD_ERROR;
753 goto end;
754 }
755
cd80958d
DG
756 if (!opt_session_name) {
757 session_name = get_session_name();
758 if (session_name == NULL) {
5eb00805 759 ret = CMD_ERROR;
cd80958d
DG
760 goto end;
761 }
762 } else {
763 session_name = opt_session_name;
764 }
765
89b72577
JRJ
766 /* Mi check */
767 if (lttng_opt_mi) {
768 writer = mi_lttng_writer_create(fileno(stdout), lttng_opt_mi);
769 if (!writer) {
770 ret = -LTTNG_ERR_NOMEM;
771 goto end;
772 }
773
774 /* Open command element */
775 ret = mi_lttng_writer_command_open(writer,
776 mi_lttng_element_command_add_context);
777 if (ret) {
778 ret = CMD_ERROR;
779 goto end;
780 }
781
782 /* Open output element */
783 ret = mi_lttng_writer_open_element(writer,
784 mi_lttng_element_command_output);
785 if (ret) {
786 ret = CMD_ERROR;
787 goto end;
788 }
789 }
790
791 command_ret = add_context(session_name);
792 if (command_ret) {
793 success = 0;
794 }
795
796 /* Mi closing */
797 if (lttng_opt_mi) {
798 /* Close output element */
799 ret = mi_lttng_writer_close_element(writer);
800 if (ret) {
801 ret = CMD_ERROR;
802 goto end;
803 }
3301e740 804
89b72577
JRJ
805 /* Success ? */
806 ret = mi_lttng_writer_write_element_bool(writer,
807 mi_lttng_element_command_success, success);
808 if (ret) {
809 ret = CMD_ERROR;
810 goto end;
811 }
812
813 /* Command element close */
814 ret = mi_lttng_writer_command_close(writer);
815 if (ret) {
816 ret = CMD_ERROR;
817 goto end;
818 }
819 }
820
821end:
1256f150
DT
822 if (!opt_session_name) {
823 free(session_name);
824 }
825
89b72577
JRJ
826 /* Mi clean-up */
827 if (writer && mi_lttng_writer_destroy(writer)) {
828 /* Preserve original error code */
829 ret = ret ? ret : LTTNG_ERR_MI_IO_FAIL;
830 }
831
3301e740 832 /* Cleanup allocated memory */
b13d56d7 833 cds_list_for_each_entry_safe(type, tmptype, &ctx_type_list.head, list) {
3301e740
DG
834 free(type);
835 }
836
89b72577
JRJ
837 /* Overwrite ret if an error occurred during add_context() */
838 ret = command_ret ? command_ret : ret;
839
ca1c3607 840 poptFreeContext(pc);
d65106b1
DG
841 return ret;
842}
This page took 0.078617 seconds and 4 git commands to generate.