summaryrefslogtreecommitdiffstats
path: root/include/linux/ftrace_event.h
blob: 5c093ffc655bfd36c1579f539d5520a0ded30c15 (plain)
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
#ifndef _LINUX_FTRACE_EVENT_H
#define _LINUX_FTRACE_EVENT_H

#include <linux/trace_seq.h>
#include <linux/ring_buffer.h>
#include <linux/percpu.h>

struct trace_array;
struct tracer;
struct dentry;

DECLARE_PER_CPU(struct trace_seq, ftrace_event_seq);

struct trace_print_flags {
	unsigned long		mask;
	const char		*name;
};

const char *ftrace_print_flags_seq(struct trace_seq *p, const char *delim,
				   unsigned long flags,
				   const struct trace_print_flags *flag_array);

const char *ftrace_print_symbols_seq(struct trace_seq *p, unsigned long val,
				     const struct trace_print_flags *symbol_array);

/*
 * The trace entry - the most basic unit of tracing. This is what
 * is printed in the end as a single line in the trace output, such as:
 *
 *     bash-15816 [01]   235.197585: idle_cpu <- irq_enter
 */
struct trace_entry {
	unsigned short		type;
	unsigned char		flags;
	unsigned char		preempt_count;
	int			pid;
	int			tgid;
};

#define FTRACE_MAX_EVENT						\
	((1 << (sizeof(((struct trace_entry *)0)->type) * 8)) - 1)

/*
 * Trace iterator - used by printout routines who present trace
 * results to users and which routines might sleep, etc:
 */
struct trace_iterator {
	struct trace_array	*tr;
	struct tracer		*trace;
	void			*private;
	int			cpu_file;
	struct mutex		mutex;
	struct ring_buffer_iter	*buffer_iter[NR_CPUS];
	unsigned long		iter_flags;

	/* The below is zeroed out in pipe_read */
	struct trace_seq	seq;
	struct trace_entry	*ent;
	int			cpu;
	u64			ts;

	loff_t			pos;
	long			idx;

	cpumask_var_t		started;
};


typedef enum print_line_t (*trace_print_func)(struct trace_iterator *iter,
					      int flags);
struct trace_event {
	struct hlist_node	node;
	struct list_head	list;
	int			type;
	trace_print_func	trace;
	trace_print_func	raw;
	trace_print_func	hex;
	trace_print_func	binary;
};

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

/* Return values for print_line callback */
enum print_line_t {
	TRACE_TYPE_PARTIAL_LINE	= 0,	/* Retry after flushing the seq */
	TRACE_TYPE_HANDLED	= 1,
	TRACE_TYPE_UNHANDLED	= 2,	/* Relay to other output functions */
	TRACE_TYPE_NO_CONSUME	= 3	/* Handled but ask to not consume */
};


struct ring_buffer_event *
trace_current_buffer_lock_reserve(int type, unsigned long len,
				  unsigned long flags, int pc);
void trace_current_buffer_unlock_commit(struct ring_buffer_event *event,
					unsigned long flags, int pc);
void trace_nowake_buffer_unlock_commit(struct ring_buffer_event *event,
					unsigned long flags, int pc);
void trace_current_buffer_discard_commit(struct ring_buffer_event *event);

void tracing_record_cmdline(struct task_struct *tsk);

struct ftrace_event_call {
	struct list_head	list;
	char			*name;
	char			*system;
	struct dentry		*dir;
	struct trace_event	*event;
	int			enabled;
	int			(*regfunc)(void);
	void			(*unregfunc)(void);
	int			id;
	int			(*raw_init)(void);
	int			(*show_format)(struct trace_seq *s);
	int			(*define_fields)(void);
	struct list_head	fields;
	int			filter_active;
	void			*filter;
	void			*mod;

#ifdef CONFIG_EVENT_PROFILE
	atomic_t	profile_count;
	int		(*profile_enable)(struct ftrace_event_call *);
	void		(*profile_disable)(struct ftrace_event_call *);
#endif
};

#define MAX_FILTER_PRED		32
#define MAX_FILTER_STR_VAL	128

extern int init_preds(struct ftrace_event_call *call);
extern void destroy_preds(struct ftrace_event_call *call);
extern int filter_match_preds(struct ftrace_event_call *call, void *rec);
extern int filter_current_check_discard(struct ftrace_event_call *call,
					void *rec,
					struct ring_buffer_event *event);

extern int trace_define_field(struct ftrace_event_call *call, char *type,
			      char *name, int offset, int size, int is_signed);

#define is_signed_type(type)	(((type)(-1)) < 0)

int trace_set_clr_event(const char *system, const char *event, int set);

/*
 * The double __builtin_constant_p is because gcc will give us an error
 * if we try to allocate the static variable to fmt if it is not a
 * constant. Even with the outer if statement optimizing out.
 */
#define event_trace_printk(ip, fmt, args...)				\
do {									\
	__trace_printk_check_format(fmt, ##args);			\
	tracing_record_cmdline(current);				\
	if (__builtin_constant_p(fmt)) {				\
		static const char *trace_printk_fmt			\
		  __attribute__((section("__trace_printk_fmt"))) =	\
			__builtin_constant_p(fmt) ? fmt : NULL;		\
									\
		__trace_bprintk(ip, trace_printk_fmt, ##args);		\
	} else								\
		__trace_printk(ip, fmt, ##args);			\
} while (0)

#define __common_field(type, item, is_signed)				\
	ret = trace_define_field(event_call, #type, "common_" #item,	\
				 offsetof(typeof(field.ent), item),	\
				 sizeof(field.ent.item), is_signed);	\
	if (ret)							\
		return ret;

#endif /* _LINUX_FTRACE_EVENT_H */
OpenPOWER on IntegriCloud