tracepoints: add DECLARE_TRACE() and DEFINE_TRACE()
Mathieu Desnoyers [Fri, 14 Nov 2008 22:47:47 +0000 (17:47 -0500)]
Impact: API *CHANGE*. Must update all tracepoint users.

Add DEFINE_TRACE() to tracepoints to let them declare the tracepoint
structure in a single spot for all the kernel. It helps reducing memory
consumption, especially when declaring a lot of tracepoints, e.g. for
kmalloc tracing.

*API CHANGE WARNING*: now, DECLARE_TRACE() must be used in headers for
tracepoint declarations rather than DEFINE_TRACE(). This is the sane way
to do it. The name previously used was misleading.

Updates scheduler instrumentation to follow this API change.

Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
Signed-off-by: Ingo Molnar <mingo@elte.hu>

Documentation/tracepoints.txt
include/asm-generic/vmlinux.lds.h
include/linux/tracepoint.h
include/trace/sched.h
kernel/exit.c
kernel/fork.c
kernel/kthread.c
kernel/sched.c
kernel/signal.c
samples/tracepoints/tp-samples-trace.h
samples/tracepoints/tracepoint-sample.c

index 5d354e1..e8ad47b 100644 (file)
@@ -42,7 +42,7 @@ In include/trace/subsys.h :
 
 #include <linux/tracepoint.h>
 
-DEFINE_TRACE(subsys_eventname,
+DECLARE_TRACE(subsys_eventname,
        TPPTOTO(int firstarg, struct task_struct *p),
        TPARGS(firstarg, p));
 
@@ -50,6 +50,8 @@ In subsys/file.c (where the tracing statement must be added) :
 
 #include <trace/subsys.h>
 
+DEFINE_TRACE(subsys_eventname);
+
 void somefct(void)
 {
        ...
@@ -86,6 +88,9 @@ to limit collisions. Tracepoint names are global to the kernel: they are
 considered as being the same whether they are in the core kernel image or in
 modules.
 
+If the tracepoint has to be used in kernel modules, an
+EXPORT_TRACEPOINT_SYMBOL_GPL() or EXPORT_TRACEPOINT_SYMBOL() can be used to
+export the defined tracepoints.
 
 * Probe / tracepoint example
 
index a5e4ed9..3b46ae4 100644 (file)
@@ -71,6 +71,7 @@
        VMLINUX_SYMBOL(__start___markers) = .;                          \
        *(__markers)                                                    \
        VMLINUX_SYMBOL(__stop___markers) = .;                           \
+       . = ALIGN(32);                                                  \
        VMLINUX_SYMBOL(__start___tracepoints) = .;                      \
        *(__tracepoints)                                                \
        VMLINUX_SYMBOL(__stop___tracepoints) = .;                       \
index 7e9b42a..7570054 100644 (file)
@@ -24,8 +24,12 @@ struct tracepoint {
        const char *name;               /* Tracepoint name */
        int state;                      /* State. */
        void **funcs;
-} __attribute__((aligned(8)));
-
+} __attribute__((aligned(32)));                /*
+                                        * Aligned on 32 bytes because it is
+                                        * globally visible and gcc happily
+                                        * align these on the structure size.
+                                        * Keep in sync with vmlinux.lds.h.
+                                        */
 
 #define TPPROTO(args...)       args
 #define TPARGS(args...)                args
@@ -55,15 +59,10 @@ struct tracepoint {
  * not add unwanted padding between the beginning of the section and the
  * structure. Force alignment to the same alignment as the section start.
  */
-#define DEFINE_TRACE(name, proto, args)                                        \
+#define DECLARE_TRACE(name, proto, args)                               \
+       extern struct tracepoint __tracepoint_##name;                   \
        static inline void trace_##name(proto)                          \
        {                                                               \
-               static const char __tpstrtab_##name[]                   \
-               __attribute__((section("__tracepoints_strings")))       \
-               = #name;                                                \
-               static struct tracepoint __tracepoint_##name            \
-               __attribute__((section("__tracepoints"), aligned(8))) = \
-               { __tpstrtab_##name, 0, NULL };                         \
                if (unlikely(__tracepoint_##name.state))                \
                        __DO_TRACE(&__tracepoint_##name,                \
                                TPPROTO(proto), TPARGS(args));          \
@@ -77,11 +76,23 @@ struct tracepoint {
                return tracepoint_probe_unregister(#name, (void *)probe);\
        }
 
+#define DEFINE_TRACE(name)                                             \
+       static const char __tpstrtab_##name[]                           \
+       __attribute__((section("__tracepoints_strings"))) = #name;      \
+       struct tracepoint __tracepoint_##name                           \
+       __attribute__((section("__tracepoints"), aligned(32))) =        \
+               { __tpstrtab_##name, 0, NULL }
+
+#define EXPORT_TRACEPOINT_SYMBOL_GPL(name)                             \
+       EXPORT_SYMBOL_GPL(__tracepoint_##name)
+#define EXPORT_TRACEPOINT_SYMBOL(name)                                 \
+       EXPORT_SYMBOL(__tracepoint_##name)
+
 extern void tracepoint_update_probe_range(struct tracepoint *begin,
        struct tracepoint *end);
 
 #else /* !CONFIG_TRACEPOINTS */
-#define DEFINE_TRACE(name, proto, args)                        \
+#define DECLARE_TRACE(name, proto, args)                               \
        static inline void _do_trace_##name(struct tracepoint *tp, proto) \
        { }                                                             \
        static inline void trace_##name(proto)                          \
@@ -95,6 +106,10 @@ extern void tracepoint_update_probe_range(struct tracepoint *begin,
                return -ENOSYS;                                         \
        }
 
+#define DEFINE_TRACE(name)
+#define EXPORT_TRACEPOINT_SYMBOL_GPL(name)
+#define EXPORT_TRACEPOINT_SYMBOL(name)
+
 static inline void tracepoint_update_probe_range(struct tracepoint *begin,
        struct tracepoint *end)
 { }
index ad47369..9b2854a 100644 (file)
@@ -4,52 +4,52 @@
 #include <linux/sched.h>
 #include <linux/tracepoint.h>
 
-DEFINE_TRACE(sched_kthread_stop,
+DECLARE_TRACE(sched_kthread_stop,
        TPPROTO(struct task_struct *t),
                TPARGS(t));
 
-DEFINE_TRACE(sched_kthread_stop_ret,
+DECLARE_TRACE(sched_kthread_stop_ret,
        TPPROTO(int ret),
                TPARGS(ret));
 
-DEFINE_TRACE(sched_wait_task,
+DECLARE_TRACE(sched_wait_task,
        TPPROTO(struct rq *rq, struct task_struct *p),
                TPARGS(rq, p));
 
-DEFINE_TRACE(sched_wakeup,
+DECLARE_TRACE(sched_wakeup,
        TPPROTO(struct rq *rq, struct task_struct *p),
                TPARGS(rq, p));
 
-DEFINE_TRACE(sched_wakeup_new,
+DECLARE_TRACE(sched_wakeup_new,
        TPPROTO(struct rq *rq, struct task_struct *p),
                TPARGS(rq, p));
 
-DEFINE_TRACE(sched_switch,
+DECLARE_TRACE(sched_switch,
        TPPROTO(struct rq *rq, struct task_struct *prev,
                struct task_struct *next),
                TPARGS(rq, prev, next));
 
-DEFINE_TRACE(sched_migrate_task,
+DECLARE_TRACE(sched_migrate_task,
        TPPROTO(struct rq *rq, struct task_struct *p, int dest_cpu),
                TPARGS(rq, p, dest_cpu));
 
-DEFINE_TRACE(sched_process_free,
+DECLARE_TRACE(sched_process_free,
        TPPROTO(struct task_struct *p),
                TPARGS(p));
 
-DEFINE_TRACE(sched_process_exit,
+DECLARE_TRACE(sched_process_exit,
        TPPROTO(struct task_struct *p),
                TPARGS(p));
 
-DEFINE_TRACE(sched_process_wait,
+DECLARE_TRACE(sched_process_wait,
        TPPROTO(struct pid *pid),
                TPARGS(pid));
 
-DEFINE_TRACE(sched_process_fork,
+DECLARE_TRACE(sched_process_fork,
        TPPROTO(struct task_struct *parent, struct task_struct *child),
                TPARGS(parent, child));
 
-DEFINE_TRACE(sched_signal_send,
+DECLARE_TRACE(sched_signal_send,
        TPPROTO(int sig, struct task_struct *p),
                TPARGS(sig, p));
 
index ae2b92b..f995d24 100644 (file)
 #include <asm/pgtable.h>
 #include <asm/mmu_context.h>
 
+DEFINE_TRACE(sched_process_free);
+DEFINE_TRACE(sched_process_exit);
+DEFINE_TRACE(sched_process_wait);
+
 static void exit_mm(struct task_struct * tsk);
 
 static inline int task_detached(struct task_struct *p)
index f608356..0837d0d 100644 (file)
@@ -79,6 +79,8 @@ DEFINE_PER_CPU(unsigned long, process_counts) = 0;
 
 __cacheline_aligned DEFINE_RWLOCK(tasklist_lock);  /* outer */
 
+DEFINE_TRACE(sched_process_fork);
+
 int nr_processes(void)
 {
        int cpu;
index 8e7a7ce..4fbc456 100644 (file)
@@ -21,6 +21,9 @@ static DEFINE_SPINLOCK(kthread_create_lock);
 static LIST_HEAD(kthread_create_list);
 struct task_struct *kthreadd_task;
 
+DEFINE_TRACE(sched_kthread_stop);
+DEFINE_TRACE(sched_kthread_stop_ret);
+
 struct kthread_create_info
 {
        /* Information passed to kthread() from kthreadd. */
index 50a21f9..327f91c 100644 (file)
  */
 #define RUNTIME_INF    ((u64)~0ULL)
 
+DEFINE_TRACE(sched_wait_task);
+DEFINE_TRACE(sched_wakeup);
+DEFINE_TRACE(sched_wakeup_new);
+DEFINE_TRACE(sched_switch);
+DEFINE_TRACE(sched_migrate_task);
+
 #ifdef CONFIG_SMP
 /*
  * Divide a load by a sched group cpu_power : (load / sg->__cpu_power)
index 4530fc6..e9afe63 100644 (file)
@@ -41,6 +41,8 @@
 
 static struct kmem_cache *sigqueue_cachep;
 
+DEFINE_TRACE(sched_signal_send);
+
 static void __user *sig_handler(struct task_struct *t, int sig)
 {
        return t->sighand->action[sig - 1].sa.sa_handler;
index 0216b55..01724e0 100644 (file)
@@ -4,10 +4,10 @@
 #include <linux/proc_fs.h>     /* for struct inode and struct file */
 #include <linux/tracepoint.h>
 
-DEFINE_TRACE(subsys_event,
+DECLARE_TRACE(subsys_event,
        TPPROTO(struct inode *inode, struct file *file),
        TPARGS(inode, file));
-DEFINE_TRACE(subsys_eventb,
+DECLARE_TRACE(subsys_eventb,
        TPPROTO(void),
        TPARGS());
 #endif
index 4ae4b7f..00d1697 100644 (file)
@@ -13,6 +13,9 @@
 #include <linux/proc_fs.h>
 #include "tp-samples-trace.h"
 
+DEFINE_TRACE(subsys_event);
+DEFINE_TRACE(subsys_eventb);
+
 struct proc_dir_entry *pentry_example;
 
 static int my_open(struct inode *inode, struct file *file)