| From: Tom Zanussi <tom.zanussi@linux.intel.com> |
| Date: Tue, 5 Sep 2017 16:57:51 -0500 |
| Subject: [PATCH 39/40] tracing: Add a clock attribute for hist triggers |
| |
| The default clock if timestamps are used in a histogram is "global". |
| If timestamps aren't used, the clock is irrelevant. |
| |
| Use the "clock=" param only if you want to override the default |
| "global" clock for a histogram with timestamps. |
| |
| Signed-off-by: Tom Zanussi <tom.zanussi@linux.intel.com> |
| Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> |
| --- |
| Documentation/trace/events.txt | 9 +++++++++ |
| kernel/trace/trace_events_hist.c | 34 +++++++++++++++++++++++++++++++--- |
| 2 files changed, 40 insertions(+), 3 deletions(-) |
| |
| --- a/Documentation/trace/events.txt |
| +++ b/Documentation/trace/events.txt |
| @@ -2173,6 +2173,15 @@ specification. In support of this overa |
| default it is in units of nanoseconds; appending '.usecs' to a |
| common_timestamp field changes the units to microseconds. |
| |
| +A note on inter-event timestamps: If $common_timestamp is used in a |
| +histogram, the trace buffer is automatically switched over to using |
| +absolute timestamps and the "global" trace clock, in order to avoid |
| +bogus timestamp differences with other clocks that aren't coherent |
| +across CPUs. This can be overridden by specifying one of the other |
| +trace clocks instead, using the "clock=XXX" hist trigger attribute, |
| +where XXX is any of the clocks listed in the tracing/trace_clock |
| +pseudo-file. |
| + |
| These features are decribed in more detail in the following sections. |
| |
| 6.3.1 Histogram Variables |
| --- a/kernel/trace/trace_events_hist.c |
| +++ b/kernel/trace/trace_events_hist.c |
| @@ -241,6 +241,7 @@ struct hist_trigger_attrs { |
| char *vals_str; |
| char *sort_key_str; |
| char *name; |
| + char *clock; |
| bool pause; |
| bool cont; |
| bool clear; |
| @@ -1701,6 +1702,7 @@ static void destroy_hist_trigger_attrs(s |
| kfree(attrs->sort_key_str); |
| kfree(attrs->keys_str); |
| kfree(attrs->vals_str); |
| + kfree(attrs->clock); |
| kfree(attrs); |
| } |
| |
| @@ -1740,7 +1742,16 @@ static int parse_assignment(char *str, s |
| attrs->sort_key_str = kstrdup(str, GFP_KERNEL); |
| else if (strncmp(str, "name=", strlen("name=")) == 0) |
| attrs->name = kstrdup(str, GFP_KERNEL); |
| - else if (strncmp(str, "size=", strlen("size=")) == 0) { |
| + else if (strncmp(str, "clock=", strlen("clock=")) == 0) { |
| + strsep(&str, "="); |
| + if (!str) { |
| + ret = -EINVAL; |
| + goto out; |
| + } |
| + |
| + str = strstrip(str); |
| + attrs->clock = kstrdup(str, GFP_KERNEL); |
| + } else if (strncmp(str, "size=", strlen("size=")) == 0) { |
| int map_bits = parse_map_size(str); |
| |
| if (map_bits < 0) { |
| @@ -1803,6 +1814,12 @@ static struct hist_trigger_attrs *parse_ |
| goto free; |
| } |
| |
| + if (!attrs->clock) { |
| + attrs->clock = kstrdup("global", GFP_KERNEL); |
| + if (!attrs->clock) |
| + goto free; |
| + } |
| + |
| return attrs; |
| free: |
| destroy_hist_trigger_attrs(attrs); |
| @@ -4644,6 +4661,8 @@ static int event_hist_trigger_print(stru |
| seq_puts(m, ".descending"); |
| } |
| seq_printf(m, ":size=%u", (1 << hist_data->map->map_bits)); |
| + if (hist_data->enable_timestamps) |
| + seq_printf(m, ":clock=%s", hist_data->attrs->clock); |
| |
| print_actions_spec(m, hist_data); |
| |
| @@ -4907,10 +4926,19 @@ static int hist_register_trigger(char *g |
| goto out; |
| } |
| |
| - ret++; |
| + if (hist_data->enable_timestamps) { |
| + char *clock = hist_data->attrs->clock; |
| + |
| + ret = tracing_set_clock(file->tr, hist_data->attrs->clock); |
| + if (ret) { |
| + hist_err("Couldn't set trace_clock: ", clock); |
| + goto out; |
| + } |
| |
| - if (hist_data->enable_timestamps) |
| tracing_set_time_stamp_abs(file->tr, true); |
| + } |
| + |
| + ret++; |
| out: |
| return ret; |
| } |