From d3b9d9fdb66f049a321660bd0ce08361b87e9830 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Thu, 19 Mar 2009 20:26:17 +0100 Subject: [PATCH] --- yaml --- r: 147263 b: refs/heads/master c: e077df4f439681e43f0db8255b2d215b342ebdc6 h: refs/heads/master i: 147261: e136f29c2bdafc3299ea7e83e6b2afc97ec951fc 147259: d38ff5352fe830c33bd60bb3724a993d86b29fa9 147255: 89f74ffebb92c66f7f01ad1f64ad030c0f986e8f 147247: 950a40faab9a81a85c8d1a443536df138ad7cba7 147231: d63ac8c6d59de75fe1af1be3994985e03ccb4885 147199: dd9b4770d2d761042403aa92d79655517c7be861 v: v3 --- [refs] | 2 +- trunk/include/linux/perf_counter.h | 3 +++ trunk/init/Kconfig | 5 ++++ trunk/kernel/perf_counter.c | 43 ++++++++++++++++++++++++++++++ 4 files changed, 52 insertions(+), 1 deletion(-) diff --git a/[refs] b/[refs] index 894ddba8b293..90fd065825b8 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: f16009527595ee562308653bc3d0039166d2ab15 +refs/heads/master: e077df4f439681e43f0db8255b2d215b342ebdc6 diff --git a/trunk/include/linux/perf_counter.h b/trunk/include/linux/perf_counter.h index 08c11a6afebc..065984c1ff57 100644 --- a/trunk/include/linux/perf_counter.h +++ b/trunk/include/linux/perf_counter.h @@ -53,6 +53,8 @@ enum hw_event_types { PERF_COUNT_PAGE_FAULTS_MAJ = -7, PERF_SW_EVENTS_MIN = -8, + + PERF_TP_EVENTS_MIN = -65536 }; /* @@ -222,6 +224,7 @@ struct perf_counter { struct perf_data *usrdata; struct perf_data data[2]; + void (*destroy)(struct perf_counter *); struct rcu_head rcu_head; #endif }; diff --git a/trunk/init/Kconfig b/trunk/init/Kconfig index 38a2ecd47c37..4f647142f2e6 100644 --- a/trunk/init/Kconfig +++ b/trunk/init/Kconfig @@ -947,6 +947,11 @@ config PERF_COUNTERS Say Y if unsure. +config EVENT_PROFILE + bool "Tracepoint profile sources" + depends on PERF_COUNTERS && EVENT_TRACER + default y + endmenu config VM_EVENT_COUNTERS diff --git a/trunk/kernel/perf_counter.c b/trunk/kernel/perf_counter.c index 97f891ffeb40..0bbe3e45ba0d 100644 --- a/trunk/kernel/perf_counter.c +++ b/trunk/kernel/perf_counter.c @@ -1152,6 +1152,9 @@ static void free_counter_rcu(struct rcu_head *head) static void free_counter(struct perf_counter *counter) { + if (counter->destroy) + counter->destroy(counter); + call_rcu(&counter->rcu_head, free_counter_rcu); } @@ -1727,6 +1730,45 @@ static const struct hw_perf_counter_ops perf_ops_cpu_migrations = { .read = cpu_migrations_perf_counter_read, }; +#ifdef CONFIG_EVENT_PROFILE +void perf_tpcounter_event(int event_id) +{ + perf_swcounter_event(PERF_TP_EVENTS_MIN + event_id, 1, 1, + task_pt_regs(current)); +} + +extern int ftrace_profile_enable(int); +extern void ftrace_profile_disable(int); + +static void tp_perf_counter_destroy(struct perf_counter *counter) +{ + int event_id = counter->hw_event.type - PERF_TP_EVENTS_MIN; + + ftrace_profile_disable(event_id); +} + +static const struct hw_perf_counter_ops * +tp_perf_counter_init(struct perf_counter *counter) +{ + int event_id = counter->hw_event.type - PERF_TP_EVENTS_MIN; + int ret; + + ret = ftrace_profile_enable(event_id); + if (ret) + return NULL; + + counter->destroy = tp_perf_counter_destroy; + + return &perf_ops_generic; +} +#else +static const struct hw_perf_counter_ops * +tp_perf_counter_init(struct perf_counter *counter) +{ + return NULL; +} +#endif + static const struct hw_perf_counter_ops * sw_perf_counter_init(struct perf_counter *counter) { @@ -1772,6 +1814,7 @@ sw_perf_counter_init(struct perf_counter *counter) hw_ops = &perf_ops_cpu_migrations; break; default: + hw_ops = tp_perf_counter_init(counter); break; }