File: libtracefs-iterator.txt

package info (click to toggle)
libtracefs 1.8.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,368 kB
  • sloc: ansic: 12,953; makefile: 609; sh: 509; yacc: 188; lex: 106
file content (265 lines) | stat: -rw-r--r-- 8,742 bytes parent folder | download | duplicates (2)
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
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
libtracefs(3)
=============

NAME
----
tracefs_iterate_raw_events, tracefs_iterate_stop, tracefs_follow_event, tracefs_follow_missed_events,
tracefs_follow_event_clear, tracefs_follow_missed_events_clear, tracefs_iterate_snapshot_events - Iterate over events in the ring buffer

SYNOPSIS
--------
[verse]
--
*#include <tracefs.h>*

int *tracefs_iterate_raw_events*(struct tep_handle pass:[*]_tep_, struct tracefs_instance pass:[*]_instance_,
				 cpu_set_t pass:[*]_cpus_, int _cpu_size_,
				 int (pass:[*]_callback_)(struct tep_event pass:[*], struct tep_record pass:[*], int, void pass:[*]),
				 void pass:[*]_callback_context_);
void *tracefs_iterate_stop*(struct tracefs_instance pass:[*]_instance_);

int *tracefs_follow_event*(struct tep_handle pass:[*]_tep_, struct tracefs_instance pass:[*]_instance_,
			  const char pass:[*]_system_, const char pass:[*]_event_name_,
			  int (pass:[*]_callback_)(struct tep_event pass:[*],
					  struct tep_record pass:[*],
					  int, void pass:[*]),
			  void pass:[*]_callback_data_);
int *tracefs_follow_missed_events*(struct tracefs_instance pass:[*]_instance_,
			  int (pass:[*]_callback_)(struct tep_event pass:[*],
					  struct tep_record pass:[*],
					  int, void pass:[*]),
			  void pass:[*]_callback_data_);

int *tracefs_follow_event_clear*(struct tracefs_instance pass:[*]_instance_,
			  const char pass:[*]_system_, const char pass:[*]_event_name_);
int *tracefs_follow_missed_events_clear*(struct tracefs_instance pass:[*]_instance_);

int *tracefs_iterate_snapshot_events*(struct tep_handle pass:[*]_tep_, struct tracefs_instance pass:[*]_instance_,
				 cpu_set_t pass:[*]_cpus_, int _cpu_size_,
				 int (pass:[*]_callback_)(struct tep_event pass:[*], struct tep_record pass:[*], int, void pass:[*]),
				 void pass:[*]_callback_context_);
--

DESCRIPTION
-----------
Trace iterator over raw events.

The *tracefs_iterate_raw_events()* function will read the tracefs raw
data buffers and call the specified _callback_ function for every event it
encounters. Events are iterated in sorted order: oldest first. An initialized
_tep_ handler is required (See *tracefs_local_events*(3)). If _instance_ is
NULL, then the toplevel tracefs buffer is used, otherwise the buffer for
the corresponding _instance_ is read. To filter only on a subset of CPUs,
_cpus_ and _cpu_size_ may be set to only call _callback_ with events that
occurred on the CPUs specified, otherwise if _cpus_ is NULL then the _callback_
function will be called for all events, and _cpu_size_ is ignored. The
_callback_ function will be called with the following parameters: A
pointer to a struct tep_event that corresponds to the type of event the
record is; The record representing the event; The CPU that the event
occurred on; and a pointer to user specified _callback_context_. If the _callback_
returns non-zero, the iteration stops.

The *tracefs_iterate_snapshot_events()* works the same as *tracefs_iterate_raw_events()*
except that it works on the snapshot buffer.

Use *tracefs_iterate_stop()* to force a executing *tracefs_iterate_raw_events()*
to halt. This can be called from either a callback that is called by
the iterator (even though a return of non-zero will stop it), or from another
thread.

The *tracefs_follow_event()* is used with *tracefs_iterate_raw_events()* but
intead of the callback being called for every event, it is only called for the
specified _system_ / _event_name_ given to the function. The _callback_ is the
same as for *tracefs_iterate_raw_events()*, and the passed in _callback_context_
will be passed to the _callback_ as well. Note, if it returns something other
than 0, it will stop the loop before the _callback_ of *tracefs_iterate_raw_events()*
is called.

The *tracefs_follow_missed_events()* will call the _callback_ when missed
events are detected. It will set the _record_ parameter of the callback to the
record that came after the missed events and _event_ will be of the type of
event _record_ is. _cpu_ will be set to the CPU that missed the events, and
_callback_data_ will be the content that was passed in to the function.

The *tracefs_follow_event_clear()* will remove followers from _instance_ that
match _system_ and _event_name_. If _system_ and _event_name_ are both NULL,
then it will remove all event followers associated to _instance_. If just _system_
is NULL, then it will remove all followers that follow events that match _event_name_. If just _event_name_
is NULL, then it will remove all followers that are attached to events that are
apart of a system that matches _system_.

The *tracefs_follow_missed_events_clear()* will remove all followers for missed
events.

RETURN VALUE
------------
The *tracefs_iterate_raw_events()* function returns -1 in case of an error or
0 otherwise.

Both *tracefs_follow_event_clear()* and *tracefs_follow_missed_events_clear()* return
0 on success and -1 on error, or if it found no followers that match and should be removed.

EXAMPLE
-------
[source,c]
--
#include <unistd.h>
#include <tracefs.h>
#include <stdbool.h>
#include <signal.h>

struct my_struct {
	bool		stopped;
};

#define MAX_COUNT 500000
static int counter;

static int callback(struct tep_event *event, struct tep_record *record,
		    int cpu, void *data)
{
	struct my_struct *my_data = data;
	static struct trace_seq seq;

	if (counter++ > MAX_COUNT) {
		my_data->stopped = true;
		return 1;
	}

	if (!seq.buffer)
		trace_seq_init(&seq);

	tep_print_event(event->tep, &seq, record, "%16s-%-5d [%03d] %6.1000d %s: %s\n",
			TEP_PRINT_COMM, TEP_PRINT_PID, TEP_PRINT_CPU,
			TEP_PRINT_TIME, TEP_PRINT_NAME, TEP_PRINT_INFO);
	trace_seq_terminate(&seq);
	trace_seq_do_printf(&seq);
	trace_seq_reset(&seq);
	return 0;
}

static int sched_callback(struct tep_event *event, struct tep_record *record,
			  int cpu, void *data)
{
	static struct tep_format_field *prev_pid;
	static struct tep_format_field *next_pid;
	unsigned long long pid;
	int this_pid = *(int *)data;

	if (!prev_pid) {
		prev_pid = tep_find_field(event, "prev_pid");
		next_pid = tep_find_field(event, "next_pid");
		if (!prev_pid || !next_pid) {
			fprintf(stderr, "No pid fields??\n");
			return -1;
		}
	}

	tep_read_number_field(prev_pid, record->data, &pid);
	if (pid == this_pid)
		printf("WE ARE LEAVING!\n");
	tep_read_number_field(next_pid, record->data, &pid);
	if (pid == this_pid)
		printf("WE ARE ARRIVING!\n");
	return 0;
}

static int missed_callback(struct tep_event *event, struct tep_record *record,
			   int cpu, void *data)
{
	printf("OOPS! cpu %d dropped ", cpu);
	if (record->missed_events > 0)
		printf("%lld ", record->missed_events);
	printf("events\n");
	return 0;
}

static struct tracefs_instance *instance;
static struct my_struct my_data;

static void sig(int s)
{
	tracefs_iterate_stop(instance);
	my_data.stopped = true;
}

int main (int argc, char **argv, char **env)
{
	struct tep_handle *tep;
	int this_pid = getpid();

	instance = tracefs_instance_create("my-buffer");
	if (!instance)
		return -1;

	signal(SIGINT, sig);

	tracefs_event_enable(instance, NULL, NULL);
	sleep(1);
	tracefs_event_disable(instance, NULL, NULL);
	tep = tracefs_local_events(NULL);
	tep_load_plugins(tep);
	tracefs_follow_missed_events(instance, missed_callback, NULL);
	tracefs_follow_event(tep, instance, "sched", "sched_switch", sched_callback, &this_pid);
	tracefs_iterate_raw_events(tep, instance, NULL, 0, callback, &my_data);

	/* Note, the clear here is to show how to clear all followers
	 * in case tracefs_iterate_raw_events() is called again, but
	 * does not want to include the followers. It's not needed
	 * here because tracefs_instance_free() will clean them up.
	 */
	tracefs_follow_event_clear(instance, NULL, NULL);
	tracefs_follow_missed_events_clear(instance);

	tracefs_instance_destroy(instance);
	tracefs_instance_free(instance);

	if (my_data.stopped) {
		if (counter > MAX_COUNT)
			printf("Finished max count\n");
		else
			printf("Finished via signal\n");
	}

	return 0;
}
--
FILES
-----
[verse]
--
*tracefs.h*
	Header file to include in order to have access to the library APIs.
*-ltracefs*
	Linker switch to add when building a program that uses the library.
--

SEE ALSO
--------
*libtracefs*(3),
*libtraceevent*(3),
*trace-cmd*(1)

AUTHOR
------
[verse]
--
*Steven Rostedt* <rostedt@goodmis.org>
*Tzvetomir Stoyanov* <tz.stoyanov@gmail.com>
--
REPORTING BUGS
--------------
Report bugs to  <linux-trace-devel@vger.kernel.org>

LICENSE
-------
libtracefs is Free Software licensed under the GNU LGPL 2.1

RESOURCES
---------
https://git.kernel.org/pub/scm/libs/libtrace/libtracefs.git/

COPYING
-------
Copyright \(C) 2020 VMware, Inc. Free use of this software is granted under
the terms of the GNU Public License (GPL).