diff options
author | Josh Stone <jistone@redhat.com> | 2009-08-24 17:43:13 -0400 |
---|---|---|
committer | Frederic Weisbecker <fweisbec@gmail.com> | 2009-08-25 18:36:41 -0400 |
commit | 97419875865859fd2403e66266c02ce028e2f5ab (patch) | |
tree | 7df6e6df767e9c8ff538a50bcae17638a1c8da99 /kernel/tracepoint.c | |
parent | 3d27d8cb34fc156beb86de2338ca4029873a5cc6 (diff) |
tracing: Move tracepoint callbacks from declaration to definition
It's not strictly correct for the tracepoint reg/unreg callbacks to
occur when a client is hooking up, because the actual tracepoint may not
be present yet. This happens to be fine for syscall, since that's in
the core kernel, but it would cause problems for tracepoints defined in
a module that hasn't been loaded yet. It also means the reg/unreg has
to be EXPORTed for any modules to use the tracepoint (as in SystemTap).
This patch removes DECLARE_TRACE_WITH_CALLBACK, and instead introduces
DEFINE_TRACE_FN which stores the callbacks in struct tracepoint. The
callbacks are used now when the active state of the tracepoint changes
in set_tracepoint & disable_tracepoint.
This also introduces TRACE_EVENT_FN, so ftrace events can also provide
registration callbacks if needed.
Signed-off-by: Josh Stone <jistone@redhat.com>
Cc: Jason Baron <jbaron@redhat.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Li Zefan <lizf@cn.fujitsu.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
Cc: Jiaying Zhang <jiayingz@google.com>
Cc: Martin Bligh <mbligh@google.com>
Cc: Lai Jiangshan <laijs@cn.fujitsu.com>
Cc: Paul Mundt <lethal@linux-sh.org>
Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
Cc: Heiko Carstens <heiko.carstens@de.ibm.com>
LKML-Reference: <1251150194-1713-4-git-send-email-jistone@redhat.com>
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Diffstat (limited to 'kernel/tracepoint.c')
-rw-r--r-- | kernel/tracepoint.c | 14 |
1 files changed, 9 insertions, 5 deletions
diff --git a/kernel/tracepoint.c b/kernel/tracepoint.c index 9e0a36f0e2a9..1a6a453b7efb 100644 --- a/kernel/tracepoint.c +++ b/kernel/tracepoint.c | |||
@@ -243,6 +243,11 @@ static void set_tracepoint(struct tracepoint_entry **entry, | |||
243 | { | 243 | { |
244 | WARN_ON(strcmp((*entry)->name, elem->name) != 0); | 244 | WARN_ON(strcmp((*entry)->name, elem->name) != 0); |
245 | 245 | ||
246 | if (elem->regfunc && !elem->state && active) | ||
247 | elem->regfunc(); | ||
248 | else if (elem->unregfunc && elem->state && !active) | ||
249 | elem->unregfunc(); | ||
250 | |||
246 | /* | 251 | /* |
247 | * rcu_assign_pointer has a smp_wmb() which makes sure that the new | 252 | * rcu_assign_pointer has a smp_wmb() which makes sure that the new |
248 | * probe callbacks array is consistent before setting a pointer to it. | 253 | * probe callbacks array is consistent before setting a pointer to it. |
@@ -262,6 +267,9 @@ static void set_tracepoint(struct tracepoint_entry **entry, | |||
262 | */ | 267 | */ |
263 | static void disable_tracepoint(struct tracepoint *elem) | 268 | static void disable_tracepoint(struct tracepoint *elem) |
264 | { | 269 | { |
270 | if (elem->unregfunc && elem->state) | ||
271 | elem->unregfunc(); | ||
272 | |||
265 | elem->state = 0; | 273 | elem->state = 0; |
266 | rcu_assign_pointer(elem->funcs, NULL); | 274 | rcu_assign_pointer(elem->funcs, NULL); |
267 | } | 275 | } |
@@ -578,7 +586,7 @@ __initcall(init_tracepoints); | |||
578 | 586 | ||
579 | #ifdef CONFIG_HAVE_SYSCALL_TRACEPOINTS | 587 | #ifdef CONFIG_HAVE_SYSCALL_TRACEPOINTS |
580 | 588 | ||
581 | static DEFINE_MUTEX(regfunc_mutex); | 589 | /* NB: reg/unreg are called while guarded with the tracepoints_mutex */ |
582 | static int sys_tracepoint_refcount; | 590 | static int sys_tracepoint_refcount; |
583 | 591 | ||
584 | void syscall_regfunc(void) | 592 | void syscall_regfunc(void) |
@@ -586,7 +594,6 @@ void syscall_regfunc(void) | |||
586 | unsigned long flags; | 594 | unsigned long flags; |
587 | struct task_struct *g, *t; | 595 | struct task_struct *g, *t; |
588 | 596 | ||
589 | mutex_lock(®func_mutex); | ||
590 | if (!sys_tracepoint_refcount) { | 597 | if (!sys_tracepoint_refcount) { |
591 | read_lock_irqsave(&tasklist_lock, flags); | 598 | read_lock_irqsave(&tasklist_lock, flags); |
592 | do_each_thread(g, t) { | 599 | do_each_thread(g, t) { |
@@ -595,7 +602,6 @@ void syscall_regfunc(void) | |||
595 | read_unlock_irqrestore(&tasklist_lock, flags); | 602 | read_unlock_irqrestore(&tasklist_lock, flags); |
596 | } | 603 | } |
597 | sys_tracepoint_refcount++; | 604 | sys_tracepoint_refcount++; |
598 | mutex_unlock(®func_mutex); | ||
599 | } | 605 | } |
600 | 606 | ||
601 | void syscall_unregfunc(void) | 607 | void syscall_unregfunc(void) |
@@ -603,7 +609,6 @@ void syscall_unregfunc(void) | |||
603 | unsigned long flags; | 609 | unsigned long flags; |
604 | struct task_struct *g, *t; | 610 | struct task_struct *g, *t; |
605 | 611 | ||
606 | mutex_lock(®func_mutex); | ||
607 | sys_tracepoint_refcount--; | 612 | sys_tracepoint_refcount--; |
608 | if (!sys_tracepoint_refcount) { | 613 | if (!sys_tracepoint_refcount) { |
609 | read_lock_irqsave(&tasklist_lock, flags); | 614 | read_lock_irqsave(&tasklist_lock, flags); |
@@ -612,6 +617,5 @@ void syscall_unregfunc(void) | |||
612 | } while_each_thread(g, t); | 617 | } while_each_thread(g, t); |
613 | read_unlock_irqrestore(&tasklist_lock, flags); | 618 | read_unlock_irqrestore(&tasklist_lock, flags); |
614 | } | 619 | } |
615 | mutex_unlock(®func_mutex); | ||
616 | } | 620 | } |
617 | #endif | 621 | #endif |