Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4f41c013 authored by Peter Zijlstra's avatar Peter Zijlstra Committed by Ingo Molnar
Browse files

perf/ftrace: Optimize perf/tracepoint interaction for single events



When we've got but a single event per tracepoint
there is no reason to try and multiplex it so don't.

Signed-off-by: default avatarPeter Zijlstra <a.p.zijlstra@chello.nl>
Tested-by: default avatarIngo Molnar <mingo@elte.hu>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
LKML-Reference: <new-submission>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent ef4f30f5
Loading
Loading
Loading
Loading
+5 −3
Original line number Diff line number Diff line
@@ -132,6 +132,7 @@ struct ftrace_event_call {
	void			*data;

	int			perf_refcount;
	void			*perf_data;
	int			(*perf_event_enable)(struct ftrace_event_call *);
	void			(*perf_event_disable)(struct ftrace_event_call *);
};
@@ -190,7 +191,7 @@ struct perf_event;

DECLARE_PER_CPU(struct pt_regs, perf_trace_regs);

extern int perf_trace_enable(int event_id);
extern int perf_trace_enable(int event_id, void *data);
extern void perf_trace_disable(int event_id);
extern int ftrace_profile_set_filter(struct perf_event *event, int event_id,
				     char *filter_str);
@@ -201,11 +202,12 @@ perf_trace_buf_prepare(int size, unsigned short type, int *rctxp,

static inline void
perf_trace_buf_submit(void *raw_data, int size, int rctx, u64 addr,
		       u64 count, unsigned long irq_flags, struct pt_regs *regs)
		       u64 count, unsigned long irq_flags, struct pt_regs *regs,
		       void *event)
{
	struct trace_entry *entry = raw_data;

	perf_tp_event(entry->type, addr, count, raw_data, size, regs);
	perf_tp_event(entry->type, addr, count, raw_data, size, regs, event);
	perf_swevent_put_recursion_context(rctx);
	local_irq_restore(irq_flags);
}
+1 −1
Original line number Diff line number Diff line
@@ -994,7 +994,7 @@ static inline bool perf_paranoid_kernel(void)

extern void perf_event_init(void);
extern void perf_tp_event(int event_id, u64 addr, u64 count, void *record,
			  int entry_size, struct pt_regs *regs);
			  int entry_size, struct pt_regs *regs, void *event);
extern void perf_bp_event(struct perf_event *event, void *data);

#ifndef perf_misc_flags
+2 −1
Original line number Diff line number Diff line
@@ -785,7 +785,8 @@ perf_trace_templ_##call(struct ftrace_event_call *event_call, \
	{ assign; }							\
									\
	perf_trace_buf_submit(entry, __entry_size, rctx, __addr,	\
			       __count, irq_flags, __regs);		\
			       __count, irq_flags, __regs, 		\
			      event_call->perf_data);			\
}

#undef DEFINE_EVENT
+10 −5
Original line number Diff line number Diff line
@@ -4468,8 +4468,9 @@ static int swevent_hlist_get(struct perf_event *event)
#ifdef CONFIG_EVENT_TRACING

void perf_tp_event(int event_id, u64 addr, u64 count, void *record,
		   int entry_size, struct pt_regs *regs)
		   int entry_size, struct pt_regs *regs, void *event)
{
	const int type = PERF_TYPE_TRACEPOINT;
	struct perf_sample_data data;
	struct perf_raw_record raw = {
		.size = entry_size,
@@ -4479,9 +4480,13 @@ void perf_tp_event(int event_id, u64 addr, u64 count, void *record,
	perf_sample_data_init(&data, addr);
	data.raw = &raw;

	/* Trace events already protected against recursion */
	do_perf_sw_event(PERF_TYPE_TRACEPOINT, event_id, count, 1,
			 &data, regs);
	if (!event) {
		do_perf_sw_event(type, event_id, count, 1, &data, regs);
		return;
	}

	if (perf_swevent_match(event, type, event_id, &data, regs))
		perf_swevent_add(event, count, 1, &data, regs);
}
EXPORT_SYMBOL_GPL(perf_tp_event);

@@ -4514,7 +4519,7 @@ static const struct pmu *tp_perf_event_init(struct perf_event *event)
			!capable(CAP_SYS_ADMIN))
		return ERR_PTR(-EPERM);

	if (perf_trace_enable(event->attr.config))
	if (perf_trace_enable(event->attr.config, event))
		return NULL;

	event->destroy = tp_perf_event_destroy;
+7 −4
Original line number Diff line number Diff line
@@ -27,13 +27,15 @@ typedef typeof(unsigned long [PERF_MAX_TRACE_SIZE / sizeof(unsigned long)])
/* Count the events in use (per event id, not per instance) */
static int	total_ref_count;

static int perf_trace_event_enable(struct ftrace_event_call *event)
static int perf_trace_event_enable(struct ftrace_event_call *event, void *data)
{
	char *buf;
	int ret = -ENOMEM;

	if (event->perf_refcount++ > 0)
	if (event->perf_refcount++ > 0) {
		event->perf_data = NULL;
		return 0;
	}

	if (!total_ref_count) {
		buf = (char *)alloc_percpu(perf_trace_t);
@@ -51,6 +53,7 @@ static int perf_trace_event_enable(struct ftrace_event_call *event)

	ret = event->perf_event_enable(event);
	if (!ret) {
		event->perf_data = data;
		total_ref_count++;
		return 0;
	}
@@ -68,7 +71,7 @@ static int perf_trace_event_enable(struct ftrace_event_call *event)
	return ret;
}

int perf_trace_enable(int event_id)
int perf_trace_enable(int event_id, void *data)
{
	struct ftrace_event_call *event;
	int ret = -EINVAL;
@@ -77,7 +80,7 @@ int perf_trace_enable(int event_id)
	list_for_each_entry(event, &ftrace_events, list) {
		if (event->id == event_id && event->perf_event_enable &&
		    try_module_get(event->mod)) {
			ret = perf_trace_event_enable(event);
			ret = perf_trace_event_enable(event, data);
			break;
		}
	}
Loading