diff options
author | Paul E. McKenney <paulmck@linux.vnet.ibm.com> | 2010-03-05 18:03:25 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2010-03-11 07:38:01 -0500 |
commit | 3f379b03fbfddd20536389a85c6456f8233d1f8d (patch) | |
tree | 2847590a23aa0d72e799bd6d65a8a794abb565ac /kernel | |
parent | 54dbf96c921513bf98484a20ef366d51944a4c4d (diff) |
ftrace: Replace read_barrier_depends() with rcu_dereference_raw()
Replace the calls to read_barrier_depends() in
ftrace_list_func() with rcu_dereference_raw() to improve
readability. The reason that we use rcu_dereference_raw() here
is that removed entries are never freed, instead they are simply
leaked. This is one of a very few cases where use of
rcu_dereference_raw() is the long-term right answer. And I
don't yet know of any others. ;-)
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Acked-by: Steven Rostedt <rostedt@goodmis.org>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: laijs@cn.fujitsu.com
Cc: dipankar@in.ibm.com
Cc: mathieu.desnoyers@polymtl.ca
Cc: josh@joshtriplett.org
Cc: dvhltc@us.ibm.com
Cc: niv@us.ibm.com
Cc: peterz@infradead.org
Cc: Valdis.Kletnieks@vt.edu
Cc: dhowells@redhat.com
LKML-Reference: <1267830207-9474-1-git-send-email-paulmck@linux.vnet.ibm.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/trace/ftrace.c | 22 |
1 files changed, 13 insertions, 9 deletions
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 83783579378f..8c5adc0e5db3 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/ctype.h> | 27 | #include <linux/ctype.h> |
28 | #include <linux/list.h> | 28 | #include <linux/list.h> |
29 | #include <linux/hash.h> | 29 | #include <linux/hash.h> |
30 | #include <linux/rcupdate.h> | ||
30 | 31 | ||
31 | #include <trace/events/sched.h> | 32 | #include <trace/events/sched.h> |
32 | 33 | ||
@@ -88,18 +89,22 @@ ftrace_func_t ftrace_pid_function __read_mostly = ftrace_stub; | |||
88 | static int ftrace_set_func(unsigned long *array, int *idx, char *buffer); | 89 | static int ftrace_set_func(unsigned long *array, int *idx, char *buffer); |
89 | #endif | 90 | #endif |
90 | 91 | ||
92 | /* | ||
93 | * Traverse the ftrace_list, invoking all entries. The reason that we | ||
94 | * can use rcu_dereference_raw() is that elements removed from this list | ||
95 | * are simply leaked, so there is no need to interact with a grace-period | ||
96 | * mechanism. The rcu_dereference_raw() calls are needed to handle | ||
97 | * concurrent insertions into the ftrace_list. | ||
98 | * | ||
99 | * Silly Alpha and silly pointer-speculation compiler optimizations! | ||
100 | */ | ||
91 | static void ftrace_list_func(unsigned long ip, unsigned long parent_ip) | 101 | static void ftrace_list_func(unsigned long ip, unsigned long parent_ip) |
92 | { | 102 | { |
93 | struct ftrace_ops *op = ftrace_list; | 103 | struct ftrace_ops *op = rcu_dereference_raw(ftrace_list); /*see above*/ |
94 | |||
95 | /* in case someone actually ports this to alpha! */ | ||
96 | read_barrier_depends(); | ||
97 | 104 | ||
98 | while (op != &ftrace_list_end) { | 105 | while (op != &ftrace_list_end) { |
99 | /* silly alpha */ | ||
100 | read_barrier_depends(); | ||
101 | op->func(ip, parent_ip); | 106 | op->func(ip, parent_ip); |
102 | op = op->next; | 107 | op = rcu_dereference_raw(op->next); /*see above*/ |
103 | }; | 108 | }; |
104 | } | 109 | } |
105 | 110 | ||
@@ -154,8 +159,7 @@ static int __register_ftrace_function(struct ftrace_ops *ops) | |||
154 | * the ops->next pointer is valid before another CPU sees | 159 | * the ops->next pointer is valid before another CPU sees |
155 | * the ops pointer included into the ftrace_list. | 160 | * the ops pointer included into the ftrace_list. |
156 | */ | 161 | */ |
157 | smp_wmb(); | 162 | rcu_assign_pointer(ftrace_list, ops); |
158 | ftrace_list = ops; | ||
159 | 163 | ||
160 | if (ftrace_enabled) { | 164 | if (ftrace_enabled) { |
161 | ftrace_func_t func; | 165 | ftrace_func_t func; |