aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/tracepoint.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/tracepoint.c')
-rw-r--r--kernel/tracepoint.c20
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 */
263static void disable_tracepoint(struct tracepoint *elem) 268static 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
581static DEFINE_MUTEX(regfunc_mutex); 589/* NB: reg/unreg are called while guarded with the tracepoints_mutex */
582static int sys_tracepoint_refcount; 590static int sys_tracepoint_refcount;
583 591
584void syscall_regfunc(void) 592void 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(&regfunc_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(&regfunc_mutex);
599} 605}
600 606
601void syscall_unregfunc(void) 607void 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(&regfunc_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(&regfunc_mutex);
616} 620}
617#endif 621#endif