]>
Commit | Line | Data |
---|---|---|
ee08c6ec FW |
1 | #include <linux/ftrace.h> |
2 | #include <linux/kernel.h> | |
3 | ||
4 | #include <asm/syscall.h> | |
5 | ||
6 | #include "trace_output.h" | |
7 | #include "trace.h" | |
8 | ||
9 | static atomic_t refcount; | |
10 | ||
11 | void start_ftrace_syscalls(void) | |
12 | { | |
13 | unsigned long flags; | |
14 | struct task_struct *g, *t; | |
15 | ||
16 | if (atomic_inc_return(&refcount) != 1) | |
17 | goto out; | |
18 | ||
19 | read_lock_irqsave(&tasklist_lock, flags); | |
20 | ||
21 | do_each_thread(g, t) { | |
22 | set_tsk_thread_flag(t, TIF_SYSCALL_FTRACE); | |
23 | } while_each_thread(g, t); | |
24 | ||
25 | read_unlock_irqrestore(&tasklist_lock, flags); | |
26 | out: | |
27 | atomic_dec(&refcount); | |
28 | } | |
29 | ||
30 | void stop_ftrace_syscalls(void) | |
31 | { | |
32 | unsigned long flags; | |
33 | struct task_struct *g, *t; | |
34 | ||
35 | if (atomic_dec_return(&refcount)) | |
36 | goto out; | |
37 | ||
38 | read_lock_irqsave(&tasklist_lock, flags); | |
39 | ||
40 | do_each_thread(g, t) { | |
41 | clear_tsk_thread_flag(t, TIF_SYSCALL_FTRACE); | |
42 | } while_each_thread(g, t); | |
43 | ||
44 | read_unlock_irqrestore(&tasklist_lock, flags); | |
45 | out: | |
46 | atomic_inc(&refcount); | |
47 | } | |
48 | ||
49 | void ftrace_syscall_enter(struct pt_regs *regs) | |
50 | { | |
51 | int syscall_nr; | |
52 | ||
53 | syscall_nr = syscall_get_nr(current, regs); | |
54 | ||
55 | trace_printk("syscall %d enter\n", syscall_nr); | |
56 | } | |
57 | ||
58 | void ftrace_syscall_exit(struct pt_regs *regs) | |
59 | { | |
60 | int syscall_nr; | |
61 | ||
62 | syscall_nr = syscall_get_nr(current, regs); | |
63 | ||
64 | trace_printk("syscall %d exit\n", syscall_nr); | |
65 | } | |
66 | ||
67 | static int init_syscall_tracer(struct trace_array *tr) | |
68 | { | |
69 | start_ftrace_syscalls(); | |
70 | ||
71 | return 0; | |
72 | } | |
73 | ||
74 | static void reset_syscall_tracer(struct trace_array *tr) | |
75 | { | |
76 | stop_ftrace_syscalls(); | |
77 | } | |
78 | ||
79 | static struct trace_event syscall_enter_event = { | |
80 | .type = TRACE_SYSCALL_ENTER, | |
81 | }; | |
82 | ||
83 | static struct trace_event syscall_exit_event = { | |
84 | .type = TRACE_SYSCALL_EXIT, | |
85 | }; | |
86 | ||
87 | static struct tracer syscall_tracer __read_mostly = { | |
88 | .name = "syscall", | |
89 | .init = init_syscall_tracer, | |
90 | .reset = reset_syscall_tracer | |
91 | }; | |
92 | ||
93 | __init int register_ftrace_syscalls(void) | |
94 | { | |
95 | int ret; | |
96 | ||
97 | ret = register_ftrace_event(&syscall_enter_event); | |
98 | if (!ret) { | |
99 | printk(KERN_WARNING "event %d failed to register\n", | |
100 | syscall_enter_event.type); | |
101 | WARN_ON_ONCE(1); | |
102 | } | |
103 | ||
104 | ret = register_ftrace_event(&syscall_exit_event); | |
105 | if (!ret) { | |
106 | printk(KERN_WARNING "event %d failed to register\n", | |
107 | syscall_exit_event.type); | |
108 | WARN_ON_ONCE(1); | |
109 | } | |
110 | ||
111 | return register_tracer(&syscall_tracer); | |
112 | } | |
113 | device_initcall(register_ftrace_syscalls); |