Skip to content

Commit

Permalink
perf_counter: Provide a way to enable counters on exec
Browse files Browse the repository at this point in the history
This provides a way to mark a counter to be enabled on the next
exec. This is useful for measuring the total activity of a
program without including overhead from the process that
launches it.

This also changes the perf stat command to use this new
facility.

Signed-off-by: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
LKML-Reference: <19017.43927.838745.689203@cargo.ozlabs.ibm.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
  • Loading branch information
Paul Mackerras authored and Ingo Molnar committed Jun 30, 2009
1 parent 051ae7f commit 57e7986
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 4 deletions.
3 changes: 2 additions & 1 deletion include/linux/perf_counter.h
Original file line number Diff line number Diff line change
Expand Up @@ -179,8 +179,9 @@ struct perf_counter_attr {
comm : 1, /* include comm data */
freq : 1, /* use freq, not period */
inherit_stat : 1, /* per task counts */
enable_on_exec : 1, /* next exec enables */

__reserved_1 : 52;
__reserved_1 : 51;

__u32 wakeup_events; /* wakeup every n events */
__u32 __reserved_2;
Expand Down
50 changes: 50 additions & 0 deletions kernel/perf_counter.c
Original file line number Diff line number Diff line change
Expand Up @@ -1428,6 +1428,53 @@ void perf_counter_task_tick(struct task_struct *curr, int cpu)
perf_counter_task_sched_in(curr, cpu);
}

/*
* Enable all of a task's counters that have been marked enable-on-exec.
* This expects task == current.
*/
static void perf_counter_enable_on_exec(struct task_struct *task)
{
struct perf_counter_context *ctx;
struct perf_counter *counter;
unsigned long flags;
int enabled = 0;

local_irq_save(flags);
ctx = task->perf_counter_ctxp;
if (!ctx || !ctx->nr_counters)
goto out;

__perf_counter_task_sched_out(ctx);

spin_lock(&ctx->lock);

list_for_each_entry(counter, &ctx->counter_list, list_entry) {
if (!counter->attr.enable_on_exec)
continue;
counter->attr.enable_on_exec = 0;
if (counter->state >= PERF_COUNTER_STATE_INACTIVE)
continue;
counter->state = PERF_COUNTER_STATE_INACTIVE;
counter->tstamp_enabled =
ctx->time - counter->total_time_enabled;
enabled = 1;
}

/*
* Unclone this context if we enabled any counter.
*/
if (enabled && ctx->parent_ctx) {
put_ctx(ctx->parent_ctx);
ctx->parent_ctx = NULL;
}

spin_unlock(&ctx->lock);

perf_counter_task_sched_in(task, smp_processor_id());
out:
local_irq_restore(flags);
}

/*
* Cross CPU call to read the hardware counter
*/
Expand Down Expand Up @@ -2949,6 +2996,9 @@ void perf_counter_comm(struct task_struct *task)
{
struct perf_comm_event comm_event;

if (task->perf_counter_ctxp)
perf_counter_enable_on_exec(task);

if (!atomic_read(&nr_comm_counters))
return;

Expand Down
6 changes: 3 additions & 3 deletions tools/perf/builtin-stat.c
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,9 @@ static void create_perf_stat_counter(int counter, int pid)
fd[cpu][counter], strerror(errno));
}
} else {
attr->inherit = inherit;
attr->disabled = 1;
attr->inherit = inherit;
attr->disabled = 1;
attr->enable_on_exec = 1;

fd[0][counter] = sys_perf_counter_open(attr, pid, -1, -1, 0);
if (fd[0][counter] < 0 && verbose)
Expand Down Expand Up @@ -262,7 +263,6 @@ static int run_perf_stat(int argc, const char **argv)
* Enable counters and exec the command:
*/
t0 = rdclock();
prctl(PR_TASK_PERF_COUNTERS_ENABLE);

close(go_pipe[1]);
wait(&status);
Expand Down

0 comments on commit 57e7986

Please sign in to comment.