aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/perf_counter.h3
-rw-r--r--kernel/perf_counter.c50
-rw-r--r--tools/perf/builtin-stat.c6
3 files changed, 55 insertions, 4 deletions
diff --git a/include/linux/perf_counter.h b/include/linux/perf_counter.h
index 3078e23c91eb..5e970c7d3fd5 100644
--- a/include/linux/perf_counter.h
+++ b/include/linux/perf_counter.h
@@ -179,8 +179,9 @@ struct perf_counter_attr {
179 comm : 1, /* include comm data */ 179 comm : 1, /* include comm data */
180 freq : 1, /* use freq, not period */ 180 freq : 1, /* use freq, not period */
181 inherit_stat : 1, /* per task counts */ 181 inherit_stat : 1, /* per task counts */
182 enable_on_exec : 1, /* next exec enables */
182 183
183 __reserved_1 : 52; 184 __reserved_1 : 51;
184 185
185 __u32 wakeup_events; /* wakeup every n events */ 186 __u32 wakeup_events; /* wakeup every n events */
186 __u32 __reserved_2; 187 __u32 __reserved_2;
diff --git a/kernel/perf_counter.c b/kernel/perf_counter.c
index 66ab1e9d1294..d55a50da2347 100644
--- a/kernel/perf_counter.c
+++ b/kernel/perf_counter.c
@@ -1429,6 +1429,53 @@ void perf_counter_task_tick(struct task_struct *curr, int cpu)
1429} 1429}
1430 1430
1431/* 1431/*
1432 * Enable all of a task's counters that have been marked enable-on-exec.
1433 * This expects task == current.
1434 */
1435static void perf_counter_enable_on_exec(struct task_struct *task)
1436{
1437 struct perf_counter_context *ctx;
1438 struct perf_counter *counter;
1439 unsigned long flags;
1440 int enabled = 0;
1441
1442 local_irq_save(flags);
1443 ctx = task->perf_counter_ctxp;
1444 if (!ctx || !ctx->nr_counters)
1445 goto out;
1446
1447 __perf_counter_task_sched_out(ctx);
1448
1449 spin_lock(&ctx->lock);
1450
1451 list_for_each_entry(counter, &ctx->counter_list, list_entry) {
1452 if (!counter->attr.enable_on_exec)
1453 continue;
1454 counter->attr.enable_on_exec = 0;
1455 if (counter->state >= PERF_COUNTER_STATE_INACTIVE)
1456 continue;
1457 counter->state = PERF_COUNTER_STATE_INACTIVE;
1458 counter->tstamp_enabled =
1459 ctx->time - counter->total_time_enabled;
1460 enabled = 1;
1461 }
1462
1463 /*
1464 * Unclone this context if we enabled any counter.
1465 */
1466 if (enabled && ctx->parent_ctx) {
1467 put_ctx(ctx->parent_ctx);
1468 ctx->parent_ctx = NULL;
1469 }
1470
1471 spin_unlock(&ctx->lock);
1472
1473 perf_counter_task_sched_in(task, smp_processor_id());
1474 out:
1475 local_irq_restore(flags);
1476}
1477
1478/*
1432 * Cross CPU call to read the hardware counter 1479 * Cross CPU call to read the hardware counter
1433 */ 1480 */
1434static void __perf_counter_read(void *info) 1481static void __perf_counter_read(void *info)
@@ -2949,6 +2996,9 @@ void perf_counter_comm(struct task_struct *task)
2949{ 2996{
2950 struct perf_comm_event comm_event; 2997 struct perf_comm_event comm_event;
2951 2998
2999 if (task->perf_counter_ctxp)
3000 perf_counter_enable_on_exec(task);
3001
2952 if (!atomic_read(&nr_comm_counters)) 3002 if (!atomic_read(&nr_comm_counters))
2953 return; 3003 return;
2954 3004
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 201ef2367dcb..2e03524a1de0 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -116,8 +116,9 @@ static void create_perf_stat_counter(int counter, int pid)
116 fd[cpu][counter], strerror(errno)); 116 fd[cpu][counter], strerror(errno));
117 } 117 }
118 } else { 118 } else {
119 attr->inherit = inherit; 119 attr->inherit = inherit;
120 attr->disabled = 1; 120 attr->disabled = 1;
121 attr->enable_on_exec = 1;
121 122
122 fd[0][counter] = sys_perf_counter_open(attr, pid, -1, -1, 0); 123 fd[0][counter] = sys_perf_counter_open(attr, pid, -1, -1, 0);
123 if (fd[0][counter] < 0 && verbose) 124 if (fd[0][counter] < 0 && verbose)
@@ -262,7 +263,6 @@ static int run_perf_stat(int argc, const char **argv)
262 * Enable counters and exec the command: 263 * Enable counters and exec the command:
263 */ 264 */
264 t0 = rdclock(); 265 t0 = rdclock();
265 prctl(PR_TASK_PERF_COUNTERS_ENABLE);
266 266
267 close(go_pipe[1]); 267 close(go_pipe[1]);
268 wait(&status); 268 wait(&status);