Port: Remove _GNU_SOURCE, defined in config.h
[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
6c1c0768 18#define _LGPL_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>
3ecec76a 27#include <assert.h>
d65106b1 28
3301e740
DG
29#include <urcu/list.h>
30
89b72577
JRJ
31#include <common/mi-lttng.h>
32
c399183f 33#include "../command.h"
d65106b1 34
b13d56d7
MD
35#define PRINT_LINE_LEN 80
36
d65106b1 37static char *opt_channel_name;
5440dc42 38static char *opt_session_name;
55cc08a6 39static int opt_kernel;
d65106b1 40static int opt_userspace;
d78d6610 41static char *opt_type;
89b72577 42
d65106b1
DG
43enum {
44 OPT_HELP = 1,
45 OPT_TYPE,
eeac7d46 46 OPT_USERSPACE,
679b4943 47 OPT_LIST_OPTIONS,
d65106b1
DG
48};
49
cd80958d 50static struct lttng_handle *handle;
89b72577 51static struct mi_writer *writer;
cd80958d 52
90b9a268
DG
53/*
54 * Taken from the LTTng ABI
55 */
56enum context_type {
57 CONTEXT_PID = 0,
aa3514e9 58 CONTEXT_PERF_COUNTER = 1, /* Backward compat. */
95da1297 59 CONTEXT_PROCNAME = 2,
90b9a268
DG
60 CONTEXT_PRIO = 3,
61 CONTEXT_NICE = 4,
62 CONTEXT_VPID = 5,
63 CONTEXT_TID = 6,
64 CONTEXT_VTID = 7,
65 CONTEXT_PPID = 8,
66 CONTEXT_VPPID = 9,
9197c5c4 67 CONTEXT_PTHREAD_ID = 10,
54773d68 68 CONTEXT_HOSTNAME = 11,
7c612c2e 69 CONTEXT_IP = 12,
aa3514e9
MD
70 CONTEXT_PERF_CPU_COUNTER = 13,
71 CONTEXT_PERF_THREAD_COUNTER = 14,
3301e740
DG
72};
73
90b9a268
DG
74/*
75 * Taken from the Perf ABI (all enum perf_*)
76 */
77enum perf_type {
78 PERF_TYPE_HARDWARE = 0,
79 PERF_TYPE_SOFTWARE = 1,
b13d56d7 80 PERF_TYPE_HW_CACHE = 3,
3301e740
DG
81};
82
90b9a268 83enum perf_count_hard {
b13d56d7
MD
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,
90b9a268
DG
93};
94
95enum 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,
3301e740
DG
105};
106
b13d56d7
MD
107/*
108 * Generalized hardware cache events:
109 *
110 * { L1-D, L1-I, LLC, ITLB, DTLB, BPU } x
111 * { read, write, prefetch } x
112 * { accesses, misses }
113 */
114enum 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,
121
122 PERF_COUNT_HW_CACHE_MAX, /* non-ABI */
123};
124
125enum 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,
129
130 PERF_COUNT_HW_CACHE_OP_MAX, /* non-ABI */
131};
132
133enum perf_hw_cache_op_result_id {
134 PERF_COUNT_HW_CACHE_RESULT_ACCESS = 0,
135 PERF_COUNT_HW_CACHE_RESULT_MISS = 1,
136
137 PERF_COUNT_HW_CACHE_RESULT_MAX, /* non-ABI */
138};
139
d65106b1
DG
140static struct poptOption long_options[] = {
141 /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
142 {"help", 'h', POPT_ARG_NONE, 0, OPT_HELP, 0, 0},
5440dc42 143 {"session", 's', POPT_ARG_STRING, &opt_session_name, 0, 0, 0},
d65106b1 144 {"channel", 'c', POPT_ARG_STRING, &opt_channel_name, 0, 0, 0},
d65106b1 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 */
aa3514e9 155#define PERF_HW(optstr, name, type, hide) \
b13d56d7 156 { \
aa3514e9 157 optstr, type, hide, \
b13d56d7
MD
158 .u.perf = { PERF_TYPE_HARDWARE, PERF_COUNT_HW_##name, },\
159 }
90b9a268 160
aa3514e9 161#define PERF_SW(optstr, name, type, hide) \
b13d56d7 162 { \
aa3514e9 163 optstr, type, hide, \
b13d56d7
MD
164 .u.perf = { PERF_TYPE_SOFTWARE, PERF_COUNT_SW_##name, },\
165 }
90b9a268 166
aa3514e9 167#define _PERF_HW_CACHE(optstr, name, type, op, result, hide) \
b13d56d7 168 { \
aa3514e9 169 optstr, type, hide, \
b13d56d7
MD
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
aa3514e9
MD
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, \
182 READ, MISS, hide), \
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)
b13d56d7
MD
191
192static
193const struct ctx_opts {
90b9a268 194 char *symbol;
b13d56d7 195 enum context_type ctx_type;
aa3514e9 196 int hide_help; /* Hide from --help */
b13d56d7
MD
197 union {
198 struct {
199 uint32_t type;
200 uint64_t config;
201 } perf;
202 } u;
203} ctx_opts[] = {
204 { "pid", CONTEXT_PID },
95da1297 205 { "procname", CONTEXT_PROCNAME },
b13d56d7
MD
206 { "prio", CONTEXT_PRIO },
207 { "nice", CONTEXT_NICE },
208 { "vpid", CONTEXT_VPID },
209 { "tid", CONTEXT_TID },
9197c5c4 210 { "pthread_id", CONTEXT_PTHREAD_ID },
b13d56d7
MD
211 { "vtid", CONTEXT_VTID },
212 { "ppid", CONTEXT_PPID },
213 { "vppid", CONTEXT_VPPID },
54773d68 214 { "hostname", CONTEXT_HOSTNAME },
7c612c2e 215 { "ip", CONTEXT_IP },
aa3514e9 216
b13d56d7 217 /* Perf options */
aa3514e9
MD
218
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),
246
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),
263
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),
288
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),
316
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),
333
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),
358
359 /*
360 * Perf per-CPU counters, backward compatibilty for names.
361 * Hidden from help listing.
362 */
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),
389
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),
406
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),
431
b13d56d7 432 { NULL, -1 }, /* Closure */
90b9a268
DG
433};
434
aa3514e9
MD
435#undef PERF_HW_CACHE
436#undef _PERF_HW_CACHE
b13d56d7
MD
437#undef PERF_SW
438#undef PERF_HW
439
90b9a268 440/*
b13d56d7 441 * Context type for command line option parsing.
90b9a268 442 */
b13d56d7
MD
443struct ctx_type {
444 const struct ctx_opts *opt;
445 struct cds_list_head list;
90b9a268
DG
446};
447
448/*
449 * List of context type. Use to enable multiple context on a single command
450 * line entry.
451 */
452struct ctx_type_list {
453 struct cds_list_head head;
454} ctx_type_list = {
455 .head = CDS_LIST_HEAD_INIT(ctx_type_list.head),
456};
457
90b9a268
DG
458/*
459 * Pretty print context type.
460 */
461static void print_ctx_type(FILE *ofp)
462{
b13d56d7
MD
463 const char *indent = " ";
464 int indent_len = strlen(indent);
465 int len, i = 0;
90b9a268 466
76e3c5dd 467 fprintf(ofp, "%s", indent);
b13d56d7 468 len = indent_len;
90b9a268 469 while (ctx_opts[i].symbol != NULL) {
aa3514e9
MD
470 if (!ctx_opts[i].hide_help) {
471 if (len > indent_len) {
472 if (len + strlen(ctx_opts[i].symbol) + 2
473 >= PRINT_LINE_LEN) {
474 fprintf(ofp, ",\n");
475 fprintf(ofp, "%s", indent);
476 len = indent_len;
477 } else {
478 len += fprintf(ofp, ", ");
479 }
90b9a268 480 }
aa3514e9 481 len += fprintf(ofp, "%s", ctx_opts[i].symbol);
90b9a268
DG
482 }
483 i++;
484 }
90b9a268
DG
485}
486
d65106b1
DG
487/*
488 * usage
489 */
490static void usage(FILE *ofp)
491{
32a6298d 492 fprintf(ofp, "usage: lttng add-context -t TYPE [-k|-u] [OPTIONS]\n");
d65106b1 493 fprintf(ofp, "\n");
601d5acf
DG
494 fprintf(ofp, "If no channel is given (-c), the context is added to\n");
495 fprintf(ofp, "all channels.\n");
32a6298d 496 fprintf(ofp, "\n");
601d5acf 497 fprintf(ofp, "Otherwise the context is added only to the channel (-c).\n");
32a6298d
DG
498 fprintf(ofp, "\n");
499 fprintf(ofp, "Exactly one domain (-k or -u) must be specified.\n");
3301e740 500 fprintf(ofp, "\n");
d65106b1
DG
501 fprintf(ofp, "Options:\n");
502 fprintf(ofp, " -h, --help Show this help\n");
679b4943 503 fprintf(ofp, " --list-options Simple listing of options\n");
5eb00805
TD
504 fprintf(ofp, " -s, --session NAME Apply to session name\n");
505 fprintf(ofp, " -c, --channel NAME Apply to channel\n");
af87c45a 506 fprintf(ofp, " -k, --kernel Apply to the kernel tracer\n");
af87c45a 507 fprintf(ofp, " -u, --userspace Apply to the user-space tracer\n");
32a6298d
DG
508 fprintf(ofp, "\n");
509 fprintf(ofp, "Context:\n");
b13d56d7 510 fprintf(ofp, " -t, --type TYPE Context type. You can repeat that option on\n");
af87c45a
DG
511 fprintf(ofp, " the command line to specify multiple contexts at once.\n");
512 fprintf(ofp, " (--kernel preempts --userspace)\n");
b13d56d7 513 fprintf(ofp, " TYPE can be one of the strings below:\n");
90b9a268 514 print_ctx_type(ofp);
d65106b1 515 fprintf(ofp, "\n");
c455d428
FD
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");
90b9a268 519 fprintf(ofp, "Example:\n");
aa3514e9
MD
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"
b13d56d7 522 "in the trace data output:\n");
aa3514e9 523 fprintf(ofp, "# lttng add-context -k -t prio -t perf:cpu:branch-misses -t perf:cpu:cache-misses\n");
d65106b1
DG
524 fprintf(ofp, "\n");
525}
526
90b9a268
DG
527/*
528 * Find context numerical value from string.
529 */
530static int find_ctx_type_idx(const char *opt)
531{
532 int ret = -1, i = 0;
533
534 while (ctx_opts[i].symbol != NULL) {
535 if (strcmp(opt, ctx_opts[i].symbol) == 0) {
536 ret = i;
537 goto end;
538 }
539 i++;
540 }
541
542end:
543 return ret;
544}
545
90b9a268
DG
546/*
547 * Add context to channel or event.
d65106b1 548 */
cd80958d 549static int add_context(char *session_name)
d65106b1 550{
89b72577 551 int ret = CMD_SUCCESS, warn = 0, success = 0;
7d29a247
DG
552 struct lttng_event_context context;
553 struct lttng_domain dom;
3301e740 554 struct ctx_type *type;
b13d56d7 555 char *ptr;
d65106b1 556
441c16a7
MD
557 memset(&context, 0, sizeof(context));
558 memset(&dom, 0, sizeof(dom));
559
cd80958d
DG
560 if (opt_kernel) {
561 dom.type = LTTNG_DOMAIN_KERNEL;
d78d6610 562 } else if (opt_userspace) {
55cc08a6 563 dom.type = LTTNG_DOMAIN_UST;
55cc08a6 564 } else {
3ecec76a 565 assert(0);
cd80958d
DG
566 }
567
568 handle = lttng_create_handle(session_name, &dom);
569 if (handle == NULL) {
af87c45a 570 ret = CMD_ERROR;
cd80958d
DG
571 goto error;
572 }
573
89b72577
JRJ
574 if (lttng_opt_mi) {
575 /* Open a contexts element */
576 ret = mi_lttng_writer_open_element(writer, config_element_contexts);
577 if (ret) {
578 goto error;
579 }
580 }
581
5eb00805 582 /* Iterate over all the context types given */
3301e740 583 cds_list_for_each_entry(type, &ctx_type_list.head, list) {
6775595e 584 context.ctx = (enum lttng_event_context_type) type->opt->ctx_type;
aa3514e9
MD
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:
b13d56d7
MD
589 context.u.perf_counter.type = type->opt->u.perf.type;
590 context.u.perf_counter.config = type->opt->u.perf.config;
24546386
MD
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';
b13d56d7
MD
594 /* Replace : and - by _ */
595 while ((ptr = strchr(context.u.perf_counter.name, '-')) != NULL) {
596 *ptr = '_';
3301e740 597 }
b13d56d7
MD
598 while ((ptr = strchr(context.u.perf_counter.name, ':')) != NULL) {
599 *ptr = '_';
3301e740 600 }
aa3514e9
MD
601 break;
602 default:
603 break;
3301e740 604 }
55cc08a6
DG
605 DBG("Adding context...");
606
89b72577
JRJ
607 if (lttng_opt_mi) {
608 /* We leave context open the update the success of the command */
609 ret = mi_lttng_context(writer, &context, 1);
610 if (ret) {
611 ret = CMD_ERROR;
612 goto error;
613 }
614 }
615
601d5acf 616 ret = lttng_add_context(handle, &context, NULL, opt_channel_name);
55cc08a6 617 if (ret < 0) {
b58471ff 618 ERR("%s: %s", type->opt->symbol, lttng_strerror(ret));
d16c1a4c 619 warn = 1;
89b72577 620 success = 0;
d65106b1 621 } else {
601d5acf 622 if (opt_channel_name) {
b58471ff
DG
623 MSG("%s context %s added to channel %s",
624 opt_kernel ? "kernel" : "UST", type->opt->symbol,
625 opt_channel_name);
b58471ff
DG
626 } else {
627 MSG("%s context %s added to all channels",
628 opt_kernel ? "kernel" : "UST", type->opt->symbol)
629 }
89b72577
JRJ
630 success = 1;
631 }
632
633 if (lttng_opt_mi) {
634 /* Is the single operation a success ? */
635 ret = mi_lttng_writer_write_element_bool(writer,
636 mi_lttng_element_success, success);
637 if (ret) {
638 ret = CMD_ERROR;
639 goto error;
640 }
641
642 /* Close the context element */
643 ret = mi_lttng_writer_close_element(writer);
644 if (ret) {
645 ret = CMD_ERROR;
646 goto error;
647 }
648 }
649 }
650
651 if (lttng_opt_mi) {
652 /* Close contexts element */
653 ret = mi_lttng_writer_close_element(writer);
654 if (ret) {
655 goto error;
d65106b1 656 }
d65106b1
DG
657 }
658
af87c45a
DG
659 ret = CMD_SUCCESS;
660
d65106b1 661error:
cd80958d
DG
662 lttng_destroy_handle(handle);
663
d16c1a4c
DG
664 /*
665 * This means that at least one add_context failed and tells the user to
666 * look on stderr for error(s).
667 */
89b72577 668 if (!ret && warn) {
d16c1a4c
DG
669 ret = CMD_WARNING;
670 }
d65106b1
DG
671 return ret;
672}
673
674/*
5eb00805 675 * Add context to channel or event.
d65106b1
DG
676 */
677int cmd_add_context(int argc, const char **argv)
678{
89b72577
JRJ
679 int index, opt, ret = CMD_SUCCESS, command_ret = CMD_SUCCESS;
680 int success = 1;
d65106b1 681 static poptContext pc;
b13d56d7 682 struct ctx_type *type, *tmptype;
cd80958d 683 char *session_name = NULL;
d65106b1 684
636167b6
DG
685 if (argc < 2) {
686 usage(stderr);
5eb00805 687 ret = CMD_ERROR;
636167b6
DG
688 goto end;
689 }
690
d65106b1
DG
691 pc = poptGetContext(NULL, argc, argv, long_options, 0);
692 poptReadDefaultConfig(pc, 0);
693
694 while ((opt = poptGetNextOpt(pc)) != -1) {
695 switch (opt) {
696 case OPT_HELP:
5eb00805 697 usage(stdout);
d65106b1
DG
698 goto end;
699 case OPT_TYPE:
af87c45a
DG
700 /*
701 * Look up the index of opt_type in ctx_opts[] first, so we don't
702 * have to free(type) on failure.
703 */
6caa2bcc 704 index = find_ctx_type_idx(opt_type);
b13d56d7 705 if (index < 0) {
6caa2bcc 706 ERR("Unknown context type %s", opt_type);
5eb00805 707 ret = CMD_ERROR;
b13d56d7 708 goto end;
90b9a268 709 }
5eb00805 710
98cf2db1 711 type = zmalloc(sizeof(struct ctx_type));
5eb00805 712 if (type == NULL) {
6f04ed72 713 PERROR("malloc ctx_type");
5eb00805
TD
714 ret = CMD_FATAL;
715 goto end;
716 }
717
b13d56d7 718 type->opt = &ctx_opts[index];
109be0da 719 if (type->opt->symbol == NULL) {
6caa2bcc 720 ERR("Unknown context type %s", opt_type);
5eb00805
TD
721 free(type);
722 ret = CMD_ERROR;
723 goto end;
90b9a268 724 } else {
31746f93 725 cds_list_add_tail(&type->list, &ctx_type_list.head);
90b9a268 726 }
d65106b1 727 break;
eeac7d46
MD
728 case OPT_USERSPACE:
729 opt_userspace = 1;
eeac7d46 730 break;
679b4943
SM
731 case OPT_LIST_OPTIONS:
732 list_cmd_options(stdout, long_options);
679b4943 733 goto end;
d65106b1
DG
734 default:
735 usage(stderr);
736 ret = CMD_UNDEFINED;
737 goto end;
738 }
739 }
740
3ecec76a
PP
741 ret = print_missing_or_multiple_domains(opt_kernel + opt_userspace);
742
743 if (ret) {
744 ret = CMD_ERROR;
745 goto end;
746 }
747
ae856491
DG
748 if (!opt_type) {
749 ERR("Missing mandatory -t TYPE");
750 usage(stderr);
751 ret = CMD_ERROR;
752 goto end;
753 }
754
cd80958d
DG
755 if (!opt_session_name) {
756 session_name = get_session_name();
757 if (session_name == NULL) {
5eb00805 758 ret = CMD_ERROR;
cd80958d
DG
759 goto end;
760 }
761 } else {
762 session_name = opt_session_name;
763 }
764
89b72577
JRJ
765 /* Mi check */
766 if (lttng_opt_mi) {
767 writer = mi_lttng_writer_create(fileno(stdout), lttng_opt_mi);
768 if (!writer) {
769 ret = -LTTNG_ERR_NOMEM;
770 goto end;
771 }
772
773 /* Open command element */
774 ret = mi_lttng_writer_command_open(writer,
775 mi_lttng_element_command_add_context);
776 if (ret) {
777 ret = CMD_ERROR;
778 goto end;
779 }
780
781 /* Open output element */
782 ret = mi_lttng_writer_open_element(writer,
783 mi_lttng_element_command_output);
784 if (ret) {
785 ret = CMD_ERROR;
786 goto end;
787 }
788 }
789
790 command_ret = add_context(session_name);
791 if (command_ret) {
792 success = 0;
793 }
794
795 /* Mi closing */
796 if (lttng_opt_mi) {
797 /* Close output element */
798 ret = mi_lttng_writer_close_element(writer);
799 if (ret) {
800 ret = CMD_ERROR;
801 goto end;
802 }
3301e740 803
89b72577
JRJ
804 /* Success ? */
805 ret = mi_lttng_writer_write_element_bool(writer,
806 mi_lttng_element_command_success, success);
807 if (ret) {
808 ret = CMD_ERROR;
809 goto end;
810 }
811
812 /* Command element close */
813 ret = mi_lttng_writer_command_close(writer);
814 if (ret) {
815 ret = CMD_ERROR;
816 goto end;
817 }
818 }
819
820end:
1256f150
DT
821 if (!opt_session_name) {
822 free(session_name);
823 }
824
89b72577
JRJ
825 /* Mi clean-up */
826 if (writer && mi_lttng_writer_destroy(writer)) {
827 /* Preserve original error code */
828 ret = ret ? ret : LTTNG_ERR_MI_IO_FAIL;
829 }
830
3301e740 831 /* Cleanup allocated memory */
b13d56d7 832 cds_list_for_each_entry_safe(type, tmptype, &ctx_type_list.head, list) {
3301e740
DG
833 free(type);
834 }
835
89b72577
JRJ
836 /* Overwrite ret if an error occurred during add_context() */
837 ret = command_ret ? command_ret : ret;
838
ca1c3607 839 poptFreeContext(pc);
d65106b1
DG
840 return ret;
841}
This page took 0.092595 seconds and 5 git commands to generate.