perf_counter: Provide a way to enable counters on exec
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>
This commit is contained in:
parent
051ae7f734
commit
57e7986ed1
|
@ -179,8 +179,9 @@ struct perf_counter_attr {
|
||||||
comm : 1, /* include comm data */
|
comm : 1, /* include comm data */
|
||||||
freq : 1, /* use freq, not period */
|
freq : 1, /* use freq, not period */
|
||||||
inherit_stat : 1, /* per task counts */
|
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 wakeup_events; /* wakeup every n events */
|
||||||
__u32 __reserved_2;
|
__u32 __reserved_2;
|
||||||
|
|
|
@ -1428,6 +1428,53 @@ void perf_counter_task_tick(struct task_struct *curr, int cpu)
|
||||||
perf_counter_task_sched_in(curr, 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
|
* Cross CPU call to read the hardware counter
|
||||||
*/
|
*/
|
||||||
|
@ -2949,6 +2996,9 @@ void perf_counter_comm(struct task_struct *task)
|
||||||
{
|
{
|
||||||
struct perf_comm_event comm_event;
|
struct perf_comm_event comm_event;
|
||||||
|
|
||||||
|
if (task->perf_counter_ctxp)
|
||||||
|
perf_counter_enable_on_exec(task);
|
||||||
|
|
||||||
if (!atomic_read(&nr_comm_counters))
|
if (!atomic_read(&nr_comm_counters))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
@ -116,8 +116,9 @@ static void create_perf_stat_counter(int counter, int pid)
|
||||||
fd[cpu][counter], strerror(errno));
|
fd[cpu][counter], strerror(errno));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
attr->inherit = inherit;
|
attr->inherit = inherit;
|
||||||
attr->disabled = 1;
|
attr->disabled = 1;
|
||||||
|
attr->enable_on_exec = 1;
|
||||||
|
|
||||||
fd[0][counter] = sys_perf_counter_open(attr, pid, -1, -1, 0);
|
fd[0][counter] = sys_perf_counter_open(attr, pid, -1, -1, 0);
|
||||||
if (fd[0][counter] < 0 && verbose)
|
if (fd[0][counter] < 0 && verbose)
|
||||||
|
@ -262,7 +263,6 @@ static int run_perf_stat(int argc, const char **argv)
|
||||||
* Enable counters and exec the command:
|
* Enable counters and exec the command:
|
||||||
*/
|
*/
|
||||||
t0 = rdclock();
|
t0 = rdclock();
|
||||||
prctl(PR_TASK_PERF_COUNTERS_ENABLE);
|
|
||||||
|
|
||||||
close(go_pipe[1]);
|
close(go_pipe[1]);
|
||||||
wait(&status);
|
wait(&status);
|
||||||
|
|
Loading…
Reference in New Issue