aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/events
diff options
context:
space:
mode:
authorYan, Zheng <zheng.z.yan@intel.com>2014-11-04 21:56:01 -0500
committerIngo Molnar <mingo@kernel.org>2015-02-18 11:16:05 -0500
commit4af57ef28c2c1047fda9e1a5be02aa7a6a69cf9e (patch)
treed186ebdcb589686170bfac7dc97b5d1c613dab9c /kernel/events
parente9d7f7cd97c45e2c612d3b38be05b4cfb27939ee (diff)
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: Yan, Zheng <zheng.z.yan@intel.com> Signed-off-by: Kan Liang <kan.liang@intel.com> Signed-off-by: Peter 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: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'kernel/events')
-rw-r--r--kernel/events/core.c40
1 files changed, 36 insertions, 4 deletions
diff --git a/kernel/events/core.c b/kernel/events/core.c
index f563ce767f93..688086bb7144 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -905,6 +905,15 @@ static void get_ctx(struct perf_event_context *ctx)
905 WARN_ON(!atomic_inc_not_zero(&ctx->refcount)); 905 WARN_ON(!atomic_inc_not_zero(&ctx->refcount));
906} 906}
907 907
908static void free_ctx(struct rcu_head *head)
909{
910 struct perf_event_context *ctx;
911
912 ctx = container_of(head, struct perf_event_context, rcu_head);
913 kfree(ctx->task_ctx_data);
914 kfree(ctx);
915}
916
908static void put_ctx(struct perf_event_context *ctx) 917static void put_ctx(struct perf_event_context *ctx)
909{ 918{
910 if (atomic_dec_and_test(&ctx->refcount)) { 919 if (atomic_dec_and_test(&ctx->refcount)) {
@@ -912,7 +921,7 @@ static void put_ctx(struct perf_event_context *ctx)
912 put_ctx(ctx->parent_ctx); 921 put_ctx(ctx->parent_ctx);
913 if (ctx->task) 922 if (ctx->task)
914 put_task_struct(ctx->task); 923 put_task_struct(ctx->task);
915 kfree_rcu(ctx, rcu_head); 924 call_rcu(&ctx->rcu_head, free_ctx);
916 } 925 }
917} 926}
918 927
@@ -3309,12 +3318,15 @@ errout:
3309 * Returns a matching context with refcount and pincount. 3318 * Returns a matching context with refcount and pincount.
3310 */ 3319 */
3311static struct perf_event_context * 3320static struct perf_event_context *
3312find_get_context(struct pmu *pmu, struct task_struct *task, int cpu) 3321find_get_context(struct pmu *pmu, struct task_struct *task,
3322 struct perf_event *event)
3313{ 3323{
3314 struct perf_event_context *ctx, *clone_ctx = NULL; 3324 struct perf_event_context *ctx, *clone_ctx = NULL;
3315 struct perf_cpu_context *cpuctx; 3325 struct perf_cpu_context *cpuctx;
3326 void *task_ctx_data = NULL;
3316 unsigned long flags; 3327 unsigned long flags;
3317 int ctxn, err; 3328 int ctxn, err;
3329 int cpu = event->cpu;
3318 3330
3319 if (!task) { 3331 if (!task) {
3320 /* Must be root to operate on a CPU event: */ 3332 /* 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)
3342 if (ctxn < 0) 3354 if (ctxn < 0)
3343 goto errout; 3355 goto errout;
3344 3356
3357 if (event->attach_state & PERF_ATTACH_TASK_DATA) {
3358 task_ctx_data = kzalloc(pmu->task_ctx_size, GFP_KERNEL);
3359 if (!task_ctx_data) {
3360 err = -ENOMEM;
3361 goto errout;
3362 }
3363 }
3364
3345retry: 3365retry:
3346 ctx = perf_lock_task_context(task, ctxn, &flags); 3366 ctx = perf_lock_task_context(task, ctxn, &flags);
3347 if (ctx) { 3367 if (ctx) {
3348 clone_ctx = unclone_ctx(ctx); 3368 clone_ctx = unclone_ctx(ctx);
3349 ++ctx->pin_count; 3369 ++ctx->pin_count;
3370
3371 if (task_ctx_data && !ctx->task_ctx_data) {
3372 ctx->task_ctx_data = task_ctx_data;
3373 task_ctx_data = NULL;
3374 }
3350 raw_spin_unlock_irqrestore(&ctx->lock, flags); 3375 raw_spin_unlock_irqrestore(&ctx->lock, flags);
3351 3376
3352 if (clone_ctx) 3377 if (clone_ctx)
@@ -3357,6 +3382,11 @@ retry:
3357 if (!ctx) 3382 if (!ctx)
3358 goto errout; 3383 goto errout;
3359 3384
3385 if (task_ctx_data) {
3386 ctx->task_ctx_data = task_ctx_data;
3387 task_ctx_data = NULL;
3388 }
3389
3360 err = 0; 3390 err = 0;
3361 mutex_lock(&task->perf_event_mutex); 3391 mutex_lock(&task->perf_event_mutex);
3362 /* 3392 /*
@@ -3383,9 +3413,11 @@ retry:
3383 } 3413 }
3384 } 3414 }
3385 3415
3416 kfree(task_ctx_data);
3386 return ctx; 3417 return ctx;
3387 3418
3388errout: 3419errout:
3420 kfree(task_ctx_data);
3389 return ERR_PTR(err); 3421 return ERR_PTR(err);
3390} 3422}
3391 3423
@@ -7559,7 +7591,7 @@ SYSCALL_DEFINE5(perf_event_open,
7559 /* 7591 /*
7560 * Get the target context (task or percpu): 7592 * Get the target context (task or percpu):
7561 */ 7593 */
7562 ctx = find_get_context(pmu, task, event->cpu); 7594 ctx = find_get_context(pmu, task, event);
7563 if (IS_ERR(ctx)) { 7595 if (IS_ERR(ctx)) {
7564 err = PTR_ERR(ctx); 7596 err = PTR_ERR(ctx);
7565 goto err_alloc; 7597 goto err_alloc;
@@ -7765,7 +7797,7 @@ perf_event_create_kernel_counter(struct perf_event_attr *attr, int cpu,
7765 7797
7766 account_event(event); 7798 account_event(event);
7767 7799
7768 ctx = find_get_context(event->pmu, task, cpu); 7800 ctx = find_get_context(event->pmu, task, event);
7769 if (IS_ERR(ctx)) { 7801 if (IS_ERR(ctx)) {
7770 err = PTR_ERR(ctx); 7802 err = PTR_ERR(ctx);
7771 goto err_free; 7803 goto err_free;