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