diff options
author | Yan, Zheng <zheng.z.yan@intel.com> | 2014-11-04 21:56:01 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2015-02-18 11:16:05 -0500 |
commit | 4af57ef28c2c1047fda9e1a5be02aa7a6a69cf9e (patch) | |
tree | d186ebdcb589686170bfac7dc97b5d1c613dab9c /kernel/events | |
parent | e9d7f7cd97c45e2c612d3b38be05b4cfb27939ee (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.c | 40 |
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 | ||
908 | static 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 | |||
908 | static void put_ctx(struct perf_event_context *ctx) | 917 | static 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 | */ |
3311 | static struct perf_event_context * | 3320 | static struct perf_event_context * |
3312 | find_get_context(struct pmu *pmu, struct task_struct *task, int cpu) | 3321 | find_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 | |||
3345 | retry: | 3365 | retry: |
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 | ||
3388 | errout: | 3419 | errout: |
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; |