From: David Goulet Date: Wed, 29 Jun 2011 21:23:26 +0000 (-0400) Subject: Add kernel context support X-Git-Tag: v2.0-pre1~68 X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=commitdiff_plain;h=d65106b1011efccf8fa5f9d7c8f2dfb0de38f5e8 Add kernel context support At this point, all context types and perf IDs are hardcoded in the usage function of the add-context command. Future works will remove them and port them into the code tree. Signed-off-by: David Goulet --- diff --git a/include/lttng/lttng.h b/include/lttng/lttng.h index a8b7ac09a..d7799780a 100644 --- a/include/lttng/lttng.h +++ b/include/lttng/lttng.h @@ -44,6 +44,35 @@ enum lttng_event_type { LTTNG_EVENT_FUNCTION, }; +/* Kernel context possible type */ +enum lttng_kernel_context_type { + LTTNG_KERNEL_CONTEXT_PID = 0, + LTTNG_KERNEL_CONTEXT_PERF_COUNTER = 1, + LTTNG_KERNEL_CONTEXT_COMM = 2, + LTTNG_KERNEL_CONTEXT_PRIO = 3, + LTTNG_KERNEL_CONTEXT_NICE = 4, + LTTNG_KERNEL_CONTEXT_VPID = 5, + LTTNG_KERNEL_CONTEXT_TID = 6, + LTTNG_KERNEL_CONTEXT_VTID = 7, + LTTNG_KERNEL_CONTEXT_PPID = 8, + LTTNG_KERNEL_CONTEXT_VPPID = 9, +}; + +/* Perf counter attributes */ +struct lttng_kernel_perf_counter_ctx { + uint32_t type; + uint64_t config; + char name[LTTNG_SYMBOL_NAME_LEN]; +}; + +/* Event/Channel context */ +struct lttng_kernel_context { + enum lttng_kernel_context_type ctx; + union { + struct lttng_kernel_perf_counter_ctx perf_counter; + } u; +}; + /* * Either addr is used or symbol_name and offset. */ @@ -129,6 +158,9 @@ extern int lttng_stop_tracing(char *session_name); /* * LTTng Kernel tracer control */ +extern int lttng_kernel_add_context(struct lttng_kernel_context *ctx, + char *event_name, char *channel_name); + extern int lttng_kernel_create_channel(struct lttng_channel *chan); extern int lttng_kernel_enable_event(struct lttng_event *ev, char *channel_name); diff --git a/libkernelctl/libkernelctl.c b/libkernelctl/libkernelctl.c index f51618d1e..25cc8c1f6 100644 --- a/libkernelctl/libkernelctl.c +++ b/libkernelctl/libkernelctl.c @@ -22,6 +22,11 @@ #include "kernel-ioctl.h" #include "libkernelctl.h" +int kernctl_add_context(int fd, struct lttng_kernel_context *ctx) +{ + return ioctl(fd, LTTNG_KERNEL_CONTEXT, ctx); +} + int kernctl_buffer_flush(int fd) { return ioctl(fd, RING_BUFFER_FLUSH); diff --git a/libkernelctl/libkernelctl.h b/libkernelctl/libkernelctl.h index 930cb892e..b5274d983 100644 --- a/libkernelctl/libkernelctl.h +++ b/libkernelctl/libkernelctl.h @@ -24,6 +24,7 @@ #include "lttng-kernel.h" +int kernctl_add_context(int fd, struct lttng_kernel_context *ctx); int kernctl_buffer_flush(int fd); int kernctl_create_channel(int fd, struct lttng_channel_attr *chops); int kernctl_create_event(int fd, struct lttng_kernel_event *ev); diff --git a/liblttngctl/liblttngctl.c b/liblttngctl/liblttngctl.c index cad4d735e..31693942d 100644 --- a/liblttngctl/liblttngctl.c +++ b/liblttngctl/liblttngctl.c @@ -251,6 +251,24 @@ int lttng_stop_tracing(char *session_name) * BEGIN Kernel control API */ +/* + * lttng_kernel_add_context + */ +int lttng_kernel_add_context(struct lttng_kernel_context *ctx, + char *event_name, char *channel_name) +{ + if (strlen(channel_name) != 0) { + strncpy(lsm.u.context.channel_name, channel_name, NAME_MAX); + } + + if (strlen(event_name) != 0) { + strncpy(lsm.u.context.event_name, event_name, NAME_MAX); + } + + memcpy(&lsm.u.context.ctx, ctx, sizeof(struct lttng_kernel_context)); + return ask_sessiond(LTTNG_KERNEL_ADD_CONTEXT, NULL); +} + /* * lttng_kernel_enable_event */ diff --git a/liblttsessiondcomm/liblttsessiondcomm.c b/liblttsessiondcomm/liblttsessiondcomm.c index ea5b68f9f..d608e86dc 100644 --- a/liblttsessiondcomm/liblttsessiondcomm.c +++ b/liblttsessiondcomm/liblttsessiondcomm.c @@ -54,6 +54,7 @@ static const char *lttcomm_readable_code[] = { [ LTTCOMM_ERR_INDEX(LTTCOMM_KERN_CHAN_NOT_FOUND) ] = "Kernel channel not found", [ LTTCOMM_ERR_INDEX(LTTCOMM_KERN_CHAN_DISABLE_FAIL) ] = "Disable kernel channel failed", [ LTTCOMM_ERR_INDEX(LTTCOMM_KERN_CHAN_ENABLE_FAIL) ] = "Enable kernel channel failed", + [ LTTCOMM_ERR_INDEX(LTTCOMM_KERN_CONTEXT_FAIL) ] = "Add kernel context failed", [ LTTCOMM_ERR_INDEX(LTTCOMM_KERN_ENABLE_FAIL) ] = "Enable kernel event failed", [ LTTCOMM_ERR_INDEX(LTTCOMM_KERN_DISABLE_FAIL) ] = "Disable kernel event failed", [ LTTCOMM_ERR_INDEX(LTTCOMM_KERN_META_FAIL) ] = "Opening metadata failed", @@ -78,7 +79,7 @@ static const char *lttcomm_readable_code[] = { [ LTTCOMM_ERR_INDEX(KCONSUMERD_SPLICE_EINVAL) ] = "Kconsumerd splice EINVAL", [ LTTCOMM_ERR_INDEX(KCONSUMERD_SPLICE_ENOMEM) ] = "Kconsumerd splice ENOMEM", [ LTTCOMM_ERR_INDEX(KCONSUMERD_SPLICE_ESPIPE) ] = "Kconsumerd splice ESPIPE", - [ LTTCOMM_ERR_INDEX(LTTCOMM_NO_EVENT) ] = "No event found", + [ LTTCOMM_ERR_INDEX(LTTCOMM_NO_EVENT) ] = "Event not found", }; /* diff --git a/liblttsessiondcomm/liblttsessiondcomm.h b/liblttsessiondcomm/liblttsessiondcomm.h index 2fb6de069..a2185f911 100644 --- a/liblttsessiondcomm/liblttsessiondcomm.h +++ b/liblttsessiondcomm/liblttsessiondcomm.h @@ -42,6 +42,7 @@ enum lttcomm_sessiond_command { /* Tracer context command */ + LTTNG_KERNEL_ADD_CONTEXT, LTTNG_KERNEL_CREATE_CHANNEL, LTTNG_KERNEL_DISABLE_CHANNEL, LTTNG_KERNEL_DISABLE_EVENT, @@ -89,6 +90,7 @@ enum lttcomm_return_code { LTTCOMM_KERN_CHAN_NOT_FOUND, /* Kernel channel not found */ LTTCOMM_KERN_CHAN_DISABLE_FAIL, /* Kernel disable channel failed */ LTTCOMM_KERN_CHAN_ENABLE_FAIL, /* Kernel enable channel failed */ + LTTCOMM_KERN_CONTEXT_FAIL, /* Kernel add context failed */ LTTCOMM_KERN_ENABLE_FAIL, /* Kernel enable event failed */ LTTCOMM_KERN_DISABLE_FAIL, /* Kernel disable event failed */ LTTCOMM_KERN_META_FAIL, /* Kernel open metadata failed */ @@ -139,6 +141,12 @@ struct lttcomm_session_msg { struct { struct lttng_channel chan; } channel; + /* Context */ + struct { + char channel_name[NAME_MAX]; + char event_name[NAME_MAX]; + struct lttng_kernel_context ctx; + } context; } u; }; diff --git a/ltt-sessiond/kernel-ctl.c b/ltt-sessiond/kernel-ctl.c index e42ab872e..95463aa50 100644 --- a/ltt-sessiond/kernel-ctl.c +++ b/ltt-sessiond/kernel-ctl.c @@ -29,6 +29,68 @@ #include "libkernelctl.h" #include "kernel-ctl.h" +/* + * kernel_add_channel_context + * + * Add context on a kernel channel. + */ +int kernel_add_channel_context(struct ltt_kernel_channel *chan, + struct lttng_kernel_context *ctx) +{ + int ret; + + DBG("Adding context to channel %s", chan->channel->name); + ret = kernctl_add_context(chan->fd, ctx); + if (ret < 0) { + perror("add context ioctl"); + goto error; + } + + chan->ctx = malloc(sizeof(struct lttng_kernel_context)); + if (chan->ctx == NULL) { + perror("malloc event context"); + goto error; + } + + memcpy(chan->ctx, ctx, sizeof(struct lttng_kernel_context)); + + return 0; + +error: + return ret; +} + +/* + * kernel_add_event_context + * + * Add context on a kernel event. + */ +int kernel_add_event_context(struct ltt_kernel_event *event, + struct lttng_kernel_context *ctx) +{ + int ret; + + DBG("Adding context to event %s", event->event->name); + ret = kernctl_add_context(event->fd, ctx); + if (ret < 0) { + perror("add context ioctl"); + goto error; + } + + event->ctx = malloc(sizeof(struct lttng_kernel_context)); + if (event->ctx == NULL) { + perror("malloc event context"); + goto error; + } + + memcpy(event->ctx, ctx, sizeof(struct lttng_kernel_context)); + + return 0; + +error: + return ret; +} + /* * kernel_create_session * diff --git a/ltt-sessiond/kernel-ctl.h b/ltt-sessiond/kernel-ctl.h index 1f8993707..cb9ed043c 100644 --- a/ltt-sessiond/kernel-ctl.h +++ b/ltt-sessiond/kernel-ctl.h @@ -30,6 +30,10 @@ */ #define KERNEL_EVENT_LIST_SIZE 2000 +int kernel_add_channel_context(struct ltt_kernel_channel *chan, + struct lttng_kernel_context *ctx); +int kernel_add_event_context(struct ltt_kernel_event *event, + struct lttng_kernel_context *ctx); int kernel_create_session(struct ltt_session *session, int tracer_fd); int kernel_create_channel(struct ltt_kernel_session *session, struct lttng_channel *chan); int kernel_create_event(struct lttng_event *ev, struct ltt_kernel_channel *channel); diff --git a/ltt-sessiond/main.c b/ltt-sessiond/main.c index 01e75cbb2..cdeb00911 100644 --- a/ltt-sessiond/main.c +++ b/ltt-sessiond/main.c @@ -803,6 +803,7 @@ static int process_client_msg(struct command_ctx *cmd_ctx) * Check kernel command for kernel session. */ switch (cmd_ctx->lsm->cmd_type) { + case LTTNG_KERNEL_ADD_CONTEXT: case LTTNG_KERNEL_CREATE_CHANNEL: case LTTNG_KERNEL_DISABLE_ALL_EVENT: case LTTNG_KERNEL_DISABLE_CHANNEL: @@ -852,6 +853,84 @@ static int process_client_msg(struct command_ctx *cmd_ctx) /* Process by command type */ switch (cmd_ctx->lsm->cmd_type) { + case LTTNG_KERNEL_ADD_CONTEXT: + { + int found = 0, no_event = 0; + struct ltt_kernel_channel *chan; + struct ltt_kernel_event *event; + + /* Setup lttng message with no payload */ + ret = setup_lttng_msg(cmd_ctx, 0); + if (ret < 0) { + goto setup_error; + } + + /* Check if event name is given */ + if (strlen(cmd_ctx->lsm->u.context.event_name) == 0) { + no_event = 1; + } + + if (strlen(cmd_ctx->lsm->u.context.channel_name) == 0) { + /* Go over all channels */ + DBG("Adding context to all channels"); + cds_list_for_each_entry(chan, + &cmd_ctx->session->kernel_session->channel_list.head, list) { + if (no_event) { + ret = kernel_add_channel_context(chan, + &cmd_ctx->lsm->u.context.ctx); + if (ret < 0) { + continue; + } + } else { + event = get_kernel_event_by_name(cmd_ctx->lsm->u.context.event_name, chan); + if (event != NULL) { + ret = kernel_add_event_context(event, + &cmd_ctx->lsm->u.context.ctx); + if (ret < 0) { + ret = LTTCOMM_KERN_CONTEXT_FAIL; + goto error; + } + found = 1; + break; + } + } + } + } else { + chan = get_kernel_channel_by_name(cmd_ctx->lsm->u.context.channel_name, + cmd_ctx->session->kernel_session); + if (chan == NULL) { + ret = LTTCOMM_KERN_CHAN_NOT_FOUND; + goto error; + } + + if (no_event) { + ret = kernel_add_channel_context(chan, + &cmd_ctx->lsm->u.context.ctx); + if (ret < 0) { + ret = LTTCOMM_KERN_CONTEXT_FAIL; + goto error; + } + } else { + event = get_kernel_event_by_name(cmd_ctx->lsm->u.context.event_name, chan); + if (event != NULL) { + ret = kernel_add_event_context(event, + &cmd_ctx->lsm->u.context.ctx); + if (ret < 0) { + ret = LTTCOMM_KERN_CONTEXT_FAIL; + goto error; + } + } + } + } + + if (!found && !no_event) { + ret = LTTCOMM_NO_EVENT; + goto error; + } + + ret = LTTCOMM_OK; + break; + } case LTTNG_KERNEL_CREATE_CHANNEL: { /* Setup lttng message with no payload */ diff --git a/ltt-sessiond/trace.h b/ltt-sessiond/trace.h index 493a23636..2c2f62ae0 100644 --- a/ltt-sessiond/trace.h +++ b/ltt-sessiond/trace.h @@ -45,6 +45,7 @@ struct ltt_kernel_channel_list { struct ltt_kernel_event { int fd; int enabled; + struct lttng_kernel_context *ctx; struct lttng_kernel_event *event; struct cds_list_head list; }; @@ -55,6 +56,7 @@ struct ltt_kernel_channel { int enabled; char *pathname; unsigned int stream_count; + struct lttng_kernel_context *ctx; struct lttng_channel *channel; struct ltt_kernel_event_list events_list; struct ltt_kernel_stream_list stream_list; diff --git a/lttng/Makefile.am b/lttng/Makefile.am index c02506419..159d81728 100644 --- a/lttng/Makefile.am +++ b/lttng/Makefile.am @@ -6,7 +6,8 @@ lttng_SOURCES = conf.c commands/start.c commands/add_channel.c \ commands/list.c commands/create.c commands/destroy.c \ commands/stop.c commands/enable_events.c \ commands/disable_events.c commands/enable_channels.c \ - commands/disable_channels.c utils.c lttng.c + commands/disable_channels.c commands/add_context.c \ + utils.c lttng.c lttng_LDADD = \ $(top_builddir)/liblttngctl/liblttngctl.la diff --git a/lttng/cmd.h b/lttng/cmd.h index 201bad9ee..a59a7f5aa 100644 --- a/lttng/cmd.h +++ b/lttng/cmd.h @@ -47,5 +47,6 @@ extern int cmd_enable_events(int argc, const char **argv); extern int cmd_disable_events(int argc, const char **argv); extern int cmd_enable_channels(int argc, const char **argv); extern int cmd_disable_channels(int argc, const char **argv); +extern int cmd_add_context(int argc, const char **argv); #endif /* _LTTNG_CMD_H */ diff --git a/lttng/commands/add_context.c b/lttng/commands/add_context.c new file mode 100644 index 000000000..afec9dab7 --- /dev/null +++ b/lttng/commands/add_context.c @@ -0,0 +1,206 @@ +/* + * Copyright (C) 2011 - David Goulet + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include + +#include "cmd.h" +#include "conf.h" +#include "utils.h" + +static char *opt_event_name; +static char *opt_channel_name; +static char *opt_perf_name; +static int *opt_kernel; +static int opt_pid_all; +static int opt_userspace; +static int opt_ctx_type; +static int opt_perf_type; +static int opt_perf_id; +static pid_t opt_pid; + +enum { + OPT_HELP = 1, + OPT_TYPE, +}; + +static struct poptOption long_options[] = { + /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */ + {"help", 'h', POPT_ARG_NONE, 0, OPT_HELP, 0, 0}, + {"channel", 'c', POPT_ARG_STRING, &opt_channel_name, 0, 0, 0}, + {"event", 'e', POPT_ARG_STRING, &opt_event_name, 0, 0, 0}, + {"kernel", 'k', POPT_ARG_VAL, &opt_kernel, 1, 0, 0}, + {"userspace", 'u', POPT_ARG_VAL, &opt_userspace, 1, 0, 0}, + {"all", 0, POPT_ARG_VAL, &opt_pid_all, 1, 0, 0}, + {"pid", 'p', POPT_ARG_INT, &opt_pid, 0, 0, 0}, + {"type", 't', POPT_ARG_INT, 0, OPT_TYPE, 0, 0}, + {"perf-name", 0, POPT_ARG_STRING, &opt_perf_name, 0, 0, 0}, + {"perf-type", 0, POPT_ARG_INT, &opt_perf_type, 0, 0, 0}, + {"perf-id", 0, POPT_ARG_INT, &opt_perf_id, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0} +}; + +/* + * usage + */ +static void usage(FILE *ofp) +{ + fprintf(ofp, "usage: lttng add-context [options] [context_options]\n"); + fprintf(ofp, "\n"); + fprintf(ofp, "Options:\n"); + fprintf(ofp, " -h, --help Show this help\n"); + fprintf(ofp, " -c, --channel NAME Apply on channel\n"); + fprintf(ofp, " -e, --event NAME Apply on event\n"); + fprintf(ofp, " -k, --kernel Apply for the kernel tracer\n"); + fprintf(ofp, " -u, --userspace Apply for the user-space tracer\n"); + fprintf(ofp, " --all If -u, apply on all traceable apps\n"); + fprintf(ofp, " -p, --pid PID If -u, apply on a specific PID\n"); + fprintf(ofp, " -t, --type TYPE Context type. TYPE must be a numerical value:\n"); + fprintf(ofp, " KERNEL_CONTEXT_PID = 0\n"); + fprintf(ofp, " KERNEL_CONTEXT_PERF_COUNTER = 1\n"); + fprintf(ofp, " KERNEL_CONTEXT_COMM = 2\n"); + fprintf(ofp, " KERNEL_CONTEXT_PRIO = 3\n"); + fprintf(ofp, " KERNEL_CONTEXT_NICE = 4\n"); + fprintf(ofp, " KERNEL_CONTEXT_VPID = 5\n"); + fprintf(ofp, " KERNEL_CONTEXT_TID = 6\n"); + fprintf(ofp, " KERNEL_CONTEXT_VTID = 7\n"); + fprintf(ofp, " KERNEL_CONTEXT_PPID = 8\n"); + fprintf(ofp, " KERNEL_CONTEXT_VPPID = 9\n"); + fprintf(ofp, "\n"); + fprintf(ofp, "Context options:\n"); + fprintf(ofp, " --perf-name NAME Perf event name\n"); + fprintf(ofp, " --perf-type TYPE Perf event type. TYPE must be a numeric value:\n"); + fprintf(ofp, " PERF_TYPE_HARDWARE = 0\n"); + fprintf(ofp, " PERF_TYPE_SOFTWARE = 1\n"); + fprintf(ofp, " --perf-id ID Perf event id. ID must be a numeric value:\n"); + fprintf(ofp, " Hardware IDs (0):\n"); + fprintf(ofp, " PERF_COUNT_HW_CPU_CYCLES = 0\n"); + fprintf(ofp, " PERF_COUNT_HW_INSTRUCTIONS = 1\n"); + fprintf(ofp, " PERF_COUNT_HW_CACHE_REFERENCES = 2\n"); + fprintf(ofp, " PERF_COUNT_HW_CACHE_MISSES = 3\n"); + fprintf(ofp, " PERF_COUNT_HW_BRANCH_INSTRUCTIONS = 4\n"); + fprintf(ofp, " PERF_COUNT_HW_BRANCH_MISSES = 5\n"); + fprintf(ofp, " PERF_COUNT_HW_BUS_CYCLES = 6\n"); + fprintf(ofp, " Software IDs (1):\n"); + fprintf(ofp, " PERF_COUNT_SW_CPU_CLOCK = 0\n"); + fprintf(ofp, " PERF_COUNT_SW_TASK_CLOCK = 1\n"); + fprintf(ofp, " PERF_COUNT_SW_PAGE_FAULTS = 2\n"); + fprintf(ofp, " PERF_COUNT_SW_CONTEXT_SWITCHES = 3\n"); + fprintf(ofp, " PERF_COUNT_SW_CPU_MIGRATIONS = 4\n"); + fprintf(ofp, " PERF_COUNT_SW_PAGE_FAULTS_MIN = 5\n"); + fprintf(ofp, " PERF_COUNT_SW_PAGE_FAULTS_MAJ = 6\n"); + fprintf(ofp, "\n"); +} + +/* + * add_context + * + * Add context to channel or event. + */ +static int add_context(void) +{ + int ret = CMD_SUCCESS; + struct lttng_kernel_context context; + + if (set_session_name() < 0) { + ret = CMD_ERROR; + goto error; + } + + context.ctx = opt_ctx_type; + if (opt_ctx_type == LTTNG_KERNEL_CONTEXT_PERF_COUNTER) { + context.u.perf_counter.type = opt_perf_type; + context.u.perf_counter.config = opt_perf_id; + strncpy(context.u.perf_counter.name, opt_perf_name, + LTTNG_SYMBOL_NAME_LEN); + } + + if (opt_kernel) { + DBG("Adding kernel context\n"); + ret = lttng_kernel_add_context(&context, opt_event_name, opt_channel_name); + if (ret < 0) { + goto error; + } else { + MSG("Kernel context added"); + } + } else if (opt_userspace) { /* User-space tracer action */ + /* + * TODO: Waiting on lttng UST 2.0 + */ + if (opt_pid_all) { + } else if (opt_pid != 0) { + } + ret = CMD_NOT_IMPLEMENTED; + goto error; + } else { + ERR("Please specify a tracer (kernel or user-space)"); + goto error; + } + +error: + return ret; +} + +/* + * cmd_add_context + * + * Add context on channel or event. + */ +int cmd_add_context(int argc, const char **argv) +{ + int opt, ret; + char *tmp; + static poptContext pc; + + pc = poptGetContext(NULL, argc, argv, long_options, 0); + poptReadDefaultConfig(pc, 0); + + while ((opt = poptGetNextOpt(pc)) != -1) { + switch (opt) { + case OPT_HELP: + usage(stderr); + ret = CMD_SUCCESS; + goto end; + case OPT_TYPE: + /* Mandatory field */ + tmp = poptGetOptArg(pc); + if (tmp == NULL) { + usage(stderr); + ret = CMD_ERROR; + goto end; + } + opt_ctx_type = atoi(tmp); + break; + default: + usage(stderr); + ret = CMD_UNDEFINED; + goto end; + } + } + + ret = add_context(); + +end: + return ret; +} diff --git a/lttng/lttng.c b/lttng/lttng.c index 48d834491..d32f563dd 100644 --- a/lttng/lttng.c +++ b/lttng/lttng.c @@ -66,6 +66,7 @@ static struct cmd_struct commands[] = { { "disable-event", cmd_disable_events}, { "enable-channel", cmd_enable_channels}, { "disable-channel", cmd_disable_channels}, + { "add-context", cmd_add_context}, { NULL, NULL} /* Array closure */ }; @@ -84,6 +85,7 @@ static void usage(FILE *ofp) fprintf(ofp, "\n"); fprintf(ofp, "Commands:\n"); fprintf(ofp, " add-channel Add channel to tracer\n"); + fprintf(ofp, " add-context Add context to event or/and channel\n"); fprintf(ofp, " create Create tracing session\n"); fprintf(ofp, " destroy Teardown tracing session\n"); fprintf(ofp, " enable-channel Enable tracing channel\n");