tracing: Add TRACE_CUSTOM_EVENT() macro
[linux-2.6-block.git] / samples / trace_events / trace_custom_sched.c
index 70a12c32ff99106ce22696fcbd3ad254f3f0dc25..b99d9ab7db858f8e309980bee271f6b40c6a06c7 100644 (file)
 #include <linux/version.h>
 #include <linux/module.h>
 #include <linux/sched.h>
-#include <trace/events/sched.h>
-
-#define THIS_SYSTEM "custom_sched"
-
-#define SCHED_PRINT_FMT                                                        \
-       C("prev_prio=%d next_pid=%d next_prio=%d", REC->prev_prio, REC->next_pid, \
-         REC->next_prio)
-
-#define SCHED_WAKING_FMT                               \
-       C("pid=%d prio=%d", REC->pid, REC->prio)
-
-#undef C
-#define C(a, b...) a, b
-
-static struct trace_event_fields sched_switch_fields[] = {
-       {
-               .type = "unsigned short",
-               .name = "prev_prio",
-               .size = sizeof(short),
-               .align = __alignof__(short),
-               .is_signed = 0,
-               .filter_type = FILTER_OTHER,
-       },
-       {
-               .type = "unsigned short",
-               .name = "next_prio",
-               .size = sizeof(short),
-               .align = __alignof__(short),
-               .is_signed = 0,
-               .filter_type = FILTER_OTHER,
-       },
-       {
-               .type = "unsigned int",
-               .name = "next_prio",
-               .size = sizeof(int),
-               .align = __alignof__(int),
-               .is_signed = 0,
-               .filter_type = FILTER_OTHER,
-       },
-       {}
-};
-
-struct sched_event {
-       struct trace_entry      ent;
-       unsigned short          prev_prio;
-       unsigned short          next_prio;
-       unsigned int            next_pid;
-};
-
-static struct trace_event_fields sched_waking_fields[] = {
-       {
-               .type = "unsigned int",
-               .name = "pid",
-               .size = sizeof(int),
-               .align = __alignof__(int),
-               .is_signed = 0,
-               .filter_type = FILTER_OTHER,
-       },
-       {
-               .type = "unsigned short",
-               .name = "prio",
-               .size = sizeof(short),
-               .align = __alignof__(short),
-               .is_signed = 0,
-               .filter_type = FILTER_OTHER,
-       },
-       {}
-};
-
-struct wake_event {
-       struct trace_entry      ent;
-       unsigned int            pid;
-       unsigned short          prio;
-};
-
-static void sched_switch_probe(void *data, bool preempt, struct task_struct *prev,
-                              struct task_struct *next)
-{
-       struct trace_event_file *trace_file = data;
-       struct trace_event_buffer fbuffer;
-       struct sched_event *entry;
-
-       if (trace_trigger_soft_disabled(trace_file))
-               return;
-
-       entry = trace_event_buffer_reserve(&fbuffer, trace_file,
-                                          sizeof(*entry));
-
-       if (!entry)
-               return;
-
-       entry->prev_prio = prev->prio;
-       entry->next_prio = next->prio;
-       entry->next_pid = next->pid;
-
-       trace_event_buffer_commit(&fbuffer);
-}
-
-static struct trace_event_class sched_switch_class = {
-       .system                 = THIS_SYSTEM,
-       .reg                    = trace_event_reg,
-       .fields_array           = sched_switch_fields,
-       .fields                 = LIST_HEAD_INIT(sched_switch_class.fields),
-       .probe                  = sched_switch_probe,
-};
-
-static void sched_waking_probe(void *data, struct task_struct *t)
-{
-       struct trace_event_file *trace_file = data;
-       struct trace_event_buffer fbuffer;
-       struct wake_event *entry;
-
-       if (trace_trigger_soft_disabled(trace_file))
-               return;
-
-       entry = trace_event_buffer_reserve(&fbuffer, trace_file,
-                                          sizeof(*entry));
-
-       if (!entry)
-               return;
-
-       entry->prio = t->prio;
-       entry->pid = t->pid;
-
-       trace_event_buffer_commit(&fbuffer);
-}
-
-static struct trace_event_class sched_waking_class = {
-       .system                 = THIS_SYSTEM,
-       .reg                    = trace_event_reg,
-       .fields_array           = sched_waking_fields,
-       .fields                 = LIST_HEAD_INIT(sched_waking_class.fields),
-       .probe                  = sched_waking_probe,
-};
-
-static enum print_line_t sched_switch_output(struct trace_iterator *iter, int flags,
-                                            struct trace_event *trace_event)
-{
-       struct trace_seq *s = &iter->seq;
-       struct sched_event *REC = (struct sched_event *)iter->ent;
-       int ret;
-
-       ret = trace_raw_output_prep(iter, trace_event);
-       if (ret != TRACE_TYPE_HANDLED)
-               return ret;
-
-       trace_seq_printf(s, SCHED_PRINT_FMT);
-       trace_seq_putc(s, '\n');
 
-       return trace_handle_return(s);
-}
-
-static struct trace_event_functions sched_switch_funcs = {
-       .trace                  = sched_switch_output,
-};
-
-static enum print_line_t sched_waking_output(struct trace_iterator *iter, int flags,
-                                            struct trace_event *trace_event)
-{
-       struct trace_seq *s = &iter->seq;
-       struct wake_event *REC = (struct wake_event *)iter->ent;
-       int ret;
-
-       ret = trace_raw_output_prep(iter, trace_event);
-       if (ret != TRACE_TYPE_HANDLED)
-               return ret;
-
-       trace_seq_printf(s, SCHED_WAKING_FMT);
-       trace_seq_putc(s, '\n');
-
-       return trace_handle_return(s);
-}
-
-static struct trace_event_functions sched_waking_funcs = {
-       .trace                  = sched_waking_output,
-};
-
-#undef C
-#define C(a, b...) #a "," __stringify(b)
+/*
+ * Must include the event header that the custom event will attach to,
+ * from the C file, and not in the custom header file.
+ */
+#include <trace/events/sched.h>
 
-static struct trace_event_call sched_switch_call = {
-       .class                  = &sched_switch_class,
-       .event                  = {
-               .funcs                  = &sched_switch_funcs,
-       },
-       .print_fmt              = SCHED_PRINT_FMT,
-       .module                 = THIS_MODULE,
-       .flags                  = TRACE_EVENT_FL_TRACEPOINT,
-};
+/* Declare CREATE_CUSTOM_TRACE_EVENTS before including custom header */
+#define CREATE_CUSTOM_TRACE_EVENTS
 
-static struct trace_event_call sched_waking_call = {
-       .class                  = &sched_waking_class,
-       .event                  = {
-               .funcs                  = &sched_waking_funcs,
-       },
-       .print_fmt              = SCHED_WAKING_FMT,
-       .module                 = THIS_MODULE,
-       .flags                  = TRACE_EVENT_FL_TRACEPOINT,
-};
+#include "trace_custom_sched.h"
 
+/*
+ * As the trace events are not exported to modules, the use of
+ * for_each_kernel_tracepoint() is needed to find the trace event
+ * to attach to. The fct() function below, is a callback that
+ * will be called for every event.
+ *
+ * Helper functions are created by the TRACE_CUSTOM_EVENT() macro
+ * update the event. Those are of the form:
+ *
+ *    trace_custom_event_<event>_update()
+ *
+ * Where <event> is the event to attach.
+ */
 static void fct(struct tracepoint *tp, void *priv)
 {
-       if (tp->name && strcmp(tp->name, "sched_switch") == 0)
-               sched_switch_call.tp = tp;
-       else if (tp->name && strcmp(tp->name, "sched_waking") == 0)
-               sched_waking_call.tp = tp;
-}
-
-static int add_event(struct trace_event_call *call)
-{
-       int ret;
-
-       ret = register_trace_event(&call->event);
-       if (WARN_ON(!ret))
-               return -ENODEV;
-
-       ret = trace_add_event_call(call);
-       if (WARN_ON(ret))
-               unregister_trace_event(&call->event);
-
-       return ret;
+       trace_custom_event_sched_switch_update(tp);
+       trace_custom_event_sched_waking_update(tp);
 }
 
 static int __init trace_sched_init(void)
 {
-       int ret;
-
-       check_trace_callback_type_sched_switch(sched_switch_probe);
-       check_trace_callback_type_sched_waking(sched_waking_probe);
-
        for_each_kernel_tracepoint(fct, NULL);
-
-       ret = add_event(&sched_switch_call);
-       if (ret)
-               return ret;
-
-       ret = add_event(&sched_waking_call);
-       if (ret)
-               trace_remove_event_call(&sched_switch_call);
-
-       return ret;
+       return 0;
 }
 
 static void __exit trace_sched_exit(void)
 {
-       trace_set_clr_event(THIS_SYSTEM, "sched_switch", 0);
-       trace_set_clr_event(THIS_SYSTEM, "sched_waking", 0);
-
-       trace_remove_event_call(&sched_switch_call);
-       trace_remove_event_call(&sched_waking_call);
 }
 
 module_init(trace_sched_init);