tracepoints: add DECLARE_TRACE() and DEFINE_TRACE()

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>
This commit is contained in:
Mathieu Desnoyers 2008-11-14 17:47:47 -05:00 committed by Ingo Molnar
parent 32f8574277
commit 7e066fb870
11 changed files with 66 additions and 25 deletions

View file

@ -42,7 +42,7 @@ In include/trace/subsys.h :
#include <linux/tracepoint.h> #include <linux/tracepoint.h>
DEFINE_TRACE(subsys_eventname, DECLARE_TRACE(subsys_eventname,
TPPTOTO(int firstarg, struct task_struct *p), TPPTOTO(int firstarg, struct task_struct *p),
TPARGS(firstarg, p)); TPARGS(firstarg, p));
@ -50,6 +50,8 @@ In subsys/file.c (where the tracing statement must be added) :
#include <trace/subsys.h> #include <trace/subsys.h>
DEFINE_TRACE(subsys_eventname);
void somefct(void) 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 considered as being the same whether they are in the core kernel image or in
modules. 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 * Probe / tracepoint example

View file

@ -71,6 +71,7 @@
VMLINUX_SYMBOL(__start___markers) = .; \ VMLINUX_SYMBOL(__start___markers) = .; \
*(__markers) \ *(__markers) \
VMLINUX_SYMBOL(__stop___markers) = .; \ VMLINUX_SYMBOL(__stop___markers) = .; \
. = ALIGN(32); \
VMLINUX_SYMBOL(__start___tracepoints) = .; \ VMLINUX_SYMBOL(__start___tracepoints) = .; \
*(__tracepoints) \ *(__tracepoints) \
VMLINUX_SYMBOL(__stop___tracepoints) = .; \ VMLINUX_SYMBOL(__stop___tracepoints) = .; \

View file

@ -24,8 +24,12 @@ struct tracepoint {
const char *name; /* Tracepoint name */ const char *name; /* Tracepoint name */
int state; /* State. */ int state; /* State. */
void **funcs; 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 TPPROTO(args...) args
#define TPARGS(args...) args #define TPARGS(args...) args
@ -55,15 +59,10 @@ struct tracepoint {
* not add unwanted padding between the beginning of the section and the * not add unwanted padding between the beginning of the section and the
* structure. Force alignment to the same alignment as the section start. * 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 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)) \ if (unlikely(__tracepoint_##name.state)) \
__DO_TRACE(&__tracepoint_##name, \ __DO_TRACE(&__tracepoint_##name, \
TPPROTO(proto), TPARGS(args)); \ TPPROTO(proto), TPARGS(args)); \
@ -77,11 +76,23 @@ struct tracepoint {
return tracepoint_probe_unregister(#name, (void *)probe);\ 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, extern void tracepoint_update_probe_range(struct tracepoint *begin,
struct tracepoint *end); struct tracepoint *end);
#else /* !CONFIG_TRACEPOINTS */ #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 _do_trace_##name(struct tracepoint *tp, proto) \
{ } \ { } \
static inline void trace_##name(proto) \ static inline void trace_##name(proto) \
@ -95,6 +106,10 @@ extern void tracepoint_update_probe_range(struct tracepoint *begin,
return -ENOSYS; \ 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, static inline void tracepoint_update_probe_range(struct tracepoint *begin,
struct tracepoint *end) struct tracepoint *end)
{ } { }

View file

@ -4,52 +4,52 @@
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/tracepoint.h> #include <linux/tracepoint.h>
DEFINE_TRACE(sched_kthread_stop, DECLARE_TRACE(sched_kthread_stop,
TPPROTO(struct task_struct *t), TPPROTO(struct task_struct *t),
TPARGS(t)); TPARGS(t));
DEFINE_TRACE(sched_kthread_stop_ret, DECLARE_TRACE(sched_kthread_stop_ret,
TPPROTO(int ret), TPPROTO(int ret),
TPARGS(ret)); TPARGS(ret));
DEFINE_TRACE(sched_wait_task, DECLARE_TRACE(sched_wait_task,
TPPROTO(struct rq *rq, struct task_struct *p), TPPROTO(struct rq *rq, struct task_struct *p),
TPARGS(rq, p)); TPARGS(rq, p));
DEFINE_TRACE(sched_wakeup, DECLARE_TRACE(sched_wakeup,
TPPROTO(struct rq *rq, struct task_struct *p), TPPROTO(struct rq *rq, struct task_struct *p),
TPARGS(rq, p)); TPARGS(rq, p));
DEFINE_TRACE(sched_wakeup_new, DECLARE_TRACE(sched_wakeup_new,
TPPROTO(struct rq *rq, struct task_struct *p), TPPROTO(struct rq *rq, struct task_struct *p),
TPARGS(rq, p)); TPARGS(rq, p));
DEFINE_TRACE(sched_switch, DECLARE_TRACE(sched_switch,
TPPROTO(struct rq *rq, struct task_struct *prev, TPPROTO(struct rq *rq, struct task_struct *prev,
struct task_struct *next), struct task_struct *next),
TPARGS(rq, prev, 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), TPPROTO(struct rq *rq, struct task_struct *p, int dest_cpu),
TPARGS(rq, p, dest_cpu)); TPARGS(rq, p, dest_cpu));
DEFINE_TRACE(sched_process_free, DECLARE_TRACE(sched_process_free,
TPPROTO(struct task_struct *p), TPPROTO(struct task_struct *p),
TPARGS(p)); TPARGS(p));
DEFINE_TRACE(sched_process_exit, DECLARE_TRACE(sched_process_exit,
TPPROTO(struct task_struct *p), TPPROTO(struct task_struct *p),
TPARGS(p)); TPARGS(p));
DEFINE_TRACE(sched_process_wait, DECLARE_TRACE(sched_process_wait,
TPPROTO(struct pid *pid), TPPROTO(struct pid *pid),
TPARGS(pid)); TPARGS(pid));
DEFINE_TRACE(sched_process_fork, DECLARE_TRACE(sched_process_fork,
TPPROTO(struct task_struct *parent, struct task_struct *child), TPPROTO(struct task_struct *parent, struct task_struct *child),
TPARGS(parent, child)); TPARGS(parent, child));
DEFINE_TRACE(sched_signal_send, DECLARE_TRACE(sched_signal_send,
TPPROTO(int sig, struct task_struct *p), TPPROTO(int sig, struct task_struct *p),
TPARGS(sig, p)); TPARGS(sig, p));

View file

@ -54,6 +54,10 @@
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <asm/mmu_context.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 void exit_mm(struct task_struct * tsk);
static inline int task_detached(struct task_struct *p) static inline int task_detached(struct task_struct *p)

View file

@ -79,6 +79,8 @@ DEFINE_PER_CPU(unsigned long, process_counts) = 0;
__cacheline_aligned DEFINE_RWLOCK(tasklist_lock); /* outer */ __cacheline_aligned DEFINE_RWLOCK(tasklist_lock); /* outer */
DEFINE_TRACE(sched_process_fork);
int nr_processes(void) int nr_processes(void)
{ {
int cpu; int cpu;

View file

@ -21,6 +21,9 @@ static DEFINE_SPINLOCK(kthread_create_lock);
static LIST_HEAD(kthread_create_list); static LIST_HEAD(kthread_create_list);
struct task_struct *kthreadd_task; struct task_struct *kthreadd_task;
DEFINE_TRACE(sched_kthread_stop);
DEFINE_TRACE(sched_kthread_stop_ret);
struct kthread_create_info struct kthread_create_info
{ {
/* Information passed to kthread() from kthreadd. */ /* Information passed to kthread() from kthreadd. */

View file

@ -118,6 +118,12 @@
*/ */
#define RUNTIME_INF ((u64)~0ULL) #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 #ifdef CONFIG_SMP
/* /*
* Divide a load by a sched group cpu_power : (load / sg->__cpu_power) * Divide a load by a sched group cpu_power : (load / sg->__cpu_power)

View file

@ -41,6 +41,8 @@
static struct kmem_cache *sigqueue_cachep; static struct kmem_cache *sigqueue_cachep;
DEFINE_TRACE(sched_signal_send);
static void __user *sig_handler(struct task_struct *t, int sig) static void __user *sig_handler(struct task_struct *t, int sig)
{ {
return t->sighand->action[sig - 1].sa.sa_handler; return t->sighand->action[sig - 1].sa.sa_handler;

View file

@ -4,10 +4,10 @@
#include <linux/proc_fs.h> /* for struct inode and struct file */ #include <linux/proc_fs.h> /* for struct inode and struct file */
#include <linux/tracepoint.h> #include <linux/tracepoint.h>
DEFINE_TRACE(subsys_event, DECLARE_TRACE(subsys_event,
TPPROTO(struct inode *inode, struct file *file), TPPROTO(struct inode *inode, struct file *file),
TPARGS(inode, file)); TPARGS(inode, file));
DEFINE_TRACE(subsys_eventb, DECLARE_TRACE(subsys_eventb,
TPPROTO(void), TPPROTO(void),
TPARGS()); TPARGS());
#endif #endif

View file

@ -13,6 +13,9 @@
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include "tp-samples-trace.h" #include "tp-samples-trace.h"
DEFINE_TRACE(subsys_event);
DEFINE_TRACE(subsys_eventb);
struct proc_dir_entry *pentry_example; struct proc_dir_entry *pentry_example;
static int my_open(struct inode *inode, struct file *file) static int my_open(struct inode *inode, struct file *file)