aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorPeter Zijlstra <a.p.zijlstra@chello.nl>2009-03-19 15:26:15 -0400
committerIngo Molnar <mingo@elte.hu>2009-03-20 05:17:07 -0400
commitac199db0189c091f2863312061c0575937f68810 (patch)
tree0068aaa77ca00102ca60754eb32329f06821bba0 /kernel
parent28bea271e58e429eccfad3d7ee2ad12d6ee015bf (diff)
ftrace: event profile hooks
Impact: new tracing infrastructure feature Provide infrastructure to generate software perf counter events from tracepoints. Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Paul Mackerras <paulus@samba.org> Cc: Steven Rostedt <rostedt@goodmis.org> LKML-Reference: <20090319194233.557364871@chello.nl> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/trace/Makefile1
-rw-r--r--kernel/trace/events.c1
-rw-r--r--kernel/trace/trace.h11
-rw-r--r--kernel/trace/trace_event_profile.c31
-rw-r--r--kernel/trace/trace_events.c9
-rw-r--r--kernel/trace/trace_events_stage_3.h44
6 files changed, 89 insertions, 8 deletions
diff --git a/kernel/trace/Makefile b/kernel/trace/Makefile
index c3feea01c3e0..0e45c206c2f9 100644
--- a/kernel/trace/Makefile
+++ b/kernel/trace/Makefile
@@ -44,5 +44,6 @@ obj-$(CONFIG_EVENT_TRACER) += trace_events.o
44obj-$(CONFIG_EVENT_TRACER) += events.o 44obj-$(CONFIG_EVENT_TRACER) += events.o
45obj-$(CONFIG_EVENT_TRACER) += trace_export.o 45obj-$(CONFIG_EVENT_TRACER) += trace_export.o
46obj-$(CONFIG_FTRACE_SYSCALLS) += trace_syscalls.o 46obj-$(CONFIG_FTRACE_SYSCALLS) += trace_syscalls.o
47obj-$(CONFIG_EVENT_PROFILE) += trace_event_profile.o
47 48
48libftrace-y := ftrace.o 49libftrace-y := ftrace.o
diff --git a/kernel/trace/events.c b/kernel/trace/events.c
index 9fc918da404f..246f2aa6dc46 100644
--- a/kernel/trace/events.c
+++ b/kernel/trace/events.c
@@ -12,4 +12,3 @@
12#include "trace_events_stage_2.h" 12#include "trace_events_stage_2.h"
13#include "trace_events_stage_3.h" 13#include "trace_events_stage_3.h"
14 14
15#include <trace/trace_event_types.h>
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index 7c9a0cbf5dca..7cfb741be200 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -785,12 +785,23 @@ struct ftrace_event_call {
785 int id; 785 int id;
786 int (*raw_init)(void); 786 int (*raw_init)(void);
787 int (*show_format)(struct trace_seq *s); 787 int (*show_format)(struct trace_seq *s);
788
789#ifdef CONFIG_EVENT_PROFILE
790 atomic_t profile_count;
791 int (*profile_enable)(struct ftrace_event_call *);
792 void (*profile_disable)(struct ftrace_event_call *);
793#endif
788}; 794};
789 795
790void event_trace_printk(unsigned long ip, const char *fmt, ...); 796void event_trace_printk(unsigned long ip, const char *fmt, ...);
791extern struct ftrace_event_call __start_ftrace_events[]; 797extern struct ftrace_event_call __start_ftrace_events[];
792extern struct ftrace_event_call __stop_ftrace_events[]; 798extern struct ftrace_event_call __stop_ftrace_events[];
793 799
800#define for_each_event(event) \
801 for (event = __start_ftrace_events; \
802 (unsigned long)event < (unsigned long)__stop_ftrace_events; \
803 event++)
804
794extern const char *__start___trace_bprintk_fmt[]; 805extern const char *__start___trace_bprintk_fmt[];
795extern const char *__stop___trace_bprintk_fmt[]; 806extern const char *__stop___trace_bprintk_fmt[];
796 807
diff --git a/kernel/trace/trace_event_profile.c b/kernel/trace/trace_event_profile.c
new file mode 100644
index 000000000000..22cba9970776
--- /dev/null
+++ b/kernel/trace/trace_event_profile.c
@@ -0,0 +1,31 @@
1/*
2 * trace event based perf counter profiling
3 *
4 * Copyright (C) 2009 Red Hat Inc, Peter Zijlstra <pzijlstr@redhat.com>
5 *
6 */
7
8#include "trace.h"
9
10int ftrace_profile_enable(int event_id)
11{
12 struct ftrace_event_call *event;
13
14 for_each_event(event) {
15 if (event->id == event_id)
16 return event->profile_enable(event);
17 }
18
19 return -EINVAL;
20}
21
22void ftrace_profile_disable(int event_id)
23{
24 struct ftrace_event_call *event;
25
26 for_each_event(event) {
27 if (event->id == event_id)
28 return event->profile_disable(event);
29 }
30}
31
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index 7763db8fd0b3..3047b56f6637 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -19,11 +19,6 @@
19 19
20static DEFINE_MUTEX(event_mutex); 20static DEFINE_MUTEX(event_mutex);
21 21
22#define events_for_each(event) \
23 for (event = __start_ftrace_events; \
24 (unsigned long)event < (unsigned long)__stop_ftrace_events; \
25 event++)
26
27static void ftrace_clear_events(void) 22static void ftrace_clear_events(void)
28{ 23{
29 struct ftrace_event_call *call = (void *)__start_ftrace_events; 24 struct ftrace_event_call *call = (void *)__start_ftrace_events;
@@ -90,7 +85,7 @@ static int ftrace_set_clr_event(char *buf, int set)
90 } 85 }
91 86
92 mutex_lock(&event_mutex); 87 mutex_lock(&event_mutex);
93 events_for_each(call) { 88 for_each_event(call) {
94 89
95 if (!call->name || !call->regfunc) 90 if (!call->name || !call->regfunc)
96 continue; 91 continue;
@@ -628,7 +623,7 @@ static __init int event_trace_init(void)
628 if (!d_events) 623 if (!d_events)
629 return 0; 624 return 0;
630 625
631 events_for_each(call) { 626 for_each_event(call) {
632 /* The linker may leave blanks */ 627 /* The linker may leave blanks */
633 if (!call->name) 628 if (!call->name)
634 continue; 629 continue;
diff --git a/kernel/trace/trace_events_stage_3.h b/kernel/trace/trace_events_stage_3.h
index 4c26d97b4508..6b3261ca988c 100644
--- a/kernel/trace/trace_events_stage_3.h
+++ b/kernel/trace/trace_events_stage_3.h
@@ -109,6 +109,40 @@
109#undef TP_FMT 109#undef TP_FMT
110#define TP_FMT(fmt, args...) fmt "\n", ##args 110#define TP_FMT(fmt, args...) fmt "\n", ##args
111 111
112#ifdef CONFIG_EVENT_PROFILE
113#define _TRACE_PROFILE(call, proto, args) \
114static void ftrace_profile_##call(proto) \
115{ \
116 extern void perf_tpcounter_event(int); \
117 perf_tpcounter_event(event_##call.id); \
118} \
119 \
120static int ftrace_profile_enable_##call(struct ftrace_event_call *call) \
121{ \
122 int ret = 0; \
123 \
124 if (!atomic_inc_return(&call->profile_count)) \
125 ret = register_trace_##call(ftrace_profile_##call); \
126 \
127 return ret; \
128} \
129 \
130static void ftrace_profile_disable_##call(struct ftrace_event_call *call) \
131{ \
132 if (atomic_add_negative(-1, &call->profile_count)) \
133 unregister_trace_##call(ftrace_profile_##call); \
134}
135
136#define _TRACE_PROFILE_INIT(call) \
137 .profile_count = ATOMIC_INIT(-1), \
138 .profile_enable = ftrace_profile_enable_##call, \
139 .profile_disable = ftrace_profile_disable_##call,
140
141#else
142#define _TRACE_PROFILE(call, proto, args)
143#define _TRACE_PROFILE_INIT(call)
144#endif
145
112#define _TRACE_FORMAT(call, proto, args, fmt) \ 146#define _TRACE_FORMAT(call, proto, args, fmt) \
113static void ftrace_event_##call(proto) \ 147static void ftrace_event_##call(proto) \
114{ \ 148{ \
@@ -147,6 +181,7 @@ static int ftrace_init_event_##call(void) \
147#undef TRACE_FORMAT 181#undef TRACE_FORMAT
148#define TRACE_FORMAT(call, proto, args, fmt) \ 182#define TRACE_FORMAT(call, proto, args, fmt) \
149_TRACE_FORMAT(call, PARAMS(proto), PARAMS(args), PARAMS(fmt)) \ 183_TRACE_FORMAT(call, PARAMS(proto), PARAMS(args), PARAMS(fmt)) \
184_TRACE_PROFILE(call, PARAMS(proto), PARAMS(args)) \
150static struct ftrace_event_call __used \ 185static struct ftrace_event_call __used \
151__attribute__((__aligned__(4))) \ 186__attribute__((__aligned__(4))) \
152__attribute__((section("_ftrace_events"))) event_##call = { \ 187__attribute__((section("_ftrace_events"))) event_##call = { \
@@ -155,6 +190,7 @@ __attribute__((section("_ftrace_events"))) event_##call = { \
155 .raw_init = ftrace_init_event_##call, \ 190 .raw_init = ftrace_init_event_##call, \
156 .regfunc = ftrace_reg_event_##call, \ 191 .regfunc = ftrace_reg_event_##call, \
157 .unregfunc = ftrace_unreg_event_##call, \ 192 .unregfunc = ftrace_unreg_event_##call, \
193 _TRACE_PROFILE_INIT(call) \
158} 194}
159 195
160#undef __entry 196#undef __entry
@@ -162,6 +198,7 @@ __attribute__((section("_ftrace_events"))) event_##call = { \
162 198
163#undef TRACE_EVENT 199#undef TRACE_EVENT
164#define TRACE_EVENT(call, proto, args, tstruct, assign, print) \ 200#define TRACE_EVENT(call, proto, args, tstruct, assign, print) \
201_TRACE_PROFILE(call, PARAMS(proto), PARAMS(args)) \
165 \ 202 \
166static struct ftrace_event_call event_##call; \ 203static struct ftrace_event_call event_##call; \
167 \ 204 \
@@ -227,4 +264,11 @@ __attribute__((section("_ftrace_events"))) event_##call = { \
227 .regfunc = ftrace_raw_reg_event_##call, \ 264 .regfunc = ftrace_raw_reg_event_##call, \
228 .unregfunc = ftrace_raw_unreg_event_##call, \ 265 .unregfunc = ftrace_raw_unreg_event_##call, \
229 .show_format = ftrace_format_##call, \ 266 .show_format = ftrace_format_##call, \
267 _TRACE_PROFILE_INIT(call) \
230} 268}
269
270#include <trace/trace_event_types.h>
271
272#undef _TRACE_PROFILE
273#undef _TRACE_PROFILE_INIT
274