Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f80836c8 authored by Ingo Molnar's avatar Ingo Molnar
Browse files

Merge branch 'tip/tracing/core-7' of...

Merge branch 'tip/tracing/core-7' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-2.6-trace into perf/core
parents 598357eb ff5f149b
Loading
Loading
Loading
Loading
+65 −17
Original line number Original line Diff line number Diff line
@@ -70,18 +70,25 @@ struct trace_iterator {
};
};




struct trace_event;

typedef enum print_line_t (*trace_print_func)(struct trace_iterator *iter,
typedef enum print_line_t (*trace_print_func)(struct trace_iterator *iter,
					      int flags);
				      int flags, struct trace_event *event);
struct trace_event {

	struct hlist_node	node;
struct trace_event_functions {
	struct list_head	list;
	int			type;
	trace_print_func	trace;
	trace_print_func	trace;
	trace_print_func	raw;
	trace_print_func	raw;
	trace_print_func	hex;
	trace_print_func	hex;
	trace_print_func	binary;
	trace_print_func	binary;
};
};


struct trace_event {
	struct hlist_node		node;
	struct list_head		list;
	int				type;
	struct trace_event_functions	*funcs;
};

extern int register_ftrace_event(struct trace_event *event);
extern int register_ftrace_event(struct trace_event *event);
extern int unregister_ftrace_event(struct trace_event *event);
extern int unregister_ftrace_event(struct trace_event *event);


@@ -113,29 +120,70 @@ void tracing_record_cmdline(struct task_struct *tsk);


struct event_filter;
struct event_filter;


enum trace_reg {
	TRACE_REG_REGISTER,
	TRACE_REG_UNREGISTER,
	TRACE_REG_PERF_REGISTER,
	TRACE_REG_PERF_UNREGISTER,
};

struct ftrace_event_call;

struct ftrace_event_class {
	char			*system;
	void			*probe;
#ifdef CONFIG_PERF_EVENTS
	void			*perf_probe;
#endif
	int			(*reg)(struct ftrace_event_call *event,
				       enum trace_reg type);
	int			(*define_fields)(struct ftrace_event_call *);
	struct list_head	*(*get_fields)(struct ftrace_event_call *);
	struct list_head	fields;
	int			(*raw_init)(struct ftrace_event_call *);
};

enum {
	TRACE_EVENT_FL_ENABLED_BIT,
	TRACE_EVENT_FL_FILTERED_BIT,
};

enum {
	TRACE_EVENT_FL_ENABLED	= (1 << TRACE_EVENT_FL_ENABLED_BIT),
	TRACE_EVENT_FL_FILTERED	= (1 << TRACE_EVENT_FL_FILTERED_BIT),
};

struct ftrace_event_call {
struct ftrace_event_call {
	struct list_head	list;
	struct list_head	list;
	struct ftrace_event_class *class;
	char			*name;
	char			*name;
	char			*system;
	struct dentry		*dir;
	struct dentry		*dir;
	struct trace_event	*event;
	struct trace_event	event;
	int			enabled;
	int			(*regfunc)(struct ftrace_event_call *);
	void			(*unregfunc)(struct ftrace_event_call *);
	int			id;
	const char		*print_fmt;
	const char		*print_fmt;
	int			(*raw_init)(struct ftrace_event_call *);
	int			(*define_fields)(struct ftrace_event_call *);
	struct list_head	fields;
	int			filter_active;
	struct event_filter	*filter;
	struct event_filter	*filter;
	void			*mod;
	void			*mod;
	void			*data;
	void			*data;


	/*
	 * 32 bit flags:
	 *   bit 1:		enabled
	 *   bit 2:		filter_active
	 *
	 * Changes to flags must hold the event_mutex.
	 *
	 * Note: Reads of flags do not hold the event_mutex since
	 * they occur in critical sections. But the way flags
	 * is currently used, these changes do no affect the code
	 * except that when a change is made, it may have a slight
	 * delay in propagating the changes to other CPUs due to
	 * caching and such.
	 */
	unsigned int		flags;

#ifdef CONFIG_PERF_EVENTS
	int			perf_refcount;
	int			perf_refcount;
	struct hlist_head	*perf_events;
	struct hlist_head	*perf_events;
	int			(*perf_event_enable)(struct ftrace_event_call *);
#endif
	void			(*perf_event_disable)(struct ftrace_event_call *);
};
};


#define PERF_MAX_TRACE_SIZE	2048
#define PERF_MAX_TRACE_SIZE	2048
+17 −40
Original line number Original line Diff line number Diff line
@@ -103,22 +103,6 @@ struct perf_event_attr;
#define __SC_TEST5(t5, a5, ...)	__SC_TEST(t5); __SC_TEST4(__VA_ARGS__)
#define __SC_TEST5(t5, a5, ...)	__SC_TEST(t5); __SC_TEST4(__VA_ARGS__)
#define __SC_TEST6(t6, a6, ...)	__SC_TEST(t6); __SC_TEST5(__VA_ARGS__)
#define __SC_TEST6(t6, a6, ...)	__SC_TEST(t6); __SC_TEST5(__VA_ARGS__)


#ifdef CONFIG_PERF_EVENTS

#define TRACE_SYS_ENTER_PERF_INIT(sname)				       \
	.perf_event_enable = perf_sysenter_enable,			       \
	.perf_event_disable = perf_sysenter_disable,

#define TRACE_SYS_EXIT_PERF_INIT(sname)					       \
	.perf_event_enable = perf_sysexit_enable,			       \
	.perf_event_disable = perf_sysexit_disable,
#else
#define TRACE_SYS_ENTER_PERF(sname)
#define TRACE_SYS_ENTER_PERF_INIT(sname)
#define TRACE_SYS_EXIT_PERF(sname)
#define TRACE_SYS_EXIT_PERF_INIT(sname)
#endif /* CONFIG_PERF_EVENTS */

#ifdef CONFIG_FTRACE_SYSCALLS
#ifdef CONFIG_FTRACE_SYSCALLS
#define __SC_STR_ADECL1(t, a)		#a
#define __SC_STR_ADECL1(t, a)		#a
#define __SC_STR_ADECL2(t, a, ...)	#a, __SC_STR_ADECL1(__VA_ARGS__)
#define __SC_STR_ADECL2(t, a, ...)	#a, __SC_STR_ADECL1(__VA_ARGS__)
@@ -134,54 +118,43 @@ struct perf_event_attr;
#define __SC_STR_TDECL5(t, a, ...)	#t, __SC_STR_TDECL4(__VA_ARGS__)
#define __SC_STR_TDECL5(t, a, ...)	#t, __SC_STR_TDECL4(__VA_ARGS__)
#define __SC_STR_TDECL6(t, a, ...)	#t, __SC_STR_TDECL5(__VA_ARGS__)
#define __SC_STR_TDECL6(t, a, ...)	#t, __SC_STR_TDECL5(__VA_ARGS__)


extern struct ftrace_event_class event_class_syscall_enter;
extern struct ftrace_event_class event_class_syscall_exit;
extern struct trace_event_functions enter_syscall_print_funcs;
extern struct trace_event_functions exit_syscall_print_funcs;

#define SYSCALL_TRACE_ENTER_EVENT(sname)				\
#define SYSCALL_TRACE_ENTER_EVENT(sname)				\
	static const struct syscall_metadata __syscall_meta_##sname;	\
	static struct syscall_metadata __syscall_meta_##sname;		\
	static struct ftrace_event_call					\
	static struct ftrace_event_call					\
	__attribute__((__aligned__(4))) event_enter_##sname;		\
	__attribute__((__aligned__(4))) event_enter_##sname;		\
	static struct trace_event enter_syscall_print_##sname = {	\
		.trace                  = print_syscall_enter,		\
	};								\
	static struct ftrace_event_call __used				\
	static struct ftrace_event_call __used				\
	  __attribute__((__aligned__(4)))				\
	  __attribute__((__aligned__(4)))				\
	  __attribute__((section("_ftrace_events")))			\
	  __attribute__((section("_ftrace_events")))			\
	  event_enter_##sname = {					\
	  event_enter_##sname = {					\
		.name                   = "sys_enter"#sname,		\
		.name                   = "sys_enter"#sname,		\
		.system                 = "syscalls",			\
		.class			= &event_class_syscall_enter,	\
		.event                  = &enter_syscall_print_##sname,	\
		.event.funcs            = &enter_syscall_print_funcs,	\
		.raw_init		= init_syscall_trace,		\
		.define_fields		= syscall_enter_define_fields,	\
		.regfunc		= reg_event_syscall_enter,	\
		.unregfunc		= unreg_event_syscall_enter,	\
		.data			= (void *)&__syscall_meta_##sname,\
		.data			= (void *)&__syscall_meta_##sname,\
		TRACE_SYS_ENTER_PERF_INIT(sname)			\
	}
	}


#define SYSCALL_TRACE_EXIT_EVENT(sname)					\
#define SYSCALL_TRACE_EXIT_EVENT(sname)					\
	static const struct syscall_metadata __syscall_meta_##sname;	\
	static struct syscall_metadata __syscall_meta_##sname;		\
	static struct ftrace_event_call					\
	static struct ftrace_event_call					\
	__attribute__((__aligned__(4))) event_exit_##sname;		\
	__attribute__((__aligned__(4))) event_exit_##sname;		\
	static struct trace_event exit_syscall_print_##sname = {	\
		.trace                  = print_syscall_exit,		\
	};								\
	static struct ftrace_event_call __used				\
	static struct ftrace_event_call __used				\
	  __attribute__((__aligned__(4)))				\
	  __attribute__((__aligned__(4)))				\
	  __attribute__((section("_ftrace_events")))			\
	  __attribute__((section("_ftrace_events")))			\
	  event_exit_##sname = {					\
	  event_exit_##sname = {					\
		.name                   = "sys_exit"#sname,		\
		.name                   = "sys_exit"#sname,		\
		.system                 = "syscalls",			\
		.class			= &event_class_syscall_exit,	\
		.event                  = &exit_syscall_print_##sname,	\
		.event.funcs		= &exit_syscall_print_funcs,	\
		.raw_init		= init_syscall_trace,		\
		.define_fields		= syscall_exit_define_fields,	\
		.regfunc		= reg_event_syscall_exit,	\
		.unregfunc		= unreg_event_syscall_exit,	\
		.data			= (void *)&__syscall_meta_##sname,\
		.data			= (void *)&__syscall_meta_##sname,\
		TRACE_SYS_EXIT_PERF_INIT(sname)			\
	}
	}


#define SYSCALL_METADATA(sname, nb)				\
#define SYSCALL_METADATA(sname, nb)				\
	SYSCALL_TRACE_ENTER_EVENT(sname);			\
	SYSCALL_TRACE_ENTER_EVENT(sname);			\
	SYSCALL_TRACE_EXIT_EVENT(sname);			\
	SYSCALL_TRACE_EXIT_EVENT(sname);			\
	static const struct syscall_metadata __used		\
	static struct syscall_metadata __used			\
	  __attribute__((__aligned__(4)))			\
	  __attribute__((__aligned__(4)))			\
	  __attribute__((section("__syscalls_metadata")))	\
	  __attribute__((section("__syscalls_metadata")))	\
	  __syscall_meta_##sname = {				\
	  __syscall_meta_##sname = {				\
@@ -191,12 +164,14 @@ struct perf_event_attr;
		.args		= args_##sname,			\
		.args		= args_##sname,			\
		.enter_event	= &event_enter_##sname,		\
		.enter_event	= &event_enter_##sname,		\
		.exit_event	= &event_exit_##sname,		\
		.exit_event	= &event_exit_##sname,		\
		.enter_fields	= LIST_HEAD_INIT(__syscall_meta_##sname.enter_fields), \
		.exit_fields	= LIST_HEAD_INIT(__syscall_meta_##sname.exit_fields), \
	};
	};


#define SYSCALL_DEFINE0(sname)					\
#define SYSCALL_DEFINE0(sname)					\
	SYSCALL_TRACE_ENTER_EVENT(_##sname);			\
	SYSCALL_TRACE_ENTER_EVENT(_##sname);			\
	SYSCALL_TRACE_EXIT_EVENT(_##sname);			\
	SYSCALL_TRACE_EXIT_EVENT(_##sname);			\
	static const struct syscall_metadata __used		\
	static struct syscall_metadata __used			\
	  __attribute__((__aligned__(4)))			\
	  __attribute__((__aligned__(4)))			\
	  __attribute__((section("__syscalls_metadata")))	\
	  __attribute__((section("__syscalls_metadata")))	\
	  __syscall_meta__##sname = {				\
	  __syscall_meta__##sname = {				\
@@ -204,6 +179,8 @@ struct perf_event_attr;
		.nb_args 	= 0,				\
		.nb_args 	= 0,				\
		.enter_event	= &event_enter__##sname,	\
		.enter_event	= &event_enter__##sname,	\
		.exit_event	= &event_exit__##sname,		\
		.exit_event	= &event_exit__##sname,		\
		.enter_fields	= LIST_HEAD_INIT(__syscall_meta__##sname.enter_fields), \
		.exit_fields	= LIST_HEAD_INIT(__syscall_meta__##sname.exit_fields), \
	};							\
	};							\
	asmlinkage long sys_##sname(void)
	asmlinkage long sys_##sname(void)
#else
#else
+76 −22
Original line number Original line Diff line number Diff line
@@ -20,12 +20,17 @@
struct module;
struct module;
struct tracepoint;
struct tracepoint;


struct tracepoint_func {
	void *func;
	void *data;
};

struct tracepoint {
struct tracepoint {
	const char *name;		/* Tracepoint name */
	const char *name;		/* Tracepoint name */
	int state;			/* State. */
	int state;			/* State. */
	void (*regfunc)(void);
	void (*regfunc)(void);
	void (*unregfunc)(void);
	void (*unregfunc)(void);
	void **funcs;
	struct tracepoint_func *funcs;
} __attribute__((aligned(32)));		/*
} __attribute__((aligned(32)));		/*
					 * Aligned on 32 bytes because it is
					 * Aligned on 32 bytes because it is
					 * globally visible and gcc happily
					 * globally visible and gcc happily
@@ -37,16 +42,19 @@ struct tracepoint {
 * Connect a probe to a tracepoint.
 * Connect a probe to a tracepoint.
 * Internal API, should not be used directly.
 * Internal API, should not be used directly.
 */
 */
extern int tracepoint_probe_register(const char *name, void *probe);
extern int tracepoint_probe_register(const char *name, void *probe, void *data);


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


extern int tracepoint_probe_register_noupdate(const char *name, void *probe);
extern int tracepoint_probe_register_noupdate(const char *name, void *probe,
extern int tracepoint_probe_unregister_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);
extern void tracepoint_probe_update_all(void);


struct tracepoint_iter {
struct tracepoint_iter {
@@ -102,17 +110,27 @@ static inline void tracepoint_update_probe_range(struct tracepoint *begin,
/*
/*
 * it_func[0] is never NULL because there is at least one element in the array
 * it_func[0] is never NULL because there is at least one element in the array
 * when the array itself is non NULL.
 * when the array itself is non NULL.
 *
 * Note, the proto and args passed in includes "__data" as the first parameter.
 * The reason for this is to handle the "void" prototype. If a tracepoint
 * has a "void" prototype, then it is invalid to declare a function
 * as "(void *, void)". The DECLARE_TRACE_NOARGS() will pass in just
 * "void *data", where as the DECLARE_TRACE() will pass in "void *data, proto".
 */
 */
#define __DO_TRACE(tp, proto, args)					\
#define __DO_TRACE(tp, proto, args)					\
	do {								\
	do {								\
		void **it_func;						\
		struct tracepoint_func *it_func_ptr;			\
		void *it_func;						\
		void *__data;						\
									\
									\
		rcu_read_lock_sched_notrace();				\
		rcu_read_lock_sched_notrace();				\
		it_func = rcu_dereference_sched((tp)->funcs);		\
		it_func_ptr = rcu_dereference_sched((tp)->funcs);	\
		if (it_func) {						\
		if (it_func_ptr) {					\
			do {						\
			do {						\
				((void(*)(proto))(*it_func))(args);	\
				it_func = (it_func_ptr)->func;		\
			} while (*(++it_func));				\
				__data = (it_func_ptr)->data;		\
				((void(*)(proto))(it_func))(args);	\
			} while ((++it_func_ptr)->func);		\
		}							\
		}							\
		rcu_read_unlock_sched_notrace();			\
		rcu_read_unlock_sched_notrace();			\
	} while (0)
	} while (0)
@@ -122,24 +140,32 @@ static inline void tracepoint_update_probe_range(struct tracepoint *begin,
 * 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 DECLARE_TRACE(name, proto, args)				\
#define __DECLARE_TRACE(name, proto, args, data_proto, data_args)	\
	extern struct tracepoint __tracepoint_##name;			\
	extern struct tracepoint __tracepoint_##name;			\
	static inline void trace_##name(proto)				\
	static inline void trace_##name(proto)				\
	{								\
	{								\
		if (unlikely(__tracepoint_##name.state))		\
		if (unlikely(__tracepoint_##name.state))		\
			__DO_TRACE(&__tracepoint_##name,		\
			__DO_TRACE(&__tracepoint_##name,		\
				TP_PROTO(proto), TP_ARGS(args));	\
				TP_PROTO(data_proto),			\
				TP_ARGS(data_args));			\
	}								\
	static inline int						\
	register_trace_##name(void (*probe)(data_proto), void *data)	\
	{								\
		return tracepoint_probe_register(#name, (void *)probe,	\
						 data);			\
	}								\
	}								\
	static inline int register_trace_##name(void (*probe)(proto))	\
	static inline int						\
	unregister_trace_##name(void (*probe)(data_proto), void *data)	\
	{								\
	{								\
		return tracepoint_probe_register(#name, (void *)probe);	\
		return tracepoint_probe_unregister(#name, (void *)probe, \
						   data);		\
	}								\
	}								\
	static inline int unregister_trace_##name(void (*probe)(proto))	\
	static inline void						\
	check_trace_callback_type_##name(void (*cb)(data_proto))	\
	{								\
	{								\
		return tracepoint_probe_unregister(#name, (void *)probe);\
	}
	}



#define DEFINE_TRACE_FN(name, reg, unreg)				\
#define DEFINE_TRACE_FN(name, reg, unreg)				\
	static const char __tpstrtab_##name[]				\
	static const char __tpstrtab_##name[]				\
	__attribute__((section("__tracepoints_strings"))) = #name;	\
	__attribute__((section("__tracepoints_strings"))) = #name;	\
@@ -156,18 +182,23 @@ static inline void tracepoint_update_probe_range(struct tracepoint *begin,
	EXPORT_SYMBOL(__tracepoint_##name)
	EXPORT_SYMBOL(__tracepoint_##name)


#else /* !CONFIG_TRACEPOINTS */
#else /* !CONFIG_TRACEPOINTS */
#define DECLARE_TRACE(name, proto, args)				\
#define __DECLARE_TRACE(name, proto, args, data_proto, data_args)	\
	static inline void _do_trace_##name(struct tracepoint *tp, proto) \
	{ }								\
	static inline void trace_##name(proto)				\
	static inline void trace_##name(proto)				\
	{ }								\
	{ }								\
	static inline int register_trace_##name(void (*probe)(proto))	\
	static inline int						\
	register_trace_##name(void (*probe)(data_proto),		\
			      void *data)				\
	{								\
	{								\
		return -ENOSYS;						\
		return -ENOSYS;						\
	}								\
	}								\
	static inline int unregister_trace_##name(void (*probe)(proto))	\
	static inline int						\
	unregister_trace_##name(void (*probe)(data_proto),		\
				void *data)				\
	{								\
	{								\
		return -ENOSYS;						\
		return -ENOSYS;						\
	}								\
	static inline void check_trace_callback_type_##name(void (*cb)(data_proto)) \
	{								\
	}
	}


#define DEFINE_TRACE_FN(name, reg, unreg)
#define DEFINE_TRACE_FN(name, reg, unreg)
@@ -176,6 +207,29 @@ static inline void tracepoint_update_probe_range(struct tracepoint *begin,
#define EXPORT_TRACEPOINT_SYMBOL(name)
#define EXPORT_TRACEPOINT_SYMBOL(name)


#endif /* CONFIG_TRACEPOINTS */
#endif /* CONFIG_TRACEPOINTS */

/*
 * The need for the DECLARE_TRACE_NOARGS() is to handle the prototype
 * (void). "void" is a special value in a function prototype and can
 * not be combined with other arguments. Since the DECLARE_TRACE()
 * macro adds a data element at the beginning of the prototype,
 * we need a way to differentiate "(void *data, proto)" from
 * "(void *data, void)". The second prototype is invalid.
 *
 * DECLARE_TRACE_NOARGS() passes "void" as the tracepoint prototype
 * and "void *__data" as the callback prototype.
 *
 * DECLARE_TRACE() passes "proto" as the tracepoint protoype and
 * "void *__data, proto" as the callback prototype.
 */
#define DECLARE_TRACE_NOARGS(name)					\
		__DECLARE_TRACE(name, void, , void *__data, __data)

#define DECLARE_TRACE(name, proto, args)				\
		__DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),	\
				PARAMS(void *__data, proto),		\
				PARAMS(__data, args))

#endif /* DECLARE_TRACE */
#endif /* DECLARE_TRACE */


#ifndef TRACE_EVENT
#ifndef TRACE_EVENT
+86 −153

File changed.

Preview size limit exceeded, changes collapsed.

+6 −4
Original line number Original line Diff line number Diff line
@@ -25,6 +25,8 @@ struct syscall_metadata {
	int		nb_args;
	int		nb_args;
	const char	**types;
	const char	**types;
	const char	**args;
	const char	**args;
	struct list_head enter_fields;
	struct list_head exit_fields;


	struct ftrace_event_call *enter_event;
	struct ftrace_event_call *enter_event;
	struct ftrace_event_call *exit_event;
	struct ftrace_event_call *exit_event;
@@ -34,16 +36,16 @@ struct syscall_metadata {
extern unsigned long arch_syscall_addr(int nr);
extern unsigned long arch_syscall_addr(int nr);
extern int init_syscall_trace(struct ftrace_event_call *call);
extern int init_syscall_trace(struct ftrace_event_call *call);


extern int syscall_enter_define_fields(struct ftrace_event_call *call);
extern int syscall_exit_define_fields(struct ftrace_event_call *call);
extern int reg_event_syscall_enter(struct ftrace_event_call *call);
extern int reg_event_syscall_enter(struct ftrace_event_call *call);
extern void unreg_event_syscall_enter(struct ftrace_event_call *call);
extern void unreg_event_syscall_enter(struct ftrace_event_call *call);
extern int reg_event_syscall_exit(struct ftrace_event_call *call);
extern int reg_event_syscall_exit(struct ftrace_event_call *call);
extern void unreg_event_syscall_exit(struct ftrace_event_call *call);
extern void unreg_event_syscall_exit(struct ftrace_event_call *call);
extern int
extern int
ftrace_format_syscall(struct ftrace_event_call *call, struct trace_seq *s);
ftrace_format_syscall(struct ftrace_event_call *call, struct trace_seq *s);
enum print_line_t print_syscall_enter(struct trace_iterator *iter, int flags);
enum print_line_t print_syscall_enter(struct trace_iterator *iter, int flags,
enum print_line_t print_syscall_exit(struct trace_iterator *iter, int flags);
				      struct trace_event *event);
enum print_line_t print_syscall_exit(struct trace_iterator *iter, int flags,
				     struct trace_event *event);
#endif
#endif


#ifdef CONFIG_PERF_EVENTS
#ifdef CONFIG_PERF_EVENTS
Loading