diff options
Diffstat (limited to 'kernel/tracepoint.c')
-rw-r--r-- | kernel/tracepoint.c | 20 |
1 files changed, 12 insertions, 8 deletions
diff --git a/kernel/tracepoint.c b/kernel/tracepoint.c index 06f165a44083..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 | } |
@@ -576,9 +584,9 @@ __initcall(init_tracepoints); | |||
576 | 584 | ||
577 | #endif /* CONFIG_MODULES */ | 585 | #endif /* CONFIG_MODULES */ |
578 | 586 | ||
579 | #ifdef CONFIG_FTRACE_SYSCALLS | 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,16 +594,14 @@ 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) { |
593 | set_tsk_thread_flag(t, TIF_SYSCALL_FTRACE); | 600 | set_tsk_thread_flag(t, TIF_SYSCALL_TRACEPOINT); |
594 | } while_each_thread(g, t); | 601 | } while_each_thread(g, t); |
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,15 +609,13 @@ 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); |
610 | do_each_thread(g, t) { | 615 | do_each_thread(g, t) { |
611 | clear_tsk_thread_flag(t, TIF_SYSCALL_FTRACE); | 616 | clear_tsk_thread_flag(t, TIF_SYSCALL_TRACEPOINT); |
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 |