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

Commit 4af57ef2 authored by Yan, Zheng's avatar Yan, Zheng Committed by Ingo Molnar
Browse files

perf: Add pmu specific data for perf task context



Introduce a new flag PERF_ATTACH_TASK_DATA for perf event's attach
stata. The flag is set by PMU's event_init() callback, it indicates
that perf event needs PMU specific data.

The PMU specific data are initialized to zeros. Later patches will
use PMU specific data to save LBR stack.

Signed-off-by: default avatarYan, Zheng <zheng.z.yan@intel.com>
Signed-off-by: default avatarKan Liang <kan.liang@intel.com>
Signed-off-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: eranian@google.com
Cc: jolsa@redhat.com
Link: http://lkml.kernel.org/r/1415156173-10035-6-git-send-email-kan.liang@intel.com


Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parent e9d7f7cd
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -271,6 +271,10 @@ struct pmu {
	 */
	void (*sched_task)		(struct perf_event_context *ctx,
					bool sched_in);
	/*
	 * PMU specific data size
	 */
	size_t				task_ctx_size;

};

@@ -307,6 +311,7 @@ struct swevent_hlist {
#define PERF_ATTACH_CONTEXT	0x01
#define PERF_ATTACH_GROUP	0x02
#define PERF_ATTACH_TASK	0x04
#define PERF_ATTACH_TASK_DATA	0x08

struct perf_cgroup;
struct ring_buffer;
@@ -511,6 +516,7 @@ struct perf_event_context {
	u64				generation;
	int				pin_count;
	int				nr_cgroups;	 /* cgroup evts */
	void				*task_ctx_data; /* pmu specific data */
	struct rcu_head			rcu_head;

	struct delayed_work		orphans_remove;
+36 −4
Original line number Diff line number Diff line
@@ -905,6 +905,15 @@ static void get_ctx(struct perf_event_context *ctx)
	WARN_ON(!atomic_inc_not_zero(&ctx->refcount));
}

static void free_ctx(struct rcu_head *head)
{
	struct perf_event_context *ctx;

	ctx = container_of(head, struct perf_event_context, rcu_head);
	kfree(ctx->task_ctx_data);
	kfree(ctx);
}

static void put_ctx(struct perf_event_context *ctx)
{
	if (atomic_dec_and_test(&ctx->refcount)) {
@@ -912,7 +921,7 @@ static void put_ctx(struct perf_event_context *ctx)
			put_ctx(ctx->parent_ctx);
		if (ctx->task)
			put_task_struct(ctx->task);
		kfree_rcu(ctx, rcu_head);
		call_rcu(&ctx->rcu_head, free_ctx);
	}
}

@@ -3309,12 +3318,15 @@ find_lively_task_by_vpid(pid_t vpid)
 * Returns a matching context with refcount and pincount.
 */
static struct perf_event_context *
find_get_context(struct pmu *pmu, struct task_struct *task, int cpu)
find_get_context(struct pmu *pmu, struct task_struct *task,
		struct perf_event *event)
{
	struct perf_event_context *ctx, *clone_ctx = NULL;
	struct perf_cpu_context *cpuctx;
	void *task_ctx_data = NULL;
	unsigned long flags;
	int ctxn, err;
	int cpu = event->cpu;

	if (!task) {
		/* Must be root to operate on a CPU event: */
@@ -3342,11 +3354,24 @@ find_get_context(struct pmu *pmu, struct task_struct *task, int cpu)
	if (ctxn < 0)
		goto errout;

	if (event->attach_state & PERF_ATTACH_TASK_DATA) {
		task_ctx_data = kzalloc(pmu->task_ctx_size, GFP_KERNEL);
		if (!task_ctx_data) {
			err = -ENOMEM;
			goto errout;
		}
	}

retry:
	ctx = perf_lock_task_context(task, ctxn, &flags);
	if (ctx) {
		clone_ctx = unclone_ctx(ctx);
		++ctx->pin_count;

		if (task_ctx_data && !ctx->task_ctx_data) {
			ctx->task_ctx_data = task_ctx_data;
			task_ctx_data = NULL;
		}
		raw_spin_unlock_irqrestore(&ctx->lock, flags);

		if (clone_ctx)
@@ -3357,6 +3382,11 @@ find_get_context(struct pmu *pmu, struct task_struct *task, int cpu)
		if (!ctx)
			goto errout;

		if (task_ctx_data) {
			ctx->task_ctx_data = task_ctx_data;
			task_ctx_data = NULL;
		}

		err = 0;
		mutex_lock(&task->perf_event_mutex);
		/*
@@ -3383,9 +3413,11 @@ find_get_context(struct pmu *pmu, struct task_struct *task, int cpu)
		}
	}

	kfree(task_ctx_data);
	return ctx;

errout:
	kfree(task_ctx_data);
	return ERR_PTR(err);
}

@@ -7559,7 +7591,7 @@ SYSCALL_DEFINE5(perf_event_open,
	/*
	 * Get the target context (task or percpu):
	 */
	ctx = find_get_context(pmu, task, event->cpu);
	ctx = find_get_context(pmu, task, event);
	if (IS_ERR(ctx)) {
		err = PTR_ERR(ctx);
		goto err_alloc;
@@ -7765,7 +7797,7 @@ perf_event_create_kernel_counter(struct perf_event_attr *attr, int cpu,

	account_event(event);

	ctx = find_get_context(event->pmu, task, cpu);
	ctx = find_get_context(event->pmu, task, event);
	if (IS_ERR(ctx)) {
		err = PTR_ERR(ctx);
		goto err_free;