Implement LTTng-UST perf counters support
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Mon, 17 Feb 2014 01:00:31 +0000 (20:00 -0500)
committerDavid Goulet <dgoulet@efficios.com>
Mon, 5 May 2014 13:08:42 +0000 (09:08 -0400)
Introduce perf:cpu:* and perf:thread:* performance monitoring counter
contexts. perf:cpu: is used for kernel tracing, and perf:thread: is used
for UST. perf:* is kept for backward compatibility, but not shown in
lttng add-context --help anymore.

Example usages of performance counters have been adapted to this new
interface.

For the lttng.h API We introduce LTTNG_EVENT_CONTEXT_PERF_CPU_COUNTER
and LTTNG_EVENT_CONTEXT_PERF_THREAD_COUNTER as the API counterparts of
the new command line options. LTTNG_EVENT_CONTEXT_PERF_COUNTER is kept
for backward compatibility.

For ABIs with the tracers, introduce the new
LTTNG_UST_CONTEXT_PERF_THREAD_COUNTER to support this new UST feature.
Rename LTTNG_KERNEL_CONTEXT_PERF_COUNTER to
LTTNG_KERNEL_CONTEXT_PERF_CPU_COUNTER, following the same change in
lttng-modules (keeping the same enum entry value).

Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Signed-off-by: David Goulet <dgoulet@efficios.com>
doc/man/lttng.1
include/lttng/lttng.h
src/bin/lttng-sessiond/context.c
src/bin/lttng-sessiond/lttng-ust-abi.h
src/bin/lttng-sessiond/trace-ust.c
src/bin/lttng-sessiond/trace-ust.h
src/bin/lttng-sessiond/ust-app.c
src/bin/lttng/commands/add_context.c
src/common/kernel-ctl/kernel-ctl.c
src/common/lttng-kernel.h

index 988208395750c24066eb376512b554260b99122a..9f95a8a13c2a04497579ca43505447d0b82bb530 100644 (file)
@@ -87,20 +87,25 @@ Add context to event(s) and/or channel(s).
 A context is basically extra information appended to a channel. For instance,
 you could ask the tracer to add the PID information for all events in a
 channel. You can also add performance monitoring unit counters (perf PMU) using
 A context is basically extra information appended to a channel. For instance,
 you could ask the tracer to add the PID information for all events in a
 channel. You can also add performance monitoring unit counters (perf PMU) using
-the perf kernel API).
+the perf kernel API.
 
 
-For example, this command will add the context information 'prio' and two perf
-counters (hardware branch misses and cache misses), to all events in the trace
+For example, this command will add the context information 'prio' and two per-CPU
+perf counters (hardware branch misses and cache misses), to all events in the trace
 data output:
 
 .nf
 data output:
 
 .nf
-# lttng add-context \-k \-t prio \-t perf:branch-misses \\
-               \-t perf:cache-misses
+# lttng add-context \-k \-t prio \-t perf:cpu:branch-misses \\
+               \-t perf:cpu:cache-misses
 .fi
 
 Please take a look at the help (\-h/\-\-help) for a detailed list of available
 contexts.
 
 .fi
 
 Please take a look at the help (\-h/\-\-help) for a detailed list of available
 contexts.
 
+Perf counters are available as per-CPU ("perf:cpu:...") and per-thread
+("perf:thread:...") counters. Currently, per-CPU counters can only be
+used with the kernel tracing domain, and per-thread counters can only be
+used with the UST tracing domain.
+
 If no channel is given (\-c), the context is added to all channels that were
 already enabled. If the session has no channel, a default channel is created.
 Otherwise the context will be added only to the given channel (\-c).
 If no channel is given (\-c), the context is added to all channels that were
 already enabled. If the session has no channel, a default channel is created.
 Otherwise the context will be added only to the given channel (\-c).
@@ -160,9 +165,9 @@ counters).
 # lttng create calibrate-function
 # lttng enable-event calibrate \-\-kernel \\
        \-\-function lttng_calibrate_kretprobe
 # lttng create calibrate-function
 # lttng enable-event calibrate \-\-kernel \\
        \-\-function lttng_calibrate_kretprobe
-# lttng add-context \-\-kernel \-t perf:LLC-load-misses \\
-       \-t perf:LLC-store-misses \\
-       \-t perf:LLC-prefetch-misses
+# lttng add-context \-\-kernel \-t perf:cpu:LLC-load-misses \\
+       \-t perf:cpu:LLC-store-misses \\
+       \-t perf:cpu:LLC-prefetch-misses
 # lttng start
 # for a in $(seq 1 10); do \\
         lttng calibrate \-\-kernel \-\-function;
 # lttng start
 # for a in $(seq 1 10); do \\
         lttng calibrate \-\-kernel \-\-function;
index f0be224b53c1b2343c2e34961bf7a5f18dd3982c..e59b2d31d41c6ad18c1b936f41cf47679454d50c 100644 (file)
@@ -132,7 +132,7 @@ enum lttng_event_output {
 /* Event context possible type */
 enum lttng_event_context_type {
        LTTNG_EVENT_CONTEXT_PID               = 0,
 /* Event context possible type */
 enum lttng_event_context_type {
        LTTNG_EVENT_CONTEXT_PID               = 0,
-       LTTNG_EVENT_CONTEXT_PERF_COUNTER      = 1,
+       LTTNG_EVENT_CONTEXT_PERF_COUNTER      = 1,      /* Backward compat. */
        LTTNG_EVENT_CONTEXT_PROCNAME          = 2,
        LTTNG_EVENT_CONTEXT_PRIO              = 3,
        LTTNG_EVENT_CONTEXT_NICE              = 4,
        LTTNG_EVENT_CONTEXT_PROCNAME          = 2,
        LTTNG_EVENT_CONTEXT_PRIO              = 3,
        LTTNG_EVENT_CONTEXT_NICE              = 4,
@@ -144,6 +144,8 @@ enum lttng_event_context_type {
        LTTNG_EVENT_CONTEXT_PTHREAD_ID        = 10,
        LTTNG_EVENT_CONTEXT_HOSTNAME          = 11,
        LTTNG_EVENT_CONTEXT_IP                = 12,
        LTTNG_EVENT_CONTEXT_PTHREAD_ID        = 10,
        LTTNG_EVENT_CONTEXT_HOSTNAME          = 11,
        LTTNG_EVENT_CONTEXT_IP                = 12,
+       LTTNG_EVENT_CONTEXT_PERF_CPU_COUNTER  = 13,
+       LTTNG_EVENT_CONTEXT_PERF_THREAD_COUNTER = 14,
 };
 
 enum lttng_calibrate_type {
 };
 
 enum lttng_calibrate_type {
index 6aacbad0ea1c96ad3375739ca908f765f1ba4370..1b87df2e90ab03a3d95192a5afc102fc21404397 100644 (file)
@@ -92,13 +92,19 @@ static int add_uctx_to_channel(struct ltt_ust_session *usess, int domain,
 {
        int ret;
        struct ltt_ust_context *uctx;
 {
        int ret;
        struct ltt_ust_context *uctx;
-       struct lttng_ht_iter iter;
-       struct lttng_ht_node_ulong *uctx_node;
 
        assert(usess);
        assert(uchan);
        assert(ctx);
 
 
        assert(usess);
        assert(uchan);
        assert(ctx);
 
+       /* Check if context is duplicate */
+       cds_list_for_each_entry(uctx, &uchan->ctx_list, list) {
+               if (trace_ust_match_context(uctx, ctx)) {
+                       ret = -EEXIST;
+                       goto duplicate;
+               }
+       }
+
        /* Create ltt UST context */
        uctx = trace_ust_create_context(ctx);
        if (uctx == NULL) {
        /* Create ltt UST context */
        uctx = trace_ust_create_context(ctx);
        if (uctx == NULL) {
@@ -120,17 +126,8 @@ static int add_uctx_to_channel(struct ltt_ust_session *usess, int domain,
 
        rcu_read_lock();
 
 
        rcu_read_lock();
 
-       /* Lookup context before adding it */
-       lttng_ht_lookup(uchan->ctx, (void *)((unsigned long)uctx->ctx.ctx), &iter);
-       uctx_node = lttng_ht_iter_get_node_ulong(&iter);
-       if (uctx_node != NULL) {
-               ret = -EEXIST;
-               rcu_read_unlock();
-               goto error;
-       }
-
        /* Add ltt UST context node to ltt UST channel */
        /* Add ltt UST context node to ltt UST channel */
-       lttng_ht_add_unique_ulong(uchan->ctx, &uctx->node);
+       lttng_ht_add_ulong(uchan->ctx, &uctx->node);
        rcu_read_unlock();
        cds_list_add_tail(&uctx->list, &uchan->ctx_list);
 
        rcu_read_unlock();
        cds_list_add_tail(&uctx->list, &uchan->ctx_list);
 
@@ -140,6 +137,7 @@ static int add_uctx_to_channel(struct ltt_ust_session *usess, int domain,
 
 error:
        free(uctx);
 
 error:
        free(uctx);
+duplicate:
        return ret;
 }
 
        return ret;
 }
 
@@ -162,9 +160,6 @@ int context_kernel_add(struct ltt_kernel_session *ksession,
        case LTTNG_EVENT_CONTEXT_PID:
                kctx.ctx = LTTNG_KERNEL_CONTEXT_PID;
                break;
        case LTTNG_EVENT_CONTEXT_PID:
                kctx.ctx = LTTNG_KERNEL_CONTEXT_PID;
                break;
-       case LTTNG_EVENT_CONTEXT_PERF_COUNTER:
-               kctx.ctx = LTTNG_KERNEL_CONTEXT_PERF_COUNTER;
-               break;
        case LTTNG_EVENT_CONTEXT_PROCNAME:
                kctx.ctx = LTTNG_KERNEL_CONTEXT_PROCNAME;
                break;
        case LTTNG_EVENT_CONTEXT_PROCNAME:
                kctx.ctx = LTTNG_KERNEL_CONTEXT_PROCNAME;
                break;
@@ -192,6 +187,10 @@ int context_kernel_add(struct ltt_kernel_session *ksession,
        case LTTNG_EVENT_CONTEXT_HOSTNAME:
                kctx.ctx = LTTNG_KERNEL_CONTEXT_HOSTNAME;
                break;
        case LTTNG_EVENT_CONTEXT_HOSTNAME:
                kctx.ctx = LTTNG_KERNEL_CONTEXT_HOSTNAME;
                break;
+       case LTTNG_EVENT_CONTEXT_PERF_CPU_COUNTER:
+       case LTTNG_EVENT_CONTEXT_PERF_COUNTER:
+               kctx.ctx = LTTNG_KERNEL_CONTEXT_PERF_CPU_COUNTER;
+               break;
        default:
                return LTTNG_ERR_KERN_CONTEXT_FAIL;
        }
        default:
                return LTTNG_ERR_KERN_CONTEXT_FAIL;
        }
index a3298caa2778435ca34cdec4ab508e940694346b..81b61492a8ff1144d1c7f17af42fd62d569e0c82 100644 (file)
@@ -140,8 +140,15 @@ enum lttng_ust_context_type {
        LTTNG_UST_CONTEXT_PTHREAD_ID            = 2,
        LTTNG_UST_CONTEXT_PROCNAME              = 3,
        LTTNG_UST_CONTEXT_IP                    = 4,
        LTTNG_UST_CONTEXT_PTHREAD_ID            = 2,
        LTTNG_UST_CONTEXT_PROCNAME              = 3,
        LTTNG_UST_CONTEXT_IP                    = 4,
+       LTTNG_UST_CONTEXT_PERF_THREAD_COUNTER   = 5,
 };
 
 };
 
+struct lttng_ust_perf_counter_ctx {
+       uint32_t type;
+       uint64_t config;
+       char name[LTTNG_UST_SYM_NAME_LEN];
+} LTTNG_PACKED;
+
 #define LTTNG_UST_CONTEXT_PADDING1     16
 #define LTTNG_UST_CONTEXT_PADDING2     (LTTNG_UST_SYM_NAME_LEN + 32)
 struct lttng_ust_context {
 #define LTTNG_UST_CONTEXT_PADDING1     16
 #define LTTNG_UST_CONTEXT_PADDING2     (LTTNG_UST_SYM_NAME_LEN + 32)
 struct lttng_ust_context {
@@ -149,6 +156,7 @@ struct lttng_ust_context {
        char padding[LTTNG_UST_CONTEXT_PADDING1];
 
        union {
        char padding[LTTNG_UST_CONTEXT_PADDING1];
 
        union {
+               struct lttng_ust_perf_counter_ctx perf_counter;
                char padding[LTTNG_UST_CONTEXT_PADDING2];
        } u;
 } LTTNG_PACKED;
                char padding[LTTNG_UST_CONTEXT_PADDING2];
        } u;
 } LTTNG_PACKED;
index dfbbcd777a264d0bcccc39253dbecc344f3f5abf..96225a21b4846e974ffb1f900c054202759e3b5a 100644 (file)
@@ -414,20 +414,12 @@ error:
        return NULL;
 }
 
        return NULL;
 }
 
-/*
- * Allocate and initialize an UST context.
- *
- * Return pointer to structure or NULL.
- */
-struct ltt_ust_context *trace_ust_create_context(
-               struct lttng_event_context *ctx)
+static
+int trace_ust_context_type_event_to_ust(enum lttng_event_context_type type)
 {
 {
-       struct ltt_ust_context *uctx;
-       enum lttng_ust_context_type utype;
-
-       assert(ctx);
+       int utype;
 
 
-       switch (ctx->ctx) {
+       switch (type) {
        case LTTNG_EVENT_CONTEXT_VTID:
                utype = LTTNG_UST_CONTEXT_VTID;
                break;
        case LTTNG_EVENT_CONTEXT_VTID:
                utype = LTTNG_UST_CONTEXT_VTID;
                break;
@@ -443,8 +435,70 @@ struct ltt_ust_context *trace_ust_create_context(
        case LTTNG_EVENT_CONTEXT_IP:
                utype = LTTNG_UST_CONTEXT_IP;
                break;
        case LTTNG_EVENT_CONTEXT_IP:
                utype = LTTNG_UST_CONTEXT_IP;
                break;
+       case LTTNG_EVENT_CONTEXT_PERF_THREAD_COUNTER:
+               utype = LTTNG_UST_CONTEXT_PERF_THREAD_COUNTER;
+               break;
        default:
                ERR("Invalid UST context");
        default:
                ERR("Invalid UST context");
+               utype = -1;
+               break;
+       }
+       return utype;
+}
+
+/*
+ * Return 1 if contexts match, 0 otherwise.
+ */
+int trace_ust_match_context(struct ltt_ust_context *uctx,
+               struct lttng_event_context *ctx)
+{
+       int utype;
+
+       utype = trace_ust_context_type_event_to_ust(ctx->ctx);
+       if (utype < 0) {
+               return 0;
+       }
+       if (uctx->ctx.ctx != utype) {
+               return 0;
+       }
+       switch (utype) {
+       case LTTNG_UST_CONTEXT_PERF_THREAD_COUNTER:
+               if (uctx->ctx.u.perf_counter.type
+                               != ctx->u.perf_counter.type) {
+                       return 0;
+               }
+               if (uctx->ctx.u.perf_counter.config
+                               != ctx->u.perf_counter.config) {
+                       return 0;
+               }
+               if (strncmp(uctx->ctx.u.perf_counter.name,
+                               ctx->u.perf_counter.name,
+                               LTTNG_UST_SYM_NAME_LEN)) {
+                       return 0;
+               }
+               break;
+       default:
+               break;
+
+       }
+       return 1;
+}
+
+/*
+ * Allocate and initialize an UST context.
+ *
+ * Return pointer to structure or NULL.
+ */
+struct ltt_ust_context *trace_ust_create_context(
+               struct lttng_event_context *ctx)
+{
+       struct ltt_ust_context *uctx;
+       int utype;
+
+       assert(ctx);
+
+       utype = trace_ust_context_type_event_to_ust(ctx->ctx);
+       if (utype < 0) {
                return NULL;
        }
 
                return NULL;
        }
 
@@ -454,9 +508,19 @@ struct ltt_ust_context *trace_ust_create_context(
                goto error;
        }
 
                goto error;
        }
 
-       uctx->ctx.ctx = utype;
+       uctx->ctx.ctx = (enum lttng_ust_context_type) utype;
+       switch (utype) {
+       case LTTNG_UST_CONTEXT_PERF_THREAD_COUNTER:
+               uctx->ctx.u.perf_counter.type = ctx->u.perf_counter.type;
+               uctx->ctx.u.perf_counter.config = ctx->u.perf_counter.config;
+               strncpy(uctx->ctx.u.perf_counter.name, ctx->u.perf_counter.name,
+                               LTTNG_UST_SYM_NAME_LEN);
+               uctx->ctx.u.perf_counter.name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
+               break;
+       default:
+               break;
+       }
        lttng_ht_node_init_ulong(&uctx->node, (unsigned long) uctx->ctx.ctx);
        lttng_ht_node_init_ulong(&uctx->node, (unsigned long) uctx->ctx.ctx);
-       CDS_INIT_LIST_HEAD(&uctx->list);
 
        return uctx;
 
 
        return uctx;
 
index bac5c328bf4f9169256d413723f0083144a6fc88..86f8d40b1de0d6d96850621bca1a2a6bcefb80b0 100644 (file)
@@ -169,6 +169,8 @@ struct ltt_ust_event *trace_ust_create_event(struct lttng_event *ev,
                struct lttng_event_exclusion *exclusion);
 struct ltt_ust_context *trace_ust_create_context(
                struct lttng_event_context *ctx);
                struct lttng_event_exclusion *exclusion);
 struct ltt_ust_context *trace_ust_create_context(
                struct lttng_event_context *ctx);
+int trace_ust_match_context(struct ltt_ust_context *uctx,
+               struct lttng_event_context *ctx);
 void trace_ust_delete_channel(struct lttng_ht *ht,
                struct ltt_ust_channel *channel);
 
 void trace_ust_delete_channel(struct lttng_ht *ht,
                struct ltt_ust_channel *channel);
 
@@ -237,6 +239,12 @@ struct ltt_ust_context *trace_ust_create_context(
 {
        return NULL;
 }
 {
        return NULL;
 }
+static inline
+int trace_ust_match_context(struct ltt_ust_context *uctx,
+               struct lttng_event_context *ctx)
+{
+       return 0;
+}
 static inline struct ltt_ust_event *trace_ust_find_event(struct lttng_ht *ht,
                char *name, struct lttng_filter_bytecode *filter, int loglevel,
                struct lttng_event_exclusion *exclusion)
 static inline struct ltt_ust_event *trace_ust_find_event(struct lttng_ht *ht,
                char *name, struct lttng_filter_bytecode *filter, int loglevel,
                struct lttng_event_exclusion *exclusion)
index e029b42d8f93827ac70da99203608abd80214e19..fc744fc027cd376c0004431c6303136914d41254 100644 (file)
@@ -1552,7 +1552,7 @@ static void shadow_copy_channel(struct ust_app_channel *ua_chan,
                }
                lttng_ht_node_init_ulong(&ua_ctx->node,
                                (unsigned long) ua_ctx->ctx.ctx);
                }
                lttng_ht_node_init_ulong(&ua_ctx->node,
                                (unsigned long) ua_ctx->ctx.ctx);
-               lttng_ht_add_unique_ulong(ua_chan->ctx, &ua_ctx->node);
+               lttng_ht_add_ulong(ua_chan->ctx, &ua_ctx->node);
                cds_list_add_tail(&ua_ctx->list, &ua_chan->ctx_list);
        }
 
                cds_list_add_tail(&ua_ctx->list, &ua_chan->ctx_list);
        }
 
@@ -1955,7 +1955,7 @@ int create_ust_app_channel_context(struct ust_app_session *ua_sess,
        }
 
        lttng_ht_node_init_ulong(&ua_ctx->node, (unsigned long) ua_ctx->ctx.ctx);
        }
 
        lttng_ht_node_init_ulong(&ua_ctx->node, (unsigned long) ua_ctx->ctx.ctx);
-       lttng_ht_add_unique_ulong(ua_chan->ctx, &ua_ctx->node);
+       lttng_ht_add_ulong(ua_chan->ctx, &ua_ctx->node);
        cds_list_add_tail(&ua_ctx->list, &ua_chan->ctx_list);
 
        ret = create_ust_channel_context(ua_chan, ua_ctx, app);
        cds_list_add_tail(&ua_ctx->list, &ua_chan->ctx_list);
 
        ret = create_ust_channel_context(ua_chan, ua_ctx, app);
index 6483c9891d83038e929b3a1b96fd3f5cd6ab07c4..405b7828f043dea695beff3bde4206cec59ee4ff 100644 (file)
@@ -56,7 +56,7 @@ static struct lttng_handle *handle;
  */
 enum context_type {
        CONTEXT_PID          = 0,
  */
 enum context_type {
        CONTEXT_PID          = 0,
-       CONTEXT_PERF_COUNTER = 1,
+       CONTEXT_PERF_COUNTER = 1,       /* Backward compat. */
        CONTEXT_PROCNAME     = 2,
        CONTEXT_PRIO         = 3,
        CONTEXT_NICE         = 4,
        CONTEXT_PROCNAME     = 2,
        CONTEXT_PRIO         = 3,
        CONTEXT_NICE         = 4,
@@ -68,6 +68,8 @@ enum context_type {
        CONTEXT_PTHREAD_ID   = 10,
        CONTEXT_HOSTNAME     = 11,
        CONTEXT_IP           = 12,
        CONTEXT_PTHREAD_ID   = 10,
        CONTEXT_HOSTNAME     = 11,
        CONTEXT_IP           = 12,
+       CONTEXT_PERF_CPU_COUNTER = 13,
+       CONTEXT_PERF_THREAD_COUNTER = 14,
 };
 
 /*
 };
 
 /*
@@ -151,21 +153,21 @@ static struct poptOption long_options[] = {
 /*
  * Context options
  */
 /*
  * Context options
  */
-#define PERF_HW(opt, name)                                             \
+#define PERF_HW(optstr, name, type, hide)                              \
        {                                                               \
        {                                                               \
-               "perf:" #opt, CONTEXT_PERF_COUNTER,                     \
+               optstr, type, hide,                                     \
                .u.perf = { PERF_TYPE_HARDWARE, PERF_COUNT_HW_##name, },\
        }
 
                .u.perf = { PERF_TYPE_HARDWARE, PERF_COUNT_HW_##name, },\
        }
 
-#define PERF_SW(opt, name)                                             \
+#define PERF_SW(optstr, name, type, hide)                              \
        {                                                               \
        {                                                               \
-               "perf:" #opt, CONTEXT_PERF_COUNTER,                     \
+               optstr, type, hide,                                     \
                .u.perf = { PERF_TYPE_SOFTWARE, PERF_COUNT_SW_##name, },\
        }
 
                .u.perf = { PERF_TYPE_SOFTWARE, PERF_COUNT_SW_##name, },\
        }
 
-#define _PERF_HW_CACHE(optstr, name, op, result)                       \
+#define _PERF_HW_CACHE(optstr, name, type, op, result, hide)           \
        {                                                               \
        {                                                               \
-               "perf:" optstr, CONTEXT_PERF_COUNTER,                   \
+               optstr, type, hide,                                     \
                .u.perf = {                                             \
                        PERF_TYPE_HW_CACHE,                             \
                        (uint64_t) PERF_COUNT_HW_CACHE_##name           \
                .u.perf = {                                             \
                        PERF_TYPE_HW_CACHE,                             \
                        (uint64_t) PERF_COUNT_HW_CACHE_##name           \
@@ -174,18 +176,25 @@ static struct poptOption long_options[] = {
                },                                                      \
        }
 
                },                                                      \
        }
 
-#define PERF_HW_CACHE(opt, name)                                       \
-       _PERF_HW_CACHE(#opt "-loads", name, READ, ACCESS),              \
-       _PERF_HW_CACHE(#opt "-load-misses", name, READ, MISS),          \
-       _PERF_HW_CACHE(#opt "-stores", name, WRITE, ACCESS),            \
-       _PERF_HW_CACHE(#opt "-store-misses", name, WRITE, MISS),        \
-       _PERF_HW_CACHE(#opt "-prefetches", name, PREFETCH, ACCESS),     \
-       _PERF_HW_CACHE(#opt "-prefetch-misses", name, PREFETCH, MISS)   \
+#define PERF_HW_CACHE(optstr, name, type, hide)                                \
+       _PERF_HW_CACHE(optstr "-loads", name, type,                     \
+               READ, ACCESS, hide),                                    \
+       _PERF_HW_CACHE(optstr "-load-misses", name, type,               \
+               READ, MISS, hide),                                      \
+       _PERF_HW_CACHE(optstr "-stores", name, type,                    \
+               WRITE, ACCESS, hide),                                   \
+       _PERF_HW_CACHE(optstr "-store-misses", name, type,              \
+               WRITE, MISS, hide),                                     \
+       _PERF_HW_CACHE(optstr "-prefetches", name, type,                \
+               PREFETCH, ACCESS, hide),                                \
+       _PERF_HW_CACHE(optstr "-prefetch-misses", name, type,           \
+               PREFETCH, MISS, hide)
 
 static
 const struct ctx_opts {
        char *symbol;
        enum context_type ctx_type;
 
 static
 const struct ctx_opts {
        char *symbol;
        enum context_type ctx_type;
+       int hide_help;  /* Hide from --help */
        union {
                struct {
                        uint32_t type;
        union {
                struct {
                        uint32_t type;
@@ -205,46 +214,227 @@ const struct ctx_opts {
        { "vppid", CONTEXT_VPPID },
        { "hostname", CONTEXT_HOSTNAME },
        { "ip", CONTEXT_IP },
        { "vppid", CONTEXT_VPPID },
        { "hostname", CONTEXT_HOSTNAME },
        { "ip", CONTEXT_IP },
+
        /* Perf options */
        /* Perf options */
-       PERF_HW(cpu-cycles, CPU_CYCLES),
-       PERF_HW(cycles, CPU_CYCLES),
-       PERF_HW(stalled-cycles-frontend, STALLED_CYCLES_FRONTEND),
-       PERF_HW(idle-cycles-frontend, STALLED_CYCLES_FRONTEND),
-       PERF_HW(stalled-cycles-backend, STALLED_CYCLES_BACKEND),
-       PERF_HW(idle-cycles-backend, STALLED_CYCLES_BACKEND),
-       PERF_HW(instructions, INSTRUCTIONS),
-       PERF_HW(cache-references, CACHE_REFERENCES),
-       PERF_HW(cache-misses, CACHE_MISSES),
-       PERF_HW(branch-instructions, BRANCH_INSTRUCTIONS),
-       PERF_HW(branches, BRANCH_INSTRUCTIONS),
-       PERF_HW(branch-misses, BRANCH_MISSES),
-       PERF_HW(bus-cycles, BUS_CYCLES),
-
-       PERF_HW_CACHE(L1-dcache, L1D),
-       PERF_HW_CACHE(L1-icache, L1I),
-       PERF_HW_CACHE(LLC, LL),
-       PERF_HW_CACHE(dTLB, DTLB),
-       _PERF_HW_CACHE("iTLB-loads", ITLB, READ, ACCESS),
-       _PERF_HW_CACHE("iTLB-load-misses", ITLB, READ, MISS),
-       _PERF_HW_CACHE("branch-loads", BPU, READ, ACCESS),
-       _PERF_HW_CACHE("branch-load-misses", BPU, READ, MISS),
-
-
-       PERF_SW(cpu-clock, CPU_CLOCK),
-       PERF_SW(task-clock, TASK_CLOCK),
-       PERF_SW(page-fault, PAGE_FAULTS),
-       PERF_SW(faults, PAGE_FAULTS),
-       PERF_SW(major-faults, PAGE_FAULTS_MAJ),
-       PERF_SW(minor-faults, PAGE_FAULTS_MIN),
-       PERF_SW(context-switches, CONTEXT_SWITCHES),
-       PERF_SW(cs, CONTEXT_SWITCHES),
-       PERF_SW(cpu-migrations, CPU_MIGRATIONS),
-       PERF_SW(migrations, CPU_MIGRATIONS),
-       PERF_SW(alignment-faults, ALIGNMENT_FAULTS),
-       PERF_SW(emulation-faults, EMULATION_FAULTS),
+
+       /* Perf per-CPU counters */
+       PERF_HW("perf:cpu:cpu-cycles", CPU_CYCLES,
+               CONTEXT_PERF_CPU_COUNTER, 0),
+       PERF_HW("perf:cpu:cycles", CPU_CYCLES,
+               CONTEXT_PERF_CPU_COUNTER, 0),
+       PERF_HW("perf:cpu:stalled-cycles-frontend", STALLED_CYCLES_FRONTEND,
+               CONTEXT_PERF_CPU_COUNTER, 0),
+       PERF_HW("perf:cpu:idle-cycles-frontend", STALLED_CYCLES_FRONTEND,
+               CONTEXT_PERF_CPU_COUNTER, 0),
+       PERF_HW("perf:cpu:stalled-cycles-backend", STALLED_CYCLES_BACKEND,
+               CONTEXT_PERF_CPU_COUNTER, 0),
+       PERF_HW("perf:cpu:idle-cycles-backend", STALLED_CYCLES_BACKEND,
+               CONTEXT_PERF_CPU_COUNTER, 0),
+       PERF_HW("perf:cpu:instructions", INSTRUCTIONS,
+               CONTEXT_PERF_CPU_COUNTER, 0),
+       PERF_HW("perf:cpu:cache-references", CACHE_REFERENCES,
+               CONTEXT_PERF_CPU_COUNTER, 0),
+       PERF_HW("perf:cpu:cache-misses", CACHE_MISSES,
+               CONTEXT_PERF_CPU_COUNTER, 0),
+       PERF_HW("perf:cpu:branch-instructions", BRANCH_INSTRUCTIONS,
+               CONTEXT_PERF_CPU_COUNTER, 0),
+       PERF_HW("perf:cpu:branches", BRANCH_INSTRUCTIONS,
+               CONTEXT_PERF_CPU_COUNTER, 0),
+       PERF_HW("perf:cpu:branch-misses", BRANCH_MISSES,
+               CONTEXT_PERF_CPU_COUNTER, 0),
+       PERF_HW("perf:cpu:bus-cycles", BUS_CYCLES,
+               CONTEXT_PERF_CPU_COUNTER, 0),
+
+       PERF_HW_CACHE("perf:cpu:L1-dcache", L1D,
+               CONTEXT_PERF_CPU_COUNTER, 0),
+       PERF_HW_CACHE("perf:cpu:L1-icache", L1I,
+               CONTEXT_PERF_CPU_COUNTER, 0),
+       PERF_HW_CACHE("perf:cpu:LLC", LL,
+               CONTEXT_PERF_CPU_COUNTER, 0),
+       PERF_HW_CACHE("perf:cpu:dTLB", DTLB,
+               CONTEXT_PERF_CPU_COUNTER, 0),
+       _PERF_HW_CACHE("perf:cpu:iTLB-loads", ITLB,
+               CONTEXT_PERF_CPU_COUNTER, READ, ACCESS, 0),
+       _PERF_HW_CACHE("perf:cpu:iTLB-load-misses", ITLB,
+               CONTEXT_PERF_CPU_COUNTER, READ, MISS, 0),
+       _PERF_HW_CACHE("perf:cpu:branch-loads", BPU,
+               CONTEXT_PERF_CPU_COUNTER, READ, ACCESS, 0),
+       _PERF_HW_CACHE("perf:cpu:branch-load-misses", BPU,
+               CONTEXT_PERF_CPU_COUNTER, READ, MISS, 0),
+
+       PERF_SW("perf:cpu:cpu-clock", CPU_CLOCK,
+               CONTEXT_PERF_CPU_COUNTER, 0),
+       PERF_SW("perf:cpu:task-clock", TASK_CLOCK,
+               CONTEXT_PERF_CPU_COUNTER, 0),
+       PERF_SW("perf:cpu:page-fault", PAGE_FAULTS,
+               CONTEXT_PERF_CPU_COUNTER, 0),
+       PERF_SW("perf:cpu:faults", PAGE_FAULTS,
+               CONTEXT_PERF_CPU_COUNTER, 0),
+       PERF_SW("perf:cpu:major-faults", PAGE_FAULTS_MAJ,
+               CONTEXT_PERF_CPU_COUNTER, 0),
+       PERF_SW("perf:cpu:minor-faults", PAGE_FAULTS_MIN,
+               CONTEXT_PERF_CPU_COUNTER, 0),
+       PERF_SW("perf:cpu:context-switches", CONTEXT_SWITCHES,
+               CONTEXT_PERF_CPU_COUNTER, 0),
+       PERF_SW("perf:cpu:cs", CONTEXT_SWITCHES,
+               CONTEXT_PERF_CPU_COUNTER, 0),
+       PERF_SW("perf:cpu:cpu-migrations", CPU_MIGRATIONS,
+               CONTEXT_PERF_CPU_COUNTER, 0),
+       PERF_SW("perf:cpu:migrations", CPU_MIGRATIONS,
+               CONTEXT_PERF_CPU_COUNTER, 0),
+       PERF_SW("perf:cpu:alignment-faults", ALIGNMENT_FAULTS,
+               CONTEXT_PERF_CPU_COUNTER, 0),
+       PERF_SW("perf:cpu:emulation-faults", EMULATION_FAULTS,
+               CONTEXT_PERF_CPU_COUNTER, 0),
+
+       /* Perf per-thread counters */
+       PERF_HW("perf:thread:cpu-cycles", CPU_CYCLES,
+               CONTEXT_PERF_THREAD_COUNTER, 0),
+       PERF_HW("perf:thread:cycles", CPU_CYCLES,
+               CONTEXT_PERF_THREAD_COUNTER, 0),
+       PERF_HW("perf:thread:stalled-cycles-frontend", STALLED_CYCLES_FRONTEND,
+               CONTEXT_PERF_THREAD_COUNTER, 0),
+       PERF_HW("perf:thread:idle-cycles-frontend", STALLED_CYCLES_FRONTEND,
+               CONTEXT_PERF_THREAD_COUNTER, 0),
+       PERF_HW("perf:thread:stalled-cycles-backend", STALLED_CYCLES_BACKEND,
+               CONTEXT_PERF_THREAD_COUNTER, 0),
+       PERF_HW("perf:thread:idle-cycles-backend", STALLED_CYCLES_BACKEND,
+               CONTEXT_PERF_THREAD_COUNTER, 0),
+       PERF_HW("perf:thread:instructions", INSTRUCTIONS,
+               CONTEXT_PERF_THREAD_COUNTER, 0),
+       PERF_HW("perf:thread:cache-references", CACHE_REFERENCES,
+               CONTEXT_PERF_THREAD_COUNTER, 0),
+       PERF_HW("perf:thread:cache-misses", CACHE_MISSES,
+               CONTEXT_PERF_THREAD_COUNTER, 0),
+       PERF_HW("perf:thread:branch-instructions", BRANCH_INSTRUCTIONS,
+               CONTEXT_PERF_THREAD_COUNTER, 0),
+       PERF_HW("perf:thread:branches", BRANCH_INSTRUCTIONS,
+               CONTEXT_PERF_THREAD_COUNTER, 0),
+       PERF_HW("perf:thread:branch-misses", BRANCH_MISSES,
+               CONTEXT_PERF_THREAD_COUNTER, 0),
+       PERF_HW("perf:thread:bus-cycles", BUS_CYCLES,
+               CONTEXT_PERF_THREAD_COUNTER, 0),
+
+       PERF_HW_CACHE("perf:thread:L1-dcache", L1D,
+               CONTEXT_PERF_THREAD_COUNTER, 0),
+       PERF_HW_CACHE("perf:thread:L1-icache", L1I,
+               CONTEXT_PERF_THREAD_COUNTER, 0),
+       PERF_HW_CACHE("perf:thread:LLC", LL,
+               CONTEXT_PERF_THREAD_COUNTER, 0),
+       PERF_HW_CACHE("perf:thread:dTLB", DTLB,
+               CONTEXT_PERF_THREAD_COUNTER, 0),
+       _PERF_HW_CACHE("perf:thread:iTLB-loads", ITLB,
+               CONTEXT_PERF_THREAD_COUNTER, READ, ACCESS, 0),
+       _PERF_HW_CACHE("perf:thread:iTLB-load-misses", ITLB,
+               CONTEXT_PERF_THREAD_COUNTER, READ, MISS, 0),
+       _PERF_HW_CACHE("perf:thread:branch-loads", BPU,
+               CONTEXT_PERF_THREAD_COUNTER, READ, ACCESS, 0),
+       _PERF_HW_CACHE("perf:thread:branch-load-misses", BPU,
+               CONTEXT_PERF_THREAD_COUNTER, READ, MISS, 0),
+
+       PERF_SW("perf:thread:cpu-clock", CPU_CLOCK,
+               CONTEXT_PERF_THREAD_COUNTER, 0),
+       PERF_SW("perf:thread:task-clock", TASK_CLOCK,
+               CONTEXT_PERF_THREAD_COUNTER, 0),
+       PERF_SW("perf:thread:page-fault", PAGE_FAULTS,
+               CONTEXT_PERF_THREAD_COUNTER, 0),
+       PERF_SW("perf:thread:faults", PAGE_FAULTS,
+               CONTEXT_PERF_THREAD_COUNTER, 0),
+       PERF_SW("perf:thread:major-faults", PAGE_FAULTS_MAJ,
+               CONTEXT_PERF_THREAD_COUNTER, 0),
+       PERF_SW("perf:thread:minor-faults", PAGE_FAULTS_MIN,
+               CONTEXT_PERF_THREAD_COUNTER, 0),
+       PERF_SW("perf:thread:context-switches", CONTEXT_SWITCHES,
+               CONTEXT_PERF_THREAD_COUNTER, 0),
+       PERF_SW("perf:thread:cs", CONTEXT_SWITCHES,
+               CONTEXT_PERF_THREAD_COUNTER, 0),
+       PERF_SW("perf:thread:cpu-migrations", CPU_MIGRATIONS,
+               CONTEXT_PERF_THREAD_COUNTER, 0),
+       PERF_SW("perf:thread:migrations", CPU_MIGRATIONS,
+               CONTEXT_PERF_THREAD_COUNTER, 0),
+       PERF_SW("perf:thread:alignment-faults", ALIGNMENT_FAULTS,
+               CONTEXT_PERF_THREAD_COUNTER, 0),
+       PERF_SW("perf:thread:emulation-faults", EMULATION_FAULTS,
+               CONTEXT_PERF_THREAD_COUNTER, 0),
+
+       /*
+        * Perf per-CPU counters, backward compatibilty for names.
+        * Hidden from help listing.
+        */
+       PERF_HW("perf:cpu-cycles", CPU_CYCLES,
+               CONTEXT_PERF_COUNTER, 1),
+       PERF_HW("perf:cycles", CPU_CYCLES,
+               CONTEXT_PERF_COUNTER, 1),
+       PERF_HW("perf:stalled-cycles-frontend", STALLED_CYCLES_FRONTEND,
+               CONTEXT_PERF_COUNTER, 1),
+       PERF_HW("perf:idle-cycles-frontend", STALLED_CYCLES_FRONTEND,
+               CONTEXT_PERF_COUNTER, 1),
+       PERF_HW("perf:stalled-cycles-backend", STALLED_CYCLES_BACKEND,
+               CONTEXT_PERF_COUNTER, 1),
+       PERF_HW("perf:idle-cycles-backend", STALLED_CYCLES_BACKEND,
+               CONTEXT_PERF_COUNTER, 1),
+       PERF_HW("perf:instructions", INSTRUCTIONS,
+               CONTEXT_PERF_COUNTER, 1),
+       PERF_HW("perf:cache-references", CACHE_REFERENCES,
+               CONTEXT_PERF_COUNTER, 1),
+       PERF_HW("perf:cache-misses", CACHE_MISSES,
+               CONTEXT_PERF_COUNTER, 1),
+       PERF_HW("perf:branch-instructions", BRANCH_INSTRUCTIONS,
+               CONTEXT_PERF_COUNTER, 1),
+       PERF_HW("perf:branches", BRANCH_INSTRUCTIONS,
+               CONTEXT_PERF_COUNTER, 1),
+       PERF_HW("perf:branch-misses", BRANCH_MISSES,
+               CONTEXT_PERF_COUNTER, 1),
+       PERF_HW("perf:bus-cycles", BUS_CYCLES,
+               CONTEXT_PERF_COUNTER, 1),
+
+       PERF_HW_CACHE("perf:L1-dcache", L1D,
+               CONTEXT_PERF_COUNTER, 1),
+       PERF_HW_CACHE("perf:L1-icache", L1I,
+               CONTEXT_PERF_COUNTER, 1),
+       PERF_HW_CACHE("perf:LLC", LL,
+               CONTEXT_PERF_COUNTER, 1),
+       PERF_HW_CACHE("perf:dTLB", DTLB,
+               CONTEXT_PERF_COUNTER, 1),
+       _PERF_HW_CACHE("perf:iTLB-loads", ITLB,
+               CONTEXT_PERF_COUNTER, READ, ACCESS, 1),
+       _PERF_HW_CACHE("perf:iTLB-load-misses", ITLB,
+               CONTEXT_PERF_COUNTER, READ, MISS, 1),
+       _PERF_HW_CACHE("perf:branch-loads", BPU,
+               CONTEXT_PERF_COUNTER, READ, ACCESS, 1),
+       _PERF_HW_CACHE("perf:branch-load-misses", BPU,
+               CONTEXT_PERF_COUNTER, READ, MISS, 1),
+
+       PERF_SW("perf:cpu-clock", CPU_CLOCK,
+               CONTEXT_PERF_COUNTER, 1),
+       PERF_SW("perf:task-clock", TASK_CLOCK,
+               CONTEXT_PERF_COUNTER, 1),
+       PERF_SW("perf:page-fault", PAGE_FAULTS,
+               CONTEXT_PERF_COUNTER, 1),
+       PERF_SW("perf:faults", PAGE_FAULTS,
+               CONTEXT_PERF_COUNTER, 1),
+       PERF_SW("perf:major-faults", PAGE_FAULTS_MAJ,
+               CONTEXT_PERF_COUNTER, 1),
+       PERF_SW("perf:minor-faults", PAGE_FAULTS_MIN,
+               CONTEXT_PERF_COUNTER, 1),
+       PERF_SW("perf:context-switches", CONTEXT_SWITCHES,
+               CONTEXT_PERF_COUNTER, 1),
+       PERF_SW("perf:cs", CONTEXT_SWITCHES,
+               CONTEXT_PERF_COUNTER, 1),
+       PERF_SW("perf:cpu-migrations", CPU_MIGRATIONS,
+               CONTEXT_PERF_COUNTER, 1),
+       PERF_SW("perf:migrations", CPU_MIGRATIONS,
+               CONTEXT_PERF_COUNTER, 1),
+       PERF_SW("perf:alignment-faults", ALIGNMENT_FAULTS,
+               CONTEXT_PERF_COUNTER, 1),
+       PERF_SW("perf:emulation-faults", EMULATION_FAULTS,
+               CONTEXT_PERF_COUNTER, 1),
+
        { NULL, -1 },           /* Closure */
 };
 
        { NULL, -1 },           /* Closure */
 };
 
+#undef PERF_HW_CACHE
+#undef _PERF_HW_CACHE
 #undef PERF_SW
 #undef PERF_HW
 
 #undef PERF_SW
 #undef PERF_HW
 
@@ -278,17 +468,19 @@ static void print_ctx_type(FILE *ofp)
        fprintf(ofp, "%s", indent);
        len = indent_len;
        while (ctx_opts[i].symbol != NULL) {
        fprintf(ofp, "%s", indent);
        len = indent_len;
        while (ctx_opts[i].symbol != NULL) {
-               if (len > indent_len) {
-                       if (len + strlen(ctx_opts[i].symbol) + 2
-                                       >= PRINT_LINE_LEN) {
-                               fprintf(ofp, ",\n");
-                               fprintf(ofp, "%s", indent);
-                               len = indent_len;
-                       } else {
-                               len += fprintf(ofp, ", ");
+               if (!ctx_opts[i].hide_help) {
+                       if (len > indent_len) {
+                               if (len + strlen(ctx_opts[i].symbol) + 2
+                                               >= PRINT_LINE_LEN) {
+                                       fprintf(ofp, ",\n");
+                                       fprintf(ofp, "%s", indent);
+                                       len = indent_len;
+                               } else {
+                                       len += fprintf(ofp, ", ");
+                               }
                        }
                        }
+                       len += fprintf(ofp, "%s", ctx_opts[i].symbol);
                }
                }
-               len += fprintf(ofp, "%s", ctx_opts[i].symbol);
                i++;
        }
 }
                i++;
        }
 }
@@ -323,10 +515,10 @@ static void usage(FILE *ofp)
        print_ctx_type(ofp);
        fprintf(ofp, "\n");
        fprintf(ofp, "Example:\n");
        print_ctx_type(ofp);
        fprintf(ofp, "\n");
        fprintf(ofp, "Example:\n");
-       fprintf(ofp, "This command will add the context information 'prio' and two perf\n"
-                       "counters (hardware branch misses and cache misses), to all channels\n"
+       fprintf(ofp, "This command will add the context information 'prio' and two per-cpu\n"
+                       "perf counters (hardware branch misses and cache misses), to all channels\n"
                        "in the trace data output:\n");
                        "in the trace data output:\n");
-       fprintf(ofp, "# lttng add-context -k -t prio -t perf:branch-misses -t perf:cache-misses\n");
+       fprintf(ofp, "# lttng add-context -k -t prio -t perf:cpu:branch-misses -t perf:cpu:cache-misses\n");
        fprintf(ofp, "\n");
 }
 
        fprintf(ofp, "\n");
 }
 
@@ -382,7 +574,10 @@ static int add_context(char *session_name)
        /* Iterate over all the context types given */
        cds_list_for_each_entry(type, &ctx_type_list.head, list) {
                context.ctx = (enum lttng_event_context_type) type->opt->ctx_type;
        /* Iterate over all the context types given */
        cds_list_for_each_entry(type, &ctx_type_list.head, list) {
                context.ctx = (enum lttng_event_context_type) type->opt->ctx_type;
-               if (context.ctx == LTTNG_EVENT_CONTEXT_PERF_COUNTER) {
+               switch (context.ctx) {
+               case LTTNG_EVENT_CONTEXT_PERF_COUNTER:
+               case LTTNG_EVENT_CONTEXT_PERF_CPU_COUNTER:
+               case LTTNG_EVENT_CONTEXT_PERF_THREAD_COUNTER:
                        context.u.perf_counter.type = type->opt->u.perf.type;
                        context.u.perf_counter.config = type->opt->u.perf.config;
                        strncpy(context.u.perf_counter.name, type->opt->symbol,
                        context.u.perf_counter.type = type->opt->u.perf.type;
                        context.u.perf_counter.config = type->opt->u.perf.config;
                        strncpy(context.u.perf_counter.name, type->opt->symbol,
@@ -395,6 +590,9 @@ static int add_context(char *session_name)
                        while ((ptr = strchr(context.u.perf_counter.name, ':')) != NULL) {
                                *ptr = '_';
                        }
                        while ((ptr = strchr(context.u.perf_counter.name, ':')) != NULL) {
                                *ptr = '_';
                        }
+                       break;
+               default:
+                       break;
                }
                DBG("Adding context...");
 
                }
                DBG("Adding context...");
 
index 5ea3e1ae12a122761750c291a7240708b4c36469..d153a1cff7dafbbc3460f7aac1baae55042263fd 100644 (file)
@@ -188,7 +188,7 @@ int kernctl_add_context(int fd, struct lttng_kernel_context *ctx)
 
                old_ctx.ctx = ctx->ctx;
                /* only type that uses the union */
 
                old_ctx.ctx = ctx->ctx;
                /* only type that uses the union */
-               if (ctx->ctx == LTTNG_KERNEL_CONTEXT_PERF_COUNTER) {
+               if (ctx->ctx == LTTNG_KERNEL_CONTEXT_PERF_CPU_COUNTER) {
                        old_ctx.u.perf_counter.type =
                                ctx->u.perf_counter.type;
                        old_ctx.u.perf_counter.config =
                        old_ctx.u.perf_counter.type =
                                ctx->u.perf_counter.type;
                        old_ctx.u.perf_counter.config =
index 38a9038f61595137877f2bf0c1540c6f7271b355..b242251907dce7746cc117cb5e4f6c3469499457 100644 (file)
@@ -43,7 +43,7 @@ enum lttng_kernel_instrumentation {
 
 enum lttng_kernel_context_type {
        LTTNG_KERNEL_CONTEXT_PID            = 0,
 
 enum lttng_kernel_context_type {
        LTTNG_KERNEL_CONTEXT_PID            = 0,
-       LTTNG_KERNEL_CONTEXT_PERF_COUNTER   = 1,
+       LTTNG_KERNEL_CONTEXT_PERF_CPU_COUNTER = 1,
        LTTNG_KERNEL_CONTEXT_PROCNAME       = 2,
        LTTNG_KERNEL_CONTEXT_PRIO           = 3,
        LTTNG_KERNEL_CONTEXT_NICE           = 4,
        LTTNG_KERNEL_CONTEXT_PROCNAME       = 2,
        LTTNG_KERNEL_CONTEXT_PRIO           = 3,
        LTTNG_KERNEL_CONTEXT_NICE           = 4,
This page took 0.037246 seconds and 4 git commands to generate.