All of lore.kernel.org
 help / color / mirror / Atom feed
From: Tom Zanussi <tom.zanussi@linux.intel.com>
To: Namhyung Kim <namhyung@kernel.org>
Cc: rostedt@goodmis.org, tglx@linutronix.de, mhiramat@kernel.org,
	vedang.patel@intel.com, bigeasy@linutronix.de,
	joel.opensrc@gmail.com, joelaf@google.com,
	mathieu.desnoyers@efficios.com, baohong.liu@intel.com,
	rajvi.jingar@intel.com, julia@ni.com, fengguang.wu@intel.com,
	linux-kernel@vger.kernel.org, linux-rt-users@vger.kernel.org,
	kernel-team@lge.com
Subject: Re: [PATCH v6 27/37] tracing: Add 'onmax' hist trigger action support
Date: Wed, 29 Nov 2017 14:53:06 -0600	[thread overview]
Message-ID: <1511988786.31570.13.camel@tzanussi-mobl.amr.corp.intel.com> (raw)
In-Reply-To: <20171123050903.GA25472@sejong>

Hi Namhyung,

Sorry for the delayed response - was out on vacation..

On Thu, 2017-11-23 at 14:09 +0900, Namhyung Kim wrote:
> On Fri, Nov 17, 2017 at 02:33:06PM -0600, Tom Zanussi wrote:
> > Add an 'onmax(var).save(field,...)' hist trigger action which is
> > invoked whenever an event exceeds the current maximum.
> > 
> > The end result is that the trace event fields or variables specified
> > as the onmax.save() params will be saved if 'var' exceeds the current
> > maximum for that hist trigger entry.  This allows context from the
> > event that exhibited the new maximum to be saved for later reference.
> > When the histogram is displayed, additional fields displaying the
> > saved values will be printed.
> > 
> > As an example the below defines a couple of hist triggers, one for
> > sched_wakeup and another for sched_switch, keyed on pid.  Whenever a
> > sched_wakeup occurs, the timestamp is saved in the entry corresponding
> > to the current pid, and when the scheduler switches back to that pid,
> > the timestamp difference is calculated.  If the resulting latency
> > exceeds the current maximum latency, the specified save() values are
> > saved:
> > 
> >     # echo 'hist:keys=pid:ts0=$common_timestamp.usecs \
> >         if comm=="cyclictest"' >> \
> >       /sys/kernel/debug/tracing/events/sched/sched_wakeup/trigger
> > 
> >     # echo 'hist:keys=next_pid:\
> >       wakeup_lat=$common_timestamp.usecs-$ts0:\
> >       onmax($wakeup_lat).save(next_comm,prev_pid,prev_prio,prev_comm) \
> >         if next_comm=="cyclictest"' >> \
> >       /sys/kernel/debug/tracing/events/sched/sched_switch/trigger
> > 
> > When the histogram is displayed, the max value and the saved values
> > corresponding to the max are displayed following the rest of the
> > fields:
> > 
> >     # cat /sys/kernel/debug/tracing/events/sched/sched_switch/hist
> > 
> >       { next_pid:       3728 } hitcount:        199 \
> >         max:        123  next_comm: cyclictest  prev_pid:          0 \
> > 	prev_prio:        120  prev_comm: swapper/3
> >       { next_pid:       3730 } hitcount:       1321 \
> >         max:         15  next_comm: cyclictest  prev_pid:          0 \
> > 	prev_prio:        120  prev_comm: swapper/1
> >       { next_pid:       3729 } hitcount:       1973\
> >         max:         25  next_comm: cyclictest  prev_pid:          0  \
> > 	prev_prio:        120  prev_comm: swapper/0
> > 
> >     Totals:
> >         Hits: 3493
> >         Entries: 3
> > 	Dropped: 0
> > 
> > Signed-off-by: Tom Zanussi <tom.zanussi@linux.intel.com>
> > ---
> 
> [SNIP]
> > +static int onmax_create(struct hist_trigger_data *hist_data,
> > +			struct action_data *data)
> > +{
> > +	struct trace_event_call *call = hist_data->event_file->event_call;
> > +	struct trace_event_file *file = hist_data->event_file;
> > +	struct hist_field *var_field, *ref_field, *max_var;
> > +	unsigned int var_ref_idx = hist_data->n_var_refs;
> > +	struct field_var *field_var;
> > +	char *onmax_var_str, *param;
> > +	const char *event_name;
> > +	unsigned long flags;
> > +	unsigned int i;
> > +	int ret = 0;
> > +
> > +	onmax_var_str = data->onmax.var_str;
> > +	if (onmax_var_str[0] != '$')
> > +		return -EINVAL;
> > +	onmax_var_str++;
> > +
> > +	event_name = trace_event_name(call);
> 
> It seems not used.
> 
> 
> > +	var_field = find_target_event_var(hist_data, NULL, NULL, onmax_var_str);
> > +	if (!var_field)
> > +		return -EINVAL;
> > +
> > +	flags = HIST_FIELD_FL_VAR_REF;
> > +	ref_field = create_hist_field(hist_data, NULL, flags, NULL);
> > +	if (!ref_field)
> > +		return -ENOMEM;
> > +
> > +	if (init_var_ref(ref_field, var_field, NULL, NULL)) {
> > +		destroy_hist_field(ref_field, 0);
> > +		ret = -ENOMEM;
> > +		goto out;
> > +	}
> > +	hist_data->var_refs[hist_data->n_var_refs] = ref_field;
> > +	ref_field->var_ref_idx = hist_data->n_var_refs++;
> > +	data->onmax.var = ref_field;
> 
> I was confused that this could create a reference to self-variable
> which would prevent a hist from being freed.  IIUC it tries to avoid
> such a self reference by using local field variable and disallowing
> variable of expression, right?
> 
> But it seems that's not the case since the reference is saved in other
> place than hist_data->fields which is used in find_var_ref().
> 

The onmax processing only allows a variable defined on the target to be
used in the onmax(), so yes it can only be a 'self' variable defined on
the same trigger.  But that variable can reference variables in an
expression e.g. where ts0 is a variable on another trigger: 

  wakeup_lat=$common_timestamp.usecs-$ts0:onmax($wakeup_lat).save(...)

The reference to $ts0 prevents that other trigger from going away, just
as a further event referencing $wakeup_lat would prevent the onmax()
trigger from going away - both of these cases are covered by the
find_var_ref() code.

But if the only trigger that accesses the $wakeup_lat is the onmax()
trigger itself, then it's ok to free that trigger.

Hope that answers your question about this..

Thanks,

Tom

> 
> > +
> > +	data->fn = onmax_save;
> > +	data->onmax.max_var_ref_idx = var_ref_idx;
> > +	max_var = create_var(hist_data, file, "max", sizeof(u64), "u64");
> > +	if (IS_ERR(max_var)) {
> > +		ret = PTR_ERR(max_var);
> > +		goto out;
> > +	}
> > +	data->onmax.max_var = max_var;
> > +
> > +	for (i = 0; i < data->n_params; i++) {
> > +		param = kstrdup(data->params[i], GFP_KERNEL);
> > +		if (!param) {
> > +			ret = -ENOMEM;
> > +			goto out;
> > +		}
> > +
> > +		field_var = create_target_field_var(hist_data, NULL, NULL, param);
> > +		if (IS_ERR(field_var)) {
> > +			ret = PTR_ERR(field_var);
> > +			kfree(param);
> > +			goto out;
> > +		}
> > +
> > +		hist_data->max_vars[hist_data->n_max_vars++] = field_var;
> > +		if (field_var->val->flags & HIST_FIELD_FL_STRING)
> > +			hist_data->n_max_var_str++;
> > +
> > +		kfree(param);
> > +	}
> > + out:
> > +	return ret;
> > +}
> > +
> 
> [SNIP]
> > +static struct action_data *onmax_parse(char *str)
> > +{
> > +	char *onmax_fn_name, *onmax_var_str;
> > +	struct action_data *data;
> > +	int ret = -EINVAL;
> > +
> > +	data = kzalloc(sizeof(*data), GFP_KERNEL);
> > +	if (!data)
> > +		return ERR_PTR(-ENOMEM);
> > +
> > +	onmax_var_str = strsep(&str, ")");
> > +	if (!onmax_var_str || !str)
> > +		return ERR_PTR(-EINVAL);
> 
> 'data' leaked.
> 
> Thanks,
> Namhyung
> 
> 
> > +	data->onmax.var_str = kstrdup(onmax_var_str, GFP_KERNEL);
> > +	if (!data->onmax.var_str) {
> > +		ret = -ENOMEM;
> > +		goto free;
> > +	}
> > +
> > +	strsep(&str, ".");
> > +	if (!str)
> > +		goto free;
> > +
> > +	onmax_fn_name = strsep(&str, "(");
> > +	if (!onmax_fn_name || !str)
> > +		goto free;
> > +
> > +	if (strncmp(onmax_fn_name, "save", strlen("save")) == 0) {
> > +		char *params = strsep(&str, ")");
> > +
> > +		if (!params) {
> > +			ret = -EINVAL;
> > +			goto free;
> > +		}
> > +
> > +		ret = parse_action_params(params, data);
> > +		if (ret)
> > +			goto free;
> > +	} else
> > +		goto free;
> > +
> > +	data->onmax.fn_name = kstrdup(onmax_fn_name, GFP_KERNEL);
> > +	if (!data->onmax.fn_name) {
> > +		ret = -ENOMEM;
> > +		goto free;
> > +	}
> > + out:
> > +	return data;
> > + free:
> > +	onmax_destroy(data);
> > +	data = ERR_PTR(ret);
> > +	goto out;
> > +}

  reply	other threads:[~2017-11-29 20:53 UTC|newest]

Thread overview: 50+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-11-17 20:32 [PATCH v6 00/37] tracing: Inter-event (e.g. latency) support Tom Zanussi
2017-11-17 20:32 ` [PATCH v6 01/37] tracing: Move hist trigger Documentation to histogram.txt Tom Zanussi
2017-11-17 20:32 ` [PATCH v6 02/37] tracing: Add Documentation for log2 modifier Tom Zanussi
2017-11-17 20:32 ` [PATCH v6 03/37] tracing: Add support to detect and avoid duplicates Tom Zanussi
2017-11-17 20:32 ` [PATCH v6 04/37] tracing: Remove code which merges duplicates Tom Zanussi
2017-11-17 20:32 ` [PATCH v6 05/37] ring-buffer: Add interface for setting absolute time stamps Tom Zanussi
2017-11-17 20:32 ` [PATCH v6 06/37] ring-buffer: Redefine the unimplemented RINGBUF_TYPE_TIME_STAMP Tom Zanussi
2017-11-17 20:32 ` [PATCH v6 07/37] tracing: Add timestamp_mode trace file Tom Zanussi
2017-11-17 20:32 ` [PATCH v6 08/37] tracing: Give event triggers access to ring_buffer_event Tom Zanussi
2017-11-17 20:32 ` [PATCH v6 09/37] tracing: Add ring buffer event param to hist field functions Tom Zanussi
2017-11-17 20:32 ` [PATCH v6 10/37] tracing: Break out hist trigger assignment parsing Tom Zanussi
2017-11-17 20:32 ` [PATCH v6 11/37] tracing: Add hist trigger timestamp support Tom Zanussi
2017-11-17 20:32 ` [PATCH v6 12/37] tracing: Add per-element variable support to tracing_map Tom Zanussi
2017-11-17 20:32 ` [PATCH v6 13/37] tracing: Add hist_data member to hist_field Tom Zanussi
2017-11-17 20:32 ` [PATCH v6 14/37] tracing: Add usecs modifier for hist trigger timestamps Tom Zanussi
2017-11-17 20:32 ` [PATCH v6 15/37] tracing: Add variable support to hist triggers Tom Zanussi
2017-11-17 20:32 ` [PATCH v6 16/37] tracing: Account for variables in named trigger compatibility Tom Zanussi
2017-11-17 20:32 ` [PATCH v6 17/37] tracing: Move get_hist_field_flags() Tom Zanussi
2017-11-17 20:32 ` [PATCH v6 18/37] tracing: Add simple expression support to hist triggers Tom Zanussi
2017-11-20  6:05   ` Namhyung Kim
2017-11-17 20:32 ` [PATCH v6 19/37] tracing: Generalize per-element hist trigger data Tom Zanussi
2017-11-17 20:32 ` [PATCH v6 20/37] tracing: Pass tracing_map_elt to hist_field accessor functions Tom Zanussi
2017-11-17 20:33 ` [PATCH v6 21/37] tracing: Add hist_field 'type' field Tom Zanussi
2017-11-17 20:33 ` [PATCH v6 22/37] tracing: Add variable reference handling to hist triggers Tom Zanussi
2017-11-21 10:53   ` Namhyung Kim
2017-11-17 20:33 ` [PATCH v6 23/37] tracing: Add hist trigger action hook Tom Zanussi
2017-11-17 20:33 ` [PATCH v6 24/37] tracing: Add support for 'synthetic' events Tom Zanussi
2017-11-21 11:32   ` Namhyung Kim
2017-11-17 20:33 ` [PATCH v6 25/37] tracing: Add support for 'field variables' Tom Zanussi
2017-11-21 12:08   ` Namhyung Kim
2017-11-22  6:05   ` Namhyung Kim
2017-11-17 20:33 ` [PATCH v6 26/37] tracing: Add 'onmatch' hist trigger action support Tom Zanussi
2017-11-22  9:49   ` Namhyung Kim
2017-11-17 20:33 ` [PATCH v6 27/37] tracing: Add 'onmax' " Tom Zanussi
2017-11-23  5:09   ` Namhyung Kim
2017-11-29 20:53     ` Tom Zanussi [this message]
2017-11-17 20:33 ` [PATCH v6 28/37] tracing: Allow whitespace to surround hist trigger filter Tom Zanussi
2017-11-17 20:33 ` [PATCH v6 29/37] tracing: Add cpu field for hist triggers Tom Zanussi
2017-11-23  5:25   ` Namhyung Kim
2017-11-29 21:02     ` Tom Zanussi
2017-11-17 20:33 ` [PATCH v6 30/37] tracing: Add hist trigger support for variable reference aliases Tom Zanussi
2017-11-17 20:33 ` [PATCH v6 31/37] tracing: Add 'last error' error facility for hist triggers Tom Zanussi
2017-11-23  6:22   ` Namhyung Kim
2017-11-17 20:33 ` [PATCH v6 32/37] tracing: Add inter-event hist trigger Documentation Tom Zanussi
2017-11-17 20:33 ` [PATCH v6 33/37] tracing: Make tracing_set_clock() non-static Tom Zanussi
2017-11-17 20:33 ` [PATCH v6 34/37] tracing: Add a clock attribute for hist triggers Tom Zanussi
2017-11-17 20:33 ` [PATCH v6 35/37] tracing: Increase trace_recursive_lock() limit for synthetic events Tom Zanussi
2017-11-17 20:33 ` [PATCH v6 36/37] tracing: Add inter-event blurb to HIST_TRIGGERS config option Tom Zanussi
2017-11-23  6:57   ` Namhyung Kim
2017-11-17 20:33 ` [PATCH v6 37/37] selftests: ftrace: Add inter-event hist triggers testcases Tom Zanussi

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1511988786.31570.13.camel@tzanussi-mobl.amr.corp.intel.com \
    --to=tom.zanussi@linux.intel.com \
    --cc=baohong.liu@intel.com \
    --cc=bigeasy@linutronix.de \
    --cc=fengguang.wu@intel.com \
    --cc=joel.opensrc@gmail.com \
    --cc=joelaf@google.com \
    --cc=julia@ni.com \
    --cc=kernel-team@lge.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-rt-users@vger.kernel.org \
    --cc=mathieu.desnoyers@efficios.com \
    --cc=mhiramat@kernel.org \
    --cc=namhyung@kernel.org \
    --cc=rajvi.jingar@intel.com \
    --cc=rostedt@goodmis.org \
    --cc=tglx@linutronix.de \
    --cc=vedang.patel@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.