lkml.org 
[lkml]   [2015]   [Feb]   [18]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[tip:perf/core] perf: Add pmu specific data for perf task context
    Commit-ID:  4af57ef28c2c1047fda9e1a5be02aa7a6a69cf9e
    Gitweb: http://git.kernel.org/tip/4af57ef28c2c1047fda9e1a5be02aa7a6a69cf9e
    Author: Yan, Zheng <zheng.z.yan@intel.com>
    AuthorDate: Tue, 4 Nov 2014 21:56:01 -0500
    Committer: Ingo Molnar <mingo@kernel.org>
    CommitDate: Wed, 18 Feb 2015 17:16:05 +0100

    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>
    ---
    include/linux/perf_event.h | 6 ++++++
    kernel/events/core.c | 40 ++++++++++++++++++++++++++++++++++++----
    2 files changed, 42 insertions(+), 4 deletions(-)

    diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
    index c7007a5..270cd01 100644
    --- a/include/linux/perf_event.h
    +++ b/include/linux/perf_event.h
    @@ -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;
    diff --git a/kernel/events/core.c b/kernel/events/core.c
    index f563ce7..688086b 100644
    --- a/kernel/events/core.c
    +++ b/kernel/events/core.c
    @@ -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 @@ errout:
    * 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 @@ retry:
    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 @@ retry:
    }
    }

    + 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;

    \
     
     \ /
      Last update: 2015-02-18 18:41    [W:5.810 / U:0.524 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site