tracepoint.h 4.7 KB
Newer Older
M
Mathieu Desnoyers 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
#ifndef _LINUX_TRACEPOINT_H
#define _LINUX_TRACEPOINT_H

/*
 * Kernel Tracepoint API.
 *
 * See Documentation/tracepoint.txt.
 *
 * (C) Copyright 2008 Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
 *
 * Heavily inspired from the Linux Kernel Markers.
 *
 * This file is released under the GPLv2.
 * See the file COPYING for more details.
 */

#include <linux/types.h>
#include <linux/rcupdate.h>

struct module;
struct tracepoint;

struct tracepoint {
	const char *name;		/* Tracepoint name */
	int state;			/* State. */
	void **funcs;
27 28 29 30 31 32
} __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.
					 */
M
Mathieu Desnoyers 已提交
33 34 35 36 37 38 39 40 41 42 43 44 45 46

#define TPPROTO(args...)	args
#define TPARGS(args...)		args

#ifdef CONFIG_TRACEPOINTS

/*
 * it_func[0] is never NULL because there is at least one element in the array
 * when the array itself is non NULL.
 */
#define __DO_TRACE(tp, proto, args)					\
	do {								\
		void **it_func;						\
									\
47
		rcu_read_lock_sched_notrace();				\
M
Mathieu Desnoyers 已提交
48 49 50 51 52 53
		it_func = rcu_dereference((tp)->funcs);			\
		if (it_func) {						\
			do {						\
				((void(*)(proto))(*it_func))(args);	\
			} while (*(++it_func));				\
		}							\
54
		rcu_read_unlock_sched_notrace();			\
M
Mathieu Desnoyers 已提交
55 56 57 58 59 60 61
	} while (0)

/*
 * Make sure the alignment of the structure in the __tracepoints section will
 * not add unwanted padding between the beginning of the section and the
 * structure. Force alignment to the same alignment as the section start.
 */
62 63
#define DECLARE_TRACE(name, proto, args)				\
	extern struct tracepoint __tracepoint_##name;			\
M
Mathieu Desnoyers 已提交
64 65 66 67 68 69 70 71
	static inline void trace_##name(proto)				\
	{								\
		if (unlikely(__tracepoint_##name.state))		\
			__DO_TRACE(&__tracepoint_##name,		\
				TPPROTO(proto), TPARGS(args));		\
	}								\
	static inline int register_trace_##name(void (*probe)(proto))	\
	{								\
72
		return tracepoint_probe_register(#name, (void *)probe);	\
M
Mathieu Desnoyers 已提交
73
	}								\
74
	static inline int unregister_trace_##name(void (*probe)(proto))	\
M
Mathieu Desnoyers 已提交
75
	{								\
76
		return tracepoint_probe_unregister(#name, (void *)probe);\
M
Mathieu Desnoyers 已提交
77 78
	}

79 80 81 82 83 84 85 86 87 88 89 90
#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)

M
Mathieu Desnoyers 已提交
91 92 93 94
extern void tracepoint_update_probe_range(struct tracepoint *begin,
	struct tracepoint *end);

#else /* !CONFIG_TRACEPOINTS */
95
#define DECLARE_TRACE(name, proto, args)				\
M
Mathieu Desnoyers 已提交
96 97 98 99 100 101 102 103
	static inline void _do_trace_##name(struct tracepoint *tp, proto) \
	{ }								\
	static inline void trace_##name(proto)				\
	{ }								\
	static inline int register_trace_##name(void (*probe)(proto))	\
	{								\
		return -ENOSYS;						\
	}								\
104 105 106 107
	static inline int unregister_trace_##name(void (*probe)(proto))	\
	{								\
		return -ENOSYS;						\
	}
M
Mathieu Desnoyers 已提交
108

109 110 111 112
#define DEFINE_TRACE(name)
#define EXPORT_TRACEPOINT_SYMBOL_GPL(name)
#define EXPORT_TRACEPOINT_SYMBOL(name)

M
Mathieu Desnoyers 已提交
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
static inline void tracepoint_update_probe_range(struct tracepoint *begin,
	struct tracepoint *end)
{ }
#endif /* CONFIG_TRACEPOINTS */

/*
 * Connect a probe to a tracepoint.
 * Internal API, should not be used directly.
 */
extern int tracepoint_probe_register(const char *name, void *probe);

/*
 * Disconnect a probe from a tracepoint.
 * Internal API, should not be used directly.
 */
extern int tracepoint_probe_unregister(const char *name, void *probe);

130 131 132 133
extern int tracepoint_probe_register_noupdate(const char *name, void *probe);
extern int tracepoint_probe_unregister_noupdate(const char *name, void *probe);
extern void tracepoint_probe_update_all(void);

M
Mathieu Desnoyers 已提交
134 135 136 137 138 139 140 141 142 143 144 145
struct tracepoint_iter {
	struct module *module;
	struct tracepoint *tracepoint;
};

extern void tracepoint_iter_start(struct tracepoint_iter *iter);
extern void tracepoint_iter_next(struct tracepoint_iter *iter);
extern void tracepoint_iter_stop(struct tracepoint_iter *iter);
extern void tracepoint_iter_reset(struct tracepoint_iter *iter);
extern int tracepoint_get_iter_range(struct tracepoint **tracepoint,
	struct tracepoint *begin, struct tracepoint *end);

146 147 148 149 150
/*
 * tracepoint_synchronize_unregister must be called between the last tracepoint
 * probe unregistration and the end of module exit to make sure there is no
 * caller executing a probe when it is freed.
 */
151 152 153 154
static inline void tracepoint_synchronize_unregister(void)
{
	synchronize_sched();
}
155

156 157 158
#define DEFINE_TRACE_FMT(name, proto, args, fmt)		\
	DECLARE_TRACE(name, TPPROTO(proto), TPARGS(args))

M
Mathieu Desnoyers 已提交
159
#endif