aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorSteven Rostedt <srostedt@redhat.com>2009-04-15 13:36:40 -0400
committerIngo Molnar <mingo@elte.hu>2009-04-17 11:01:37 -0400
commite6187007d6c365b551c69ea3df46f06fd1c8bd19 (patch)
tree6607598ccbe4f10470114f3667649c603d19cc0c /kernel
parent93eb677d74a4f7d3edfb678c94f6c0544d9fbad2 (diff)
tracing/events: add startup tests for events
As events start to become popular, and the new way to add tracing infrastructure into ftrace, it is important to catch any problems that might happen with a mistake in the TRACE_EVENT macro. This patch introduces a startup self test on the registered trace events. Note, it can only do a generic test, any type of testing that needs more involement is needed to be implemented by the tracepoint creators. The test goes down one by one enabling a trace point and running some random tasks (random in the sense that I just made them up). Those tasks are creating threads, grabbing mutexes and spinlocks and using workqueues. After testing each event individually, it does the same test after enabling each system of trace points. Like sched, irq, lockdep. Then finally it enables all tracepoints and performs the tasks again. The output to the console on bootup will look like this when everything works: Running tests on trace events: Testing event kfree_skb: OK Testing event kmalloc: OK Testing event kmem_cache_alloc: OK Testing event kmalloc_node: OK Testing event kmem_cache_alloc_node: OK Testing event kfree: OK Testing event kmem_cache_free: OK Testing event irq_handler_exit: OK Testing event irq_handler_entry: OK Testing event softirq_entry: OK Testing event softirq_exit: OK Testing event lock_acquire: OK Testing event lock_release: OK Testing event sched_kthread_stop: OK Testing event sched_kthread_stop_ret: OK Testing event sched_wait_task: OK Testing event sched_wakeup: OK Testing event sched_wakeup_new: OK Testing event sched_switch: OK Testing event sched_migrate_task: OK Testing event sched_process_free: OK Testing event sched_process_exit: OK Testing event sched_process_wait: OK Testing event sched_process_fork: OK Testing event sched_signal_send: OK Running tests on trace event systems: Testing event system skb: OK Testing event system kmem: OK Testing event system irq: OK Testing event system lockdep: OK Testing event system sched: OK Running tests on all trace events: Testing all events: OK [ folded in: tracing: add #include <linux/delay.h> to fix build failure in test_work() This build failure occured on a few rare configs: kernel/trace/trace_events.c: In function ‘test_work’: kernel/trace/trace_events.c:975: error: implicit declaration of function ‘udelay’ kernel/trace/trace_events.c:980: error: implicit declaration of function ‘msleep’ delay.h is included in way too many other headers, hiding cases where new usage is added without header inclusion. [ Impact: build fix ] Signed-off-by: Ingo Molnar <mingo@elte.hu> ] [ Impact: add event tracer self-tests ] Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/trace/trace_events.c178
1 files changed, 178 insertions, 0 deletions
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index 6591d83e1e7a..f81d6eec4e43 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -8,10 +8,14 @@
8 * 8 *
9 */ 9 */
10 10
11#include <linux/workqueue.h>
12#include <linux/spinlock.h>
13#include <linux/kthread.h>
11#include <linux/debugfs.h> 14#include <linux/debugfs.h>
12#include <linux/uaccess.h> 15#include <linux/uaccess.h>
13#include <linux/module.h> 16#include <linux/module.h>
14#include <linux/ctype.h> 17#include <linux/ctype.h>
18#include <linux/delay.h>
15 19
16#include "trace_output.h" 20#include "trace_output.h"
17 21
@@ -920,3 +924,177 @@ static __init int event_trace_init(void)
920 return 0; 924 return 0;
921} 925}
922fs_initcall(event_trace_init); 926fs_initcall(event_trace_init);
927
928#ifdef CONFIG_FTRACE_STARTUP_TEST
929
930static DEFINE_SPINLOCK(test_spinlock);
931static DEFINE_SPINLOCK(test_spinlock_irq);
932static DEFINE_MUTEX(test_mutex);
933
934static __init void test_work(struct work_struct *dummy)
935{
936 spin_lock(&test_spinlock);
937 spin_lock_irq(&test_spinlock_irq);
938 udelay(1);
939 spin_unlock_irq(&test_spinlock_irq);
940 spin_unlock(&test_spinlock);
941
942 mutex_lock(&test_mutex);
943 msleep(1);
944 mutex_unlock(&test_mutex);
945}
946
947static __init int event_test_thread(void *unused)
948{
949 void *test_malloc;
950
951 test_malloc = kmalloc(1234, GFP_KERNEL);
952 if (!test_malloc)
953 pr_info("failed to kmalloc\n");
954
955 schedule_on_each_cpu(test_work);
956
957 kfree(test_malloc);
958
959 set_current_state(TASK_INTERRUPTIBLE);
960 while (!kthread_should_stop())
961 schedule();
962
963 return 0;
964}
965
966/*
967 * Do various things that may trigger events.
968 */
969static __init void event_test_stuff(void)
970{
971 struct task_struct *test_thread;
972
973 test_thread = kthread_run(event_test_thread, NULL, "test-events");
974 msleep(1);
975 kthread_stop(test_thread);
976}
977
978/*
979 * For every trace event defined, we will test each trace point separately,
980 * and then by groups, and finally all trace points.
981 */
982static __init int event_trace_self_tests(void)
983{
984 struct ftrace_event_call *call;
985 struct event_subsystem *system;
986 char *sysname;
987 int ret;
988
989 pr_info("Running tests on trace events:\n");
990
991 list_for_each_entry(call, &ftrace_events, list) {
992
993 /* Only test those that have a regfunc */
994 if (!call->regfunc)
995 continue;
996
997 pr_info("Testing event %s: ", call->name);
998
999 /*
1000 * If an event is already enabled, someone is using
1001 * it and the self test should not be on.
1002 */
1003 if (call->enabled) {
1004 pr_warning("Enabled event during self test!\n");
1005 WARN_ON_ONCE(1);
1006 continue;
1007 }
1008
1009 call->enabled = 1;
1010 call->regfunc();
1011
1012 event_test_stuff();
1013
1014 call->unregfunc();
1015 call->enabled = 0;
1016
1017 pr_cont("OK\n");
1018 }
1019
1020 /* Now test at the sub system level */
1021
1022 pr_info("Running tests on trace event systems:\n");
1023
1024 list_for_each_entry(system, &event_subsystems, list) {
1025
1026 /* the ftrace system is special, skip it */
1027 if (strcmp(system->name, "ftrace") == 0)
1028 continue;
1029
1030 pr_info("Testing event system %s: ", system->name);
1031
1032 /* ftrace_set_clr_event can modify the name passed in. */
1033 sysname = kstrdup(system->name, GFP_KERNEL);
1034 if (WARN_ON(!sysname)) {
1035 pr_warning("Can't allocate memory, giving up!\n");
1036 return 0;
1037 }
1038 ret = ftrace_set_clr_event(sysname, 1);
1039 kfree(sysname);
1040 if (WARN_ON_ONCE(ret)) {
1041 pr_warning("error enabling system %s\n",
1042 system->name);
1043 continue;
1044 }
1045
1046 event_test_stuff();
1047
1048 sysname = kstrdup(system->name, GFP_KERNEL);
1049 if (WARN_ON(!sysname)) {
1050 pr_warning("Can't allocate memory, giving up!\n");
1051 return 0;
1052 }
1053 ret = ftrace_set_clr_event(sysname, 0);
1054 kfree(sysname);
1055
1056 if (WARN_ON_ONCE(ret))
1057 pr_warning("error disabling system %s\n",
1058 system->name);
1059
1060 pr_cont("OK\n");
1061 }
1062
1063 /* Test with all events enabled */
1064
1065 pr_info("Running tests on all trace events:\n");
1066 pr_info("Testing all events: ");
1067
1068 sysname = kmalloc(4, GFP_KERNEL);
1069 if (WARN_ON(!sysname)) {
1070 pr_warning("Can't allocate memory, giving up!\n");
1071 return 0;
1072 }
1073 memcpy(sysname, "*:*", 4);
1074 ret = ftrace_set_clr_event(sysname, 1);
1075 if (WARN_ON_ONCE(ret)) {
1076 kfree(sysname);
1077 pr_warning("error enabling all events\n");
1078 return 0;
1079 }
1080
1081 event_test_stuff();
1082
1083 /* reset sysname */
1084 memcpy(sysname, "*:*", 4);
1085 ret = ftrace_set_clr_event(sysname, 0);
1086 kfree(sysname);
1087
1088 if (WARN_ON_ONCE(ret)) {
1089 pr_warning("error disabling all events\n");
1090 return 0;
1091 }
1092
1093 pr_cont("OK\n");
1094
1095 return 0;
1096}
1097
1098late_initcall(event_trace_self_tests);
1099
1100#endif