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

Commit e6dab5ff authored by Andrew Vagin's avatar Andrew Vagin Committed by Ingo Molnar
Browse files

perf/trace: Add ability to set a target task for events



A few events are interesting not only for a current task.
For example, sched_stat_* events are interesting for a task
which wakes up. For this reason, it will be good if such
events will be delivered to a target task too.

Now a target task can be set by using __perf_task().

The original idea and a draft patch belongs to Peter Zijlstra.

I need these events for profiling sleep times. sched_switch is used for
getting callchains and sched_stat_* is used for getting time periods.
These events are combined in user space, then it can be analyzed by
perf tools.

Inspired-by: default avatarPeter Zijlstra <peterz@infradead.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Arun Sharma <asharma@fb.com>
Signed-off-by: default avatarAndrew Vagin <avagin@openvz.org>
Signed-off-by: default avatarPeter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1342016098-213063-1-git-send-email-avagin@openvz.org


Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parent d07bdfd3
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -306,9 +306,10 @@ extern void *perf_trace_buf_prepare(int size, unsigned short type,

static inline void
perf_trace_buf_submit(void *raw_data, int size, int rctx, u64 addr,
		       u64 count, struct pt_regs *regs, void *head)
		       u64 count, struct pt_regs *regs, void *head,
		       struct task_struct *task)
{
	perf_tp_event(addr, count, raw_data, size, regs, head, rctx);
	perf_tp_event(addr, count, raw_data, size, regs, head, rctx, task);
}
#endif

+2 −1
Original line number Diff line number Diff line
@@ -1272,7 +1272,8 @@ static inline bool perf_paranoid_kernel(void)
extern void perf_event_init(void);
extern void perf_tp_event(u64 addr, u64 count, void *record,
			  int entry_size, struct pt_regs *regs,
			  struct hlist_head *head, int rctx);
			  struct hlist_head *head, int rctx,
			  struct task_struct *task);
extern void perf_bp_event(struct perf_event *event, void *data);

#ifndef perf_misc_flags
+4 −0
Original line number Diff line number Diff line
@@ -73,6 +73,9 @@ DECLARE_EVENT_CLASS(sched_wakeup_template,
		__entry->prio		= p->prio;
		__entry->success	= success;
		__entry->target_cpu	= task_cpu(p);
	)
	TP_perf_assign(
		__perf_task(p);
	),

	TP_printk("comm=%s pid=%d prio=%d success=%d target_cpu=%03d",
@@ -325,6 +328,7 @@ DECLARE_EVENT_CLASS(sched_stat_template,
	)
	TP_perf_assign(
		__perf_count(delay);
		__perf_task(tsk);
	),

	TP_printk("comm=%s pid=%d delay=%Lu [ns]",
+5 −1
Original line number Diff line number Diff line
@@ -712,6 +712,9 @@ __attribute__((section("_ftrace_events"))) *__event_##call = &event_##call
#undef __perf_count
#define __perf_count(c) __count = (c)

#undef __perf_task
#define __perf_task(t) __task = (t)

#undef TP_perf_assign
#define TP_perf_assign(args...) args

@@ -725,6 +728,7 @@ perf_trace_##call(void *__data, proto) \
	struct ftrace_raw_##call *entry;				\
	struct pt_regs __regs;						\
	u64 __addr = 0, __count = 1;					\
	struct task_struct *__task = NULL;				\
	struct hlist_head *head;					\
	int __entry_size;						\
	int __data_size;						\
@@ -752,7 +756,7 @@ perf_trace_##call(void *__data, proto) \
									\
	head = this_cpu_ptr(event_call->perf_events);			\
	perf_trace_buf_submit(entry, __entry_size, rctx, __addr,	\
		__count, &__regs, head);				\
		__count, &__regs, head, __task);			\
}

/*
+8 −1
Original line number Diff line number Diff line
@@ -153,7 +153,8 @@ put_callchain_entry(int rctx)
	put_recursion_context(__get_cpu_var(callchain_recursion), rctx);
}

struct perf_callchain_entry *perf_callchain(struct pt_regs *regs)
struct perf_callchain_entry *
perf_callchain(struct perf_event *event, struct pt_regs *regs)
{
	int rctx;
	struct perf_callchain_entry *entry;
@@ -178,6 +179,12 @@ struct perf_callchain_entry *perf_callchain(struct pt_regs *regs)
	}

	if (regs) {
		/*
		 * Disallow cross-task user callchains.
		 */
		if (event->ctx->task && event->ctx->task != current)
			goto exit_put;

		perf_callchain_store(entry, PERF_CONTEXT_USER);
		perf_callchain_user(entry, regs);
	}
Loading