| #ifndef _LINUX_TRACEPOINT_H |
| #define _LINUX_TRACEPOINT_H |
| |
| /* |
| * Kernel Tracepoint API. |
| * |
| * See Documentation/trace/tracepoints.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/errno.h> |
| #include <linux/types.h> |
| #include <linux/rcupdate.h> |
| #include <linux/static_key.h> |
| |
| struct module; |
| struct tracepoint; |
| |
| struct tracepoint_func { |
| void *func; |
| void *data; |
| }; |
| |
| struct tracepoint { |
| const char *name; |
| struct static_key key; |
| void (*regfunc)(void); |
| void (*unregfunc)(void); |
| struct tracepoint_func __rcu *funcs; |
| }; |
| |
| extern int tracepoint_probe_register(const char *name, void *probe, void *data); |
| |
| extern int |
| tracepoint_probe_unregister(const char *name, void *probe, void *data); |
| |
| extern int tracepoint_probe_register_noupdate(const char *name, void *probe, |
| void *data); |
| extern int tracepoint_probe_unregister_noupdate(const char *name, void *probe, |
| void *data); |
| extern void tracepoint_probe_update_all(void); |
| |
| #ifdef CONFIG_MODULES |
| struct tp_module { |
| struct list_head list; |
| unsigned int num_tracepoints; |
| struct tracepoint * const *tracepoints_ptrs; |
| }; |
| #endif |
| |
| struct tracepoint_iter { |
| #ifdef CONFIG_MODULES |
| struct tp_module *module; |
| #endif |
| struct tracepoint * const *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); |
| |
| static inline void tracepoint_synchronize_unregister(void) |
| { |
| synchronize_sched(); |
| } |
| |
| #define PARAMS(args...) args |
| |
| #endif |
| |
| |
| #ifndef DECLARE_TRACE |
| |
| #define TP_PROTO(args...) args |
| #define TP_ARGS(args...) args |
| #define TP_CONDITION(args...) args |
| |
| #ifdef CONFIG_TRACEPOINTS |
| |
| #define __DO_TRACE(tp, proto, args, cond, prercu, postrcu) \ |
| do { \ |
| struct tracepoint_func *it_func_ptr; \ |
| void *it_func; \ |
| void *__data; \ |
| \ |
| if (!(cond)) \ |
| return; \ |
| prercu; \ |
| rcu_read_lock_sched_notrace(); \ |
| it_func_ptr = rcu_dereference_sched((tp)->funcs); \ |
| if (it_func_ptr) { \ |
| do { \ |
| it_func = (it_func_ptr)->func; \ |
| __data = (it_func_ptr)->data; \ |
| ((void(*)(proto))(it_func))(args); \ |
| } while ((++it_func_ptr)->func); \ |
| } \ |
| rcu_read_unlock_sched_notrace(); \ |
| postrcu; \ |
| } while (0) |
| |
| #define __DECLARE_TRACE(name, proto, args, cond, data_proto, data_args) \ |
| extern struct tracepoint __tracepoint_##name; \ |
| static inline void trace_##name(proto) \ |
| { \ |
| if (static_key_false(&__tracepoint_##name.key)) \ |
| __DO_TRACE(&__tracepoint_##name, \ |
| TP_PROTO(data_proto), \ |
| TP_ARGS(data_args), \ |
| TP_CONDITION(cond),,); \ |
| } \ |
| static inline void trace_##name##_rcuidle(proto) \ |
| { \ |
| if (static_branch(&__tracepoint_##name.key)) \ |
| __DO_TRACE(&__tracepoint_##name, \ |
| TP_PROTO(data_proto), \ |
| TP_ARGS(data_args), \ |
| TP_CONDITION(cond), \ |
| rcu_idle_exit(), \ |
| rcu_idle_enter()); \ |
| } \ |
| static inline int \ |
| register_trace_##name(void (*probe)(data_proto), void *data) \ |
| { \ |
| return tracepoint_probe_register(#name, (void *)probe, \ |
| data); \ |
| } \ |
| static inline int \ |
| unregister_trace_##name(void (*probe)(data_proto), void *data) \ |
| { \ |
| return tracepoint_probe_unregister(#name, (void *)probe, \ |
| data); \ |
| } \ |
| static inline void \ |
| check_trace_callback_type_##name(void (*cb)(data_proto)) \ |
| { \ |
| } |
| |
| #define DEFINE_TRACE_FN(name, reg, unreg) \ |
| static const char __tpstrtab_##name[] \ |
| __attribute__((section("__tracepoints_strings"))) = #name; \ |
| struct tracepoint __tracepoint_##name \ |
| __attribute__((section("__tracepoints"))) = \ |
| { __tpstrtab_##name, STATIC_KEY_INIT_FALSE, reg, unreg, NULL };\ |
| static struct tracepoint * const __tracepoint_ptr_##name __used \ |
| __attribute__((section("__tracepoints_ptrs"))) = \ |
| &__tracepoint_##name; |
| |
| #define DEFINE_TRACE(name) \ |
| DEFINE_TRACE_FN(name, NULL, NULL); |
| |
| #define EXPORT_TRACEPOINT_SYMBOL_GPL(name) \ |
| EXPORT_SYMBOL_GPL(__tracepoint_##name) |
| #define EXPORT_TRACEPOINT_SYMBOL(name) \ |
| EXPORT_SYMBOL(__tracepoint_##name) |
| |
| #else |
| #define __DECLARE_TRACE(name, proto, args, cond, data_proto, data_args) \ |
| static inline void trace_##name(proto) \ |
| { } \ |
| static inline void trace_##name##_rcuidle(proto) \ |
| { } \ |
| static inline int \ |
| register_trace_##name(void (*probe)(data_proto), \ |
| void *data) \ |
| { \ |
| return -ENOSYS; \ |
| } \ |
| static inline int \ |
| unregister_trace_##name(void (*probe)(data_proto), \ |
| void *data) \ |
| { \ |
| return -ENOSYS; \ |
| } \ |
| static inline void check_trace_callback_type_##name(void (*cb)(data_proto)) \ |
| { \ |
| } |
| |
| #define DEFINE_TRACE_FN(name, reg, unreg) |
| #define DEFINE_TRACE(name) |
| #define EXPORT_TRACEPOINT_SYMBOL_GPL(name) |
| #define EXPORT_TRACEPOINT_SYMBOL(name) |
| |
| #endif |
| |
| #define DECLARE_TRACE_NOARGS(name) \ |
| __DECLARE_TRACE(name, void, , 1, void *__data, __data) |
| |
| #define DECLARE_TRACE(name, proto, args) \ |
| __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args), 1, \ |
| PARAMS(void *__data, proto), \ |
| PARAMS(__data, args)) |
| |
| #define DECLARE_TRACE_CONDITION(name, proto, args, cond) \ |
| __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args), PARAMS(cond), \ |
| PARAMS(void *__data, proto), \ |
| PARAMS(__data, args)) |
| |
| #define TRACE_EVENT_FLAGS(event, flag) |
| |
| #endif |
| |
| #ifndef TRACE_EVENT |
| |
| #define DECLARE_EVENT_CLASS(name, proto, args, tstruct, assign, print) |
| #define DEFINE_EVENT(template, name, proto, args) \ |
| DECLARE_TRACE(name, PARAMS(proto), PARAMS(args)) |
| #define DEFINE_EVENT_PRINT(template, name, proto, args, print) \ |
| DECLARE_TRACE(name, PARAMS(proto), PARAMS(args)) |
| #define DEFINE_EVENT_CONDITION(template, name, proto, \ |
| args, cond) \ |
| DECLARE_TRACE_CONDITION(name, PARAMS(proto), \ |
| PARAMS(args), PARAMS(cond)) |
| |
| #define TRACE_EVENT(name, proto, args, struct, assign, print) \ |
| DECLARE_TRACE(name, PARAMS(proto), PARAMS(args)) |
| #define TRACE_EVENT_FN(name, proto, args, struct, \ |
| assign, print, reg, unreg) \ |
| DECLARE_TRACE(name, PARAMS(proto), PARAMS(args)) |
| #define TRACE_EVENT_CONDITION(name, proto, args, cond, \ |
| struct, assign, print) \ |
| DECLARE_TRACE_CONDITION(name, PARAMS(proto), \ |
| PARAMS(args), PARAMS(cond)) |
| |
| #define TRACE_EVENT_FLAGS(event, flag) |
| |
| #endif |