aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/perf_counter.c
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2008-12-11 08:59:31 -0500
committerIngo Molnar <mingo@elte.hu>2008-12-11 09:45:55 -0500
commit1d1c7ddbfab358445a542715551301b7fc363e28 (patch)
treed4421834d109b206f39c2019ea039fd42ed22e1d /kernel/perf_counter.c
parentbae43c9945ebeef15e7952e317efb02393d3bfc7 (diff)
perf counters: add prctl interface to disable/enable counters
Add a way for self-monitoring tasks to disable/enable counters summarily, via a prctl: PR_TASK_PERF_COUNTERS_DISABLE 31 PR_TASK_PERF_COUNTERS_ENABLE 32 Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel/perf_counter.c')
-rw-r--r--kernel/perf_counter.c86
1 files changed, 79 insertions, 7 deletions
diff --git a/kernel/perf_counter.c b/kernel/perf_counter.c
index a0fe8474ee29..4e679b91d8bb 100644
--- a/kernel/perf_counter.c
+++ b/kernel/perf_counter.c
@@ -415,6 +415,9 @@ counter_sched_in(struct perf_counter *counter,
415 struct perf_counter_context *ctx, 415 struct perf_counter_context *ctx,
416 int cpu) 416 int cpu)
417{ 417{
418 if (counter->active == -1)
419 return;
420
418 counter->hw_ops->hw_perf_counter_enable(counter); 421 counter->hw_ops->hw_perf_counter_enable(counter);
419 counter->active = 1; 422 counter->active = 1;
420 counter->oncpu = cpu; /* TODO: put 'cpu' into cpuctx->cpu */ 423 counter->oncpu = cpu; /* TODO: put 'cpu' into cpuctx->cpu */
@@ -479,6 +482,79 @@ void perf_counter_task_sched_in(struct task_struct *task, int cpu)
479 cpuctx->task_ctx = ctx; 482 cpuctx->task_ctx = ctx;
480} 483}
481 484
485int perf_counter_task_disable(void)
486{
487 struct task_struct *curr = current;
488 struct perf_counter_context *ctx = &curr->perf_counter_ctx;
489 struct perf_counter *counter;
490 u64 perf_flags;
491 int cpu;
492
493 if (likely(!ctx->nr_counters))
494 return 0;
495
496 local_irq_disable();
497 cpu = smp_processor_id();
498
499 perf_counter_task_sched_out(curr, cpu);
500
501 spin_lock(&ctx->lock);
502
503 /*
504 * Disable all the counters:
505 */
506 perf_flags = hw_perf_save_disable();
507
508 list_for_each_entry(counter, &ctx->counter_list, list_entry) {
509 WARN_ON_ONCE(counter->active == 1);
510 counter->active = -1;
511 }
512 hw_perf_restore(perf_flags);
513
514 spin_unlock(&ctx->lock);
515
516 local_irq_enable();
517
518 return 0;
519}
520
521int perf_counter_task_enable(void)
522{
523 struct task_struct *curr = current;
524 struct perf_counter_context *ctx = &curr->perf_counter_ctx;
525 struct perf_counter *counter;
526 u64 perf_flags;
527 int cpu;
528
529 if (likely(!ctx->nr_counters))
530 return 0;
531
532 local_irq_disable();
533 cpu = smp_processor_id();
534
535 spin_lock(&ctx->lock);
536
537 /*
538 * Disable all the counters:
539 */
540 perf_flags = hw_perf_save_disable();
541
542 list_for_each_entry(counter, &ctx->counter_list, list_entry) {
543 if (counter->active != -1)
544 continue;
545 counter->active = 0;
546 }
547 hw_perf_restore(perf_flags);
548
549 spin_unlock(&ctx->lock);
550
551 perf_counter_task_sched_in(curr, cpu);
552
553 local_irq_enable();
554
555 return 0;
556}
557
482void perf_counter_task_tick(struct task_struct *curr, int cpu) 558void perf_counter_task_tick(struct task_struct *curr, int cpu)
483{ 559{
484 struct perf_counter_context *ctx = &curr->perf_counter_ctx; 560 struct perf_counter_context *ctx = &curr->perf_counter_ctx;
@@ -951,13 +1027,9 @@ perf_counter_alloc(struct perf_counter_hw_event *hw_event,
951 * @cpu: target cpu 1027 * @cpu: target cpu
952 * @group_fd: group leader counter fd 1028 * @group_fd: group leader counter fd
953 */ 1029 */
954asmlinkage int sys_perf_counter_open( 1030asmlinkage int
955 1031sys_perf_counter_open(struct perf_counter_hw_event *hw_event_uptr __user,
956 struct perf_counter_hw_event *hw_event_uptr __user, 1032 pid_t pid, int cpu, int group_fd)
957 pid_t pid,
958 int cpu,
959 int group_fd)
960
961{ 1033{
962 struct perf_counter *counter, *group_leader; 1034 struct perf_counter *counter, *group_leader;
963 struct perf_counter_hw_event hw_event; 1035 struct perf_counter_hw_event hw_event;