ftrace: event profile hooks
[linux-2.6-block.git] / kernel / trace / trace_events_stage_3.h
index d6de06b9201a29e59cdb66b7af6c8bf58b45db5f..6b3261ca988c69676c6f890420507fa5d91ad76a 100644 (file)
@@ -5,23 +5,23 @@
  *
  * static void ftrace_event_<call>(proto)
  * {
- *     event_trace_printk(_RET_IP_, "<call>: " <fmt>);
+ *     event_trace_printk(_RET_IP_, "<call>: " <fmt>);
  * }
  *
  * static int ftrace_reg_event_<call>(void)
  * {
- *     int ret;
+ *     int ret;
  *
- *     ret = register_trace_<call>(ftrace_event_<call>);
- *     if (!ret)
- *             pr_info("event trace: Could not activate trace point "
- *                     "probe to  <call>");
- *     return ret;
+ *     ret = register_trace_<call>(ftrace_event_<call>);
+ *     if (!ret)
+ *             pr_info("event trace: Could not activate trace point "
+ *                     "probe to  <call>");
+ *     return ret;
  * }
  *
  * static void ftrace_unreg_event_<call>(void)
  * {
- *     unregister_trace_<call>(ftrace_event_<call>);
+ *     unregister_trace_<call>(ftrace_event_<call>);
  * }
  *
  * For those macros defined with TRACE_FORMAT:
@@ -29,9 +29,9 @@
  * static struct ftrace_event_call __used
  * __attribute__((__aligned__(4)))
  * __attribute__((section("_ftrace_events"))) event_<call> = {
- *     .name                   = "<call>",
- *     .regfunc                = ftrace_reg_event_<call>,
- *     .unregfunc              = ftrace_unreg_event_<call>,
+ *     .name                   = "<call>",
+ *     .regfunc                = ftrace_reg_event_<call>,
+ *     .unregfunc              = ftrace_unreg_event_<call>,
  * }
  *
  *
  *
  * static void ftrace_raw_event_<call>(proto)
  * {
- *     struct ring_buffer_event *event;
- *     struct ftrace_raw_<call> *entry; <-- defined in stage 1
- *     unsigned long irq_flags;
- *     int pc;
+ *     struct ring_buffer_event *event;
+ *     struct ftrace_raw_<call> *entry; <-- defined in stage 1
+ *     unsigned long irq_flags;
+ *     int pc;
  *
- *     local_save_flags(irq_flags);
- *     pc = preempt_count();
+ *     local_save_flags(irq_flags);
+ *     pc = preempt_count();
  *
- *     event = trace_current_buffer_lock_reserve(event_<call>.id,
- *                               sizeof(struct ftrace_raw_<call>),
- *                               irq_flags, pc);
- *     if (!event)
- *             return;
- *     entry   = ring_buffer_event_data(event);
+ *     event = trace_current_buffer_lock_reserve(event_<call>.id,
+ *                               sizeof(struct ftrace_raw_<call>),
+ *                               irq_flags, pc);
+ *     if (!event)
+ *             return;
+ *     entry   = ring_buffer_event_data(event);
  *
- *     <tstruct>;  <-- Here we assign the entries by the TRACE_FIELD.
+ *     <assign>;  <-- Here we assign the entries by the __field and
+ *                     __array macros.
  *
- *     trace_current_buffer_unlock_commit(event, irq_flags, pc);
+ *     trace_current_buffer_unlock_commit(event, irq_flags, pc);
  * }
  *
  * static int ftrace_raw_reg_event_<call>(void)
  * {
- *     int ret;
+ *     int ret;
  *
- *     ret = register_trace_<call>(ftrace_raw_event_<call>);
- *     if (!ret)
- *             pr_info("event trace: Could not activate trace point "
- *                     "probe to <call>");
- *     return ret;
+ *     ret = register_trace_<call>(ftrace_raw_event_<call>);
+ *     if (!ret)
+ *             pr_info("event trace: Could not activate trace point "
+ *                     "probe to <call>");
+ *     return ret;
  * }
  *
  * static void ftrace_unreg_event_<call>(void)
  * {
- *     unregister_trace_<call>(ftrace_raw_event_<call>);
+ *     unregister_trace_<call>(ftrace_raw_event_<call>);
  * }
  *
  * static struct trace_event ftrace_event_type_<call> = {
- *     .trace                  = ftrace_raw_output_<call>, <-- stage 2
+ *     .trace                  = ftrace_raw_output_<call>, <-- stage 2
  * };
  *
  * static int ftrace_raw_init_event_<call>(void)
  * {
- *     int id;
+ *     int id;
  *
- *     id = register_ftrace_event(&ftrace_event_type_<call>);
- *     if (!id)
- *             return -ENODEV;
- *     event_<call>.id = id;
- *     return 0;
+ *     id = register_ftrace_event(&ftrace_event_type_<call>);
+ *     if (!id)
+ *             return -ENODEV;
+ *     event_<call>.id = id;
+ *     return 0;
  * }
  *
  * static struct ftrace_event_call __used
  * __attribute__((__aligned__(4)))
  * __attribute__((section("_ftrace_events"))) event_<call> = {
- *     .name                   = "<call>",
- *     .regfunc                = ftrace_reg_event_<call>,
- *     .unregfunc              = ftrace_unreg_event_<call>,
- *     .raw_init               = ftrace_raw_init_event_<call>,
- *     .raw_reg                = ftrace_raw_reg_event_<call>,
- *     .raw_unreg              = ftrace_raw_unreg_event_<call>,
+ *     .name                   = "<call>",
+ *     .system                 = "<system>",
+ *     .raw_init               = ftrace_raw_init_event_<call>,
+ *     .regfunc                = ftrace_reg_event_<call>,
+ *     .unregfunc              = ftrace_unreg_event_<call>,
  *     .show_format            = ftrace_format_<call>,
  * }
  *
 #undef TP_FMT
 #define TP_FMT(fmt, args...)   fmt "\n", ##args
 
+#ifdef CONFIG_EVENT_PROFILE
+#define _TRACE_PROFILE(call, proto, args)                              \
+static void ftrace_profile_##call(proto)                               \
+{                                                                      \
+       extern void perf_tpcounter_event(int);                          \
+       perf_tpcounter_event(event_##call.id);                          \
+}                                                                      \
+                                                                       \
+static int ftrace_profile_enable_##call(struct ftrace_event_call *call) \
+{                                                                      \
+       int ret = 0;                                                    \
+                                                                       \
+       if (!atomic_inc_return(&call->profile_count))                   \
+               ret = register_trace_##call(ftrace_profile_##call);     \
+                                                                       \
+       return ret;                                                     \
+}                                                                      \
+                                                                       \
+static void ftrace_profile_disable_##call(struct ftrace_event_call *call) \
+{                                                                      \
+       if (atomic_add_negative(-1, &call->profile_count))              \
+               unregister_trace_##call(ftrace_profile_##call);         \
+}
+
+#define _TRACE_PROFILE_INIT(call)                                      \
+       .profile_count = ATOMIC_INIT(-1),                               \
+       .profile_enable = ftrace_profile_enable_##call,                 \
+       .profile_disable = ftrace_profile_disable_##call,
+
+#else
+#define _TRACE_PROFILE(call, proto, args)
+#define _TRACE_PROFILE_INIT(call)
+#endif
+
 #define _TRACE_FORMAT(call, proto, args, fmt)                          \
 static void ftrace_event_##call(proto)                                 \
 {                                                                      \
@@ -130,18 +164,33 @@ static void ftrace_unreg_event_##call(void)                               \
 {                                                                      \
        unregister_trace_##call(ftrace_event_##call);                   \
 }                                                                      \
-
+                                                                       \
+static struct ftrace_event_call event_##call;                          \
+                                                                       \
+static int ftrace_init_event_##call(void)                              \
+{                                                                      \
+       int id;                                                         \
+                                                                       \
+       id = register_ftrace_event(NULL);                               \
+       if (!id)                                                        \
+               return -ENODEV;                                         \
+       event_##call.id = id;                                           \
+       return 0;                                                       \
+}
 
 #undef TRACE_FORMAT
 #define TRACE_FORMAT(call, proto, args, fmt)                           \
 _TRACE_FORMAT(call, PARAMS(proto), PARAMS(args), PARAMS(fmt))          \
+_TRACE_PROFILE(call, PARAMS(proto), PARAMS(args))                      \
 static struct ftrace_event_call __used                                 \
 __attribute__((__aligned__(4)))                                                \
 __attribute__((section("_ftrace_events"))) event_##call = {            \
-       .name                   = #call,                                \
+       .name                   = #call,                                \
        .system                 = __stringify(TRACE_SYSTEM),            \
+       .raw_init               = ftrace_init_event_##call,             \
        .regfunc                = ftrace_reg_event_##call,              \
        .unregfunc              = ftrace_unreg_event_##call,            \
+       _TRACE_PROFILE_INIT(call)                                       \
 }
 
 #undef __entry
@@ -149,6 +198,7 @@ __attribute__((section("_ftrace_events"))) event_##call = {         \
 
 #undef TRACE_EVENT
 #define TRACE_EVENT(call, proto, args, tstruct, assign, print)         \
+_TRACE_PROFILE(call, PARAMS(proto), PARAMS(args))                      \
                                                                        \
 static struct ftrace_event_call event_##call;                          \
                                                                        \
@@ -163,7 +213,7 @@ static void ftrace_raw_event_##call(proto)                          \
        pc = preempt_count();                                           \
                                                                        \
        event = trace_current_buffer_lock_reserve(event_##call.id,      \
-                                 sizeof(struct ftrace_raw_##call),     \
+                                 sizeof(struct ftrace_raw_##call),     \
                                  irq_flags, pc);                       \
        if (!event)                                                     \
                return;                                                 \
@@ -208,10 +258,17 @@ static int ftrace_raw_init_event_##call(void)                             \
 static struct ftrace_event_call __used                                 \
 __attribute__((__aligned__(4)))                                                \
 __attribute__((section("_ftrace_events"))) event_##call = {            \
-       .name                   = #call,                                \
+       .name                   = #call,                                \
        .system                 = __stringify(TRACE_SYSTEM),            \
        .raw_init               = ftrace_raw_init_event_##call,         \
        .regfunc                = ftrace_raw_reg_event_##call,          \
        .unregfunc              = ftrace_raw_unreg_event_##call,        \
        .show_format            = ftrace_format_##call,                 \
+       _TRACE_PROFILE_INIT(call)                                       \
 }
+
+#include <trace/trace_event_types.h>
+
+#undef _TRACE_PROFILE
+#undef _TRACE_PROFILE_INIT
+