From: Mathieu Desnoyers Date: Mon, 17 Feb 2014 01:00:31 +0000 (-0500) Subject: Implement LTTng-UST perf counters support X-Git-Tag: v2.5.0-rc1~64 X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=commitdiff_plain;h=aa3514e96f12c13f681a81ea275dc51dd63473c8 Implement LTTng-UST perf counters support 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 Signed-off-by: David Goulet --- diff --git a/doc/man/lttng.1 b/doc/man/lttng.1 index 988208395..9f95a8a13 100644 --- a/doc/man/lttng.1 +++ b/doc/man/lttng.1 @@ -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 -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 -# 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. +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). @@ -160,9 +165,9 @@ counters). # 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; diff --git a/include/lttng/lttng.h b/include/lttng/lttng.h index f0be224b5..e59b2d31d 100644 --- a/include/lttng/lttng.h +++ b/include/lttng/lttng.h @@ -132,7 +132,7 @@ enum lttng_event_output { /* 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, @@ -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_PERF_CPU_COUNTER = 13, + LTTNG_EVENT_CONTEXT_PERF_THREAD_COUNTER = 14, }; enum lttng_calibrate_type { diff --git a/src/bin/lttng-sessiond/context.c b/src/bin/lttng-sessiond/context.c index 6aacbad0e..1b87df2e9 100644 --- a/src/bin/lttng-sessiond/context.c +++ b/src/bin/lttng-sessiond/context.c @@ -92,13 +92,19 @@ static int add_uctx_to_channel(struct ltt_ust_session *usess, int domain, { 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); + /* 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) { @@ -120,17 +126,8 @@ static int add_uctx_to_channel(struct ltt_ust_session *usess, int domain, 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 */ - 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); @@ -140,6 +137,7 @@ static int add_uctx_to_channel(struct ltt_ust_session *usess, int domain, error: free(uctx); +duplicate: 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_PERF_COUNTER: - kctx.ctx = LTTNG_KERNEL_CONTEXT_PERF_COUNTER; - 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_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; } diff --git a/src/bin/lttng-sessiond/lttng-ust-abi.h b/src/bin/lttng-sessiond/lttng-ust-abi.h index a3298caa2..81b61492a 100644 --- a/src/bin/lttng-sessiond/lttng-ust-abi.h +++ b/src/bin/lttng-sessiond/lttng-ust-abi.h @@ -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_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 { @@ -149,6 +156,7 @@ struct lttng_ust_context { char padding[LTTNG_UST_CONTEXT_PADDING1]; union { + struct lttng_ust_perf_counter_ctx perf_counter; char padding[LTTNG_UST_CONTEXT_PADDING2]; } u; } LTTNG_PACKED; diff --git a/src/bin/lttng-sessiond/trace-ust.c b/src/bin/lttng-sessiond/trace-ust.c index dfbbcd777..96225a21b 100644 --- a/src/bin/lttng-sessiond/trace-ust.c +++ b/src/bin/lttng-sessiond/trace-ust.c @@ -414,20 +414,12 @@ error: 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; @@ -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_PERF_THREAD_COUNTER: + utype = LTTNG_UST_CONTEXT_PERF_THREAD_COUNTER; + break; 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; } @@ -454,9 +508,19 @@ struct ltt_ust_context *trace_ust_create_context( 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); - CDS_INIT_LIST_HEAD(&uctx->list); return uctx; diff --git a/src/bin/lttng-sessiond/trace-ust.h b/src/bin/lttng-sessiond/trace-ust.h index bac5c328b..86f8d40b1 100644 --- a/src/bin/lttng-sessiond/trace-ust.h +++ b/src/bin/lttng-sessiond/trace-ust.h @@ -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); +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); @@ -237,6 +239,12 @@ struct ltt_ust_context *trace_ust_create_context( { 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) diff --git a/src/bin/lttng-sessiond/ust-app.c b/src/bin/lttng-sessiond/ust-app.c index e029b42d8..fc744fc02 100644 --- a/src/bin/lttng-sessiond/ust-app.c +++ b/src/bin/lttng-sessiond/ust-app.c @@ -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_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); } @@ -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_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); diff --git a/src/bin/lttng/commands/add_context.c b/src/bin/lttng/commands/add_context.c index 6483c9891..405b7828f 100644 --- a/src/bin/lttng/commands/add_context.c +++ b/src/bin/lttng/commands/add_context.c @@ -56,7 +56,7 @@ static struct lttng_handle *handle; */ 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, @@ -68,6 +68,8 @@ enum context_type { 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 */ -#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, },\ } -#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, },\ } -#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 \ @@ -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; + int hide_help; /* Hide from --help */ union { struct { uint32_t type; @@ -205,46 +214,227 @@ const struct ctx_opts { { "vppid", CONTEXT_VPPID }, { "hostname", CONTEXT_HOSTNAME }, { "ip", CONTEXT_IP }, + /* 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 */ }; +#undef PERF_HW_CACHE +#undef _PERF_HW_CACHE #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) { - 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++; } } @@ -323,10 +515,10 @@ static void usage(FILE *ofp) 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"); - 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"); } @@ -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; - 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, @@ -395,6 +590,9 @@ static int add_context(char *session_name) while ((ptr = strchr(context.u.perf_counter.name, ':')) != NULL) { *ptr = '_'; } + break; + default: + break; } DBG("Adding context..."); diff --git a/src/common/kernel-ctl/kernel-ctl.c b/src/common/kernel-ctl/kernel-ctl.c index 5ea3e1ae1..d153a1cff 100644 --- a/src/common/kernel-ctl/kernel-ctl.c +++ b/src/common/kernel-ctl/kernel-ctl.c @@ -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 */ - 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 = diff --git a/src/common/lttng-kernel.h b/src/common/lttng-kernel.h index 38a9038f6..b24225190 100644 --- a/src/common/lttng-kernel.h +++ b/src/common/lttng-kernel.h @@ -43,7 +43,7 @@ enum lttng_kernel_instrumentation { 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,