aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace/trace_event_profile.c
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2009-09-19 06:05:25 -0400
committerIngo Molnar <mingo@elte.hu>2009-09-19 06:05:25 -0400
commitbe4bdbfbae6b303c21ebe446648f617908a794b5 (patch)
tree4ea485b2fa95cb17aded35b0ac83d6bdf9a0396d /kernel/trace/trace_event_profile.c
parentfc5377668c3d808e1d53c4aee152c836f55c3490 (diff)
parent20ab4425a77a1f34028cc6ce57053c22c184ba5f (diff)
Merge branch 'tracing/core-v3' of git://git.kernel.org/pub/scm/linux/kernel/git/frederic/random-tracing into tracing/urgent
Diffstat (limited to 'kernel/trace/trace_event_profile.c')
-rw-r--r--kernel/trace/trace_event_profile.c79
1 files changed, 77 insertions, 2 deletions
diff --git a/kernel/trace/trace_event_profile.c b/kernel/trace/trace_event_profile.c
index 55a25c933d15..3aaa77c3309b 100644
--- a/kernel/trace/trace_event_profile.c
+++ b/kernel/trace/trace_event_profile.c
@@ -8,6 +8,54 @@
8#include <linux/module.h> 8#include <linux/module.h>
9#include "trace.h" 9#include "trace.h"
10 10
11/*
12 * We can't use a size but a type in alloc_percpu()
13 * So let's create a dummy type that matches the desired size
14 */
15typedef struct {char buf[FTRACE_MAX_PROFILE_SIZE];} profile_buf_t;
16
17char *trace_profile_buf;
18char *trace_profile_buf_nmi;
19
20/* Count the events in use (per event id, not per instance) */
21static int total_profile_count;
22
23static int ftrace_profile_enable_event(struct ftrace_event_call *event)
24{
25 char *buf;
26 int ret = -ENOMEM;
27
28 if (atomic_inc_return(&event->profile_count))
29 return 0;
30
31 if (!total_profile_count++) {
32 buf = (char *)alloc_percpu(profile_buf_t);
33 if (!buf)
34 goto fail_buf;
35
36 rcu_assign_pointer(trace_profile_buf, buf);
37
38 buf = (char *)alloc_percpu(profile_buf_t);
39 if (!buf)
40 goto fail_buf_nmi;
41
42 rcu_assign_pointer(trace_profile_buf_nmi, buf);
43 }
44
45 ret = event->profile_enable();
46 if (!ret)
47 return 0;
48
49 kfree(trace_profile_buf_nmi);
50fail_buf_nmi:
51 kfree(trace_profile_buf);
52fail_buf:
53 total_profile_count--;
54 atomic_dec(&event->profile_count);
55
56 return ret;
57}
58
11int ftrace_profile_enable(int event_id) 59int ftrace_profile_enable(int event_id)
12{ 60{
13 struct ftrace_event_call *event; 61 struct ftrace_event_call *event;
@@ -17,7 +65,7 @@ int ftrace_profile_enable(int event_id)
17 list_for_each_entry(event, &ftrace_events, list) { 65 list_for_each_entry(event, &ftrace_events, list) {
18 if (event->id == event_id && event->profile_enable && 66 if (event->id == event_id && event->profile_enable &&
19 try_module_get(event->mod)) { 67 try_module_get(event->mod)) {
20 ret = event->profile_enable(event); 68 ret = ftrace_profile_enable_event(event);
21 break; 69 break;
22 } 70 }
23 } 71 }
@@ -26,6 +74,33 @@ int ftrace_profile_enable(int event_id)
26 return ret; 74 return ret;
27} 75}
28 76
77static void ftrace_profile_disable_event(struct ftrace_event_call *event)
78{
79 char *buf, *nmi_buf;
80
81 if (!atomic_add_negative(-1, &event->profile_count))
82 return;
83
84 event->profile_disable();
85
86 if (!--total_profile_count) {
87 buf = trace_profile_buf;
88 rcu_assign_pointer(trace_profile_buf, NULL);
89
90 nmi_buf = trace_profile_buf_nmi;
91 rcu_assign_pointer(trace_profile_buf_nmi, NULL);
92
93 /*
94 * Ensure every events in profiling have finished before
95 * releasing the buffers
96 */
97 synchronize_sched();
98
99 free_percpu(buf);
100 free_percpu(nmi_buf);
101 }
102}
103
29void ftrace_profile_disable(int event_id) 104void ftrace_profile_disable(int event_id)
30{ 105{
31 struct ftrace_event_call *event; 106 struct ftrace_event_call *event;
@@ -33,7 +108,7 @@ void ftrace_profile_disable(int event_id)
33 mutex_lock(&event_mutex); 108 mutex_lock(&event_mutex);
34 list_for_each_entry(event, &ftrace_events, list) { 109 list_for_each_entry(event, &ftrace_events, list) {
35 if (event->id == event_id) { 110 if (event->id == event_id) {
36 event->profile_disable(event); 111 ftrace_profile_disable_event(event);
37 module_put(event->mod); 112 module_put(event->mod);
38 break; 113 break;
39 } 114 }