Commit 7e066fb8 authored by Mathieu Desnoyers's avatar Mathieu Desnoyers Committed by Ingo Molnar

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: default avatarMathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent 32f85742
...@@ -42,7 +42,7 @@ In include/trace/subsys.h : ...@@ -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) : ...@@ -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 ...@@ -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
......
...@@ -71,6 +71,7 @@ ...@@ -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) = .; \
......
...@@ -24,8 +24,12 @@ struct tracepoint { ...@@ -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 { ...@@ -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 { ...@@ -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, ...@@ -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)
{ } { }
......
...@@ -4,52 +4,52 @@ ...@@ -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));
......
...@@ -54,6 +54,10 @@ ...@@ -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)
......
...@@ -79,6 +79,8 @@ DEFINE_PER_CPU(unsigned long, process_counts) = 0; ...@@ -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;
......
...@@ -21,6 +21,9 @@ static DEFINE_SPINLOCK(kthread_create_lock); ...@@ -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. */
......
...@@ -118,6 +118,12 @@ ...@@ -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)
......
...@@ -41,6 +41,8 @@ ...@@ -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;
......
...@@ -4,10 +4,10 @@ ...@@ -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
...@@ -13,6 +13,9 @@ ...@@ -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)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment