From: Tom Zanussi Date: Wed, 6 Dec 2017 16:38:10 -0600 Subject: [PATCH 29/37] tracing: Add cpu field for hist triggers Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.14/older/patches-4.14.6-rt7.tar.xz A common key to use in a histogram is the cpuid - add a new cpu 'synthetic' field named 'cpu' for that purpose. Signed-off-by: Tom Zanussi Signed-off-by: Sebastian Andrzej Siewior --- Documentation/trace/histogram.txt | 15 +++++++++++++++ kernel/trace/trace_events_hist.c | 28 +++++++++++++++++++++++++++- 2 files changed, 42 insertions(+), 1 deletion(-) --- a/Documentation/trace/histogram.txt +++ b/Documentation/trace/histogram.txt @@ -172,6 +172,21 @@ The examples below provide a more concrete illustration of the concepts and typical usage patterns discussed above. + 'special' event fields + ------------------------ + + There are a number of 'special event fields' available for use as + keys or values in a hist trigger. These look like and behave as if + they were actual event fields, but aren't really part of the event's + field definition or format file. They are however available for any + event, and can be used anywhere an actual event field could be. + They are: + + common_timestamp u64 - timestamp (from ring buffer) associated + with the event, in nanoseconds. May be + modified by .usecs to have timestamps + interpreted as microseconds. + cpu int - the cpu on which the event occurred. 6.2 'hist' trigger examples --------------------------- --- a/kernel/trace/trace_events_hist.c +++ b/kernel/trace/trace_events_hist.c @@ -227,6 +227,7 @@ enum hist_field_flags { HIST_FIELD_FL_VAR = 1 << 12, HIST_FIELD_FL_EXPR = 1 << 13, HIST_FIELD_FL_VAR_REF = 1 << 14, + HIST_FIELD_FL_CPU = 1 << 15, }; struct var_defs { @@ -1168,6 +1169,16 @@ static u64 hist_field_timestamp(struct h return ts; } +static u64 hist_field_cpu(struct hist_field *hist_field, + struct tracing_map_elt *elt, + struct ring_buffer_event *rbe, + void *event) +{ + int cpu = smp_processor_id(); + + return cpu; +} + static struct hist_field * check_field_for_var_ref(struct hist_field *hist_field, struct hist_trigger_data *var_data, @@ -1619,6 +1630,8 @@ static const char *hist_field_name(struc field_name = hist_field_name(field->operands[0], ++level); else if (field->flags & HIST_FIELD_FL_TIMESTAMP) field_name = "common_timestamp"; + else if (field->flags & HIST_FIELD_FL_CPU) + field_name = "cpu"; else if (field->flags & HIST_FIELD_FL_EXPR || field->flags & HIST_FIELD_FL_VAR_REF) { if (field->system) { @@ -2124,6 +2137,15 @@ static struct hist_field *create_hist_fi goto out; } + if (flags & HIST_FIELD_FL_CPU) { + hist_field->fn = hist_field_cpu; + hist_field->size = sizeof(int); + hist_field->type = kstrdup("unsigned int", GFP_KERNEL); + if (!hist_field->type) + goto free; + goto out; + } + if (WARN_ON_ONCE(!field)) goto out; @@ -2358,7 +2380,9 @@ parse_field(struct hist_trigger_data *hi hist_data->enable_timestamps = true; if (*flags & HIST_FIELD_FL_TIMESTAMP_USECS) hist_data->attrs->ts_in_usecs = true; - } else { + } else if (strcmp(field_name, "cpu") == 0) + *flags |= HIST_FIELD_FL_CPU; + else { field = trace_find_event_field(file->event_call, field_name); if (!field || !field->size) { field = ERR_PTR(-EINVAL); @@ -4634,6 +4658,8 @@ static void hist_field_print(struct seq_ if (hist_field->flags & HIST_FIELD_FL_TIMESTAMP) seq_puts(m, "common_timestamp"); + else if (hist_field->flags & HIST_FIELD_FL_CPU) + seq_puts(m, "cpu"); else if (field_name) { if (hist_field->flags & HIST_FIELD_FL_VAR_REF) seq_putc(m, '$');