aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace/trace_syscalls.c
diff options
context:
space:
mode:
authorJason Baron <jbaron@redhat.com>2009-08-10 16:53:02 -0400
committerFrederic Weisbecker <fweisbec@gmail.com>2009-08-11 14:35:29 -0400
commitf4b5ffccc83c82947f5d9f15d6f1b6edb1b71cd7 (patch)
tree06ec4a005b40ba0b6039e6c3425dd186486b8c6f /kernel/trace/trace_syscalls.c
parent64c12e0444fcc6b75eb49144ba46d43dbdc6bc8f (diff)
tracing: Add perf counter support for syscalls tracing
The perf counter support is automated for usual trace events. But we have to define specific callbacks for this to handle syscalls trace events Make 'perf stat -e syscalls:sys_enter_blah' work with syscall style tracepoints. Signed-off-by: Jason Baron <jbaron@redhat.com> Cc: Lai Jiangshan <laijs@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: Li Zefan <lizf@cn.fujitsu.com> Cc: Masami Hiramatsu <mhiramat@redhat.com> Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Diffstat (limited to 'kernel/trace/trace_syscalls.c')
-rw-r--r--kernel/trace/trace_syscalls.c121
1 files changed, 121 insertions, 0 deletions
diff --git a/kernel/trace/trace_syscalls.c b/kernel/trace/trace_syscalls.c
index e58a9c11ba85..f4eaec3d559a 100644
--- a/kernel/trace/trace_syscalls.c
+++ b/kernel/trace/trace_syscalls.c
@@ -1,6 +1,7 @@
1#include <trace/syscall.h> 1#include <trace/syscall.h>
2#include <linux/kernel.h> 2#include <linux/kernel.h>
3#include <linux/ftrace.h> 3#include <linux/ftrace.h>
4#include <linux/perf_counter.h>
4#include <asm/syscall.h> 5#include <asm/syscall.h>
5 6
6#include "trace_output.h" 7#include "trace_output.h"
@@ -252,3 +253,123 @@ struct trace_event event_syscall_enter = {
252struct trace_event event_syscall_exit = { 253struct trace_event event_syscall_exit = {
253 .trace = print_syscall_exit, 254 .trace = print_syscall_exit,
254}; 255};
256
257#ifdef CONFIG_EVENT_PROFILE
258static DECLARE_BITMAP(enabled_prof_enter_syscalls, FTRACE_SYSCALL_MAX);
259static DECLARE_BITMAP(enabled_prof_exit_syscalls, FTRACE_SYSCALL_MAX);
260static int sys_prof_refcount_enter;
261static int sys_prof_refcount_exit;
262
263static void prof_syscall_enter(struct pt_regs *regs, long id)
264{
265 struct syscall_metadata *sys_data;
266 int syscall_nr;
267
268 syscall_nr = syscall_get_nr(current, regs);
269 if (!test_bit(syscall_nr, enabled_prof_enter_syscalls))
270 return;
271
272 sys_data = syscall_nr_to_meta(syscall_nr);
273 if (!sys_data)
274 return;
275
276 perf_tpcounter_event(sys_data->enter_id, 0, 1, NULL, 0);
277}
278
279int reg_prof_syscall_enter(char *name)
280{
281 int ret = 0;
282 int num;
283
284 num = syscall_name_to_nr(name);
285 if (num < 0 || num >= FTRACE_SYSCALL_MAX)
286 return -ENOSYS;
287
288 mutex_lock(&syscall_trace_lock);
289 if (!sys_prof_refcount_enter)
290 ret = register_trace_syscall_enter(prof_syscall_enter);
291 if (ret) {
292 pr_info("event trace: Could not activate"
293 "syscall entry trace point");
294 } else {
295 set_bit(num, enabled_prof_enter_syscalls);
296 sys_prof_refcount_enter++;
297 }
298 mutex_unlock(&syscall_trace_lock);
299 return ret;
300}
301
302void unreg_prof_syscall_enter(char *name)
303{
304 int num;
305
306 num = syscall_name_to_nr(name);
307 if (num < 0 || num >= FTRACE_SYSCALL_MAX)
308 return;
309
310 mutex_lock(&syscall_trace_lock);
311 sys_prof_refcount_enter--;
312 clear_bit(num, enabled_prof_enter_syscalls);
313 if (!sys_prof_refcount_enter)
314 unregister_trace_syscall_enter(prof_syscall_enter);
315 mutex_unlock(&syscall_trace_lock);
316}
317
318static void prof_syscall_exit(struct pt_regs *regs, long ret)
319{
320 struct syscall_metadata *sys_data;
321 int syscall_nr;
322
323 syscall_nr = syscall_get_nr(current, regs);
324 if (!test_bit(syscall_nr, enabled_prof_exit_syscalls))
325 return;
326
327 sys_data = syscall_nr_to_meta(syscall_nr);
328 if (!sys_data)
329 return;
330
331 perf_tpcounter_event(sys_data->exit_id, 0, 1, NULL, 0);
332}
333
334int reg_prof_syscall_exit(char *name)
335{
336 int ret = 0;
337 int num;
338
339 num = syscall_name_to_nr(name);
340 if (num < 0 || num >= FTRACE_SYSCALL_MAX)
341 return -ENOSYS;
342
343 mutex_lock(&syscall_trace_lock);
344 if (!sys_prof_refcount_exit)
345 ret = register_trace_syscall_exit(prof_syscall_exit);
346 if (ret) {
347 pr_info("event trace: Could not activate"
348 "syscall entry trace point");
349 } else {
350 set_bit(num, enabled_prof_exit_syscalls);
351 sys_prof_refcount_exit++;
352 }
353 mutex_unlock(&syscall_trace_lock);
354 return ret;
355}
356
357void unreg_prof_syscall_exit(char *name)
358{
359 int num;
360
361 num = syscall_name_to_nr(name);
362 if (num < 0 || num >= FTRACE_SYSCALL_MAX)
363 return;
364
365 mutex_lock(&syscall_trace_lock);
366 sys_prof_refcount_exit--;
367 clear_bit(num, enabled_prof_exit_syscalls);
368 if (!sys_prof_refcount_exit)
369 unregister_trace_syscall_exit(prof_syscall_exit);
370 mutex_unlock(&syscall_trace_lock);
371}
372
373#endif
374
375