xref: /aosp_15_r20/external/libtracefs/Documentation/libtracefs-cpu.txt (revision 287e80b3a36113050663245e7f2c00d274188f18)
1*287e80b3SSadaf Ebrahimilibtracefs(3)
2*287e80b3SSadaf Ebrahimi=============
3*287e80b3SSadaf Ebrahimi
4*287e80b3SSadaf EbrahimiNAME
5*287e80b3SSadaf Ebrahimi----
6*287e80b3SSadaf Ebrahimitracefs_cpu_read_size, tracefs_cpu_read, tracefs_cpu_buffered_read, tracefs_cpu_write,
7*287e80b3SSadaf Ebrahimitracefs_cpu_stop, tracefs_cpu_flush, tracefs_cpu_flush_write, tracefs_cpu_pipe
8*287e80b3SSadaf Ebrahimi- Reading trace_pipe_raw data
9*287e80b3SSadaf Ebrahimi
10*287e80b3SSadaf EbrahimiSYNOPSIS
11*287e80b3SSadaf Ebrahimi--------
12*287e80b3SSadaf Ebrahimi[verse]
13*287e80b3SSadaf Ebrahimi--
14*287e80b3SSadaf Ebrahimi*#include <tracefs.h>*
15*287e80b3SSadaf Ebrahimi
16*287e80b3SSadaf Ebrahimiint *tracefs_cpu_read_size*(struct tracefs_cpu pass:[*]_tcpu_);
17*287e80b3SSadaf Ebrahimiint *tracefs_cpu_read*(struct tracefs_cpu pass:[*]_tcpu_, void pass:[*]_buffer_, bool _nonblock_);
18*287e80b3SSadaf Ebrahimiint *tracefs_cpu_buffered_read*(struct tracefs_cpu pass:[*]_tcpu_, void pass:[*]_buffer_, bool _nonblock_);
19*287e80b3SSadaf Ebrahimiint *tracefs_cpu_write*(struct tracefs_cpu pass:[*]_tcpu_, int _wfd_, bool _nonblock_);
20*287e80b3SSadaf Ebrahimiint *tracefs_cpu_stop*(struct tracefs_cpu pass:[*]_tcpu_);
21*287e80b3SSadaf Ebrahimiint *tracefs_cpu_flush*(struct tracefs_cpu pass:[*]_tcpu_, void pass:[*]_buffer_);
22*287e80b3SSadaf Ebrahimiint *tracefs_cpu_flush_write*(struct tracefs_cpu pass:[*]_tcpu_, int _wfd_);
23*287e80b3SSadaf Ebrahimiint *tracefs_cpu_pipe*(struct tracefs_cpu pass:[*]_tcpu_, int _wfd_, bool _nonblock_);
24*287e80b3SSadaf Ebrahimi--
25*287e80b3SSadaf Ebrahimi
26*287e80b3SSadaf EbrahimiDESCRIPTION
27*287e80b3SSadaf Ebrahimi-----------
28*287e80b3SSadaf EbrahimiThis set of APIs can be used to read the raw data from the trace_pipe_raw
29*287e80b3SSadaf Ebrahimifiles in the tracefs file system.
30*287e80b3SSadaf Ebrahimi
31*287e80b3SSadaf EbrahimiThe *tracefs_cpu_read_size()* returns the subbuffer size of the trace_pipe_raw. This
32*287e80b3SSadaf Ebrahimireturns the minimum size of the buffer that is passed to the below functions.
33*287e80b3SSadaf Ebrahimi
34*287e80b3SSadaf EbrahimiThe *tracefs_cpu_read()* reads the trace_pipe_raw files associated to _tcpu_ into _buffer_.
35*287e80b3SSadaf Ebrahimi_buffer_ must be at least the size of the sub buffer of the ring buffer,
36*287e80b3SSadaf Ebrahimiwhich is returned by *tracefs_cpu_read_size()*. If _nonblock_ is set, and
37*287e80b3SSadaf Ebrahimithere's no data available, it will return immediately. Otherwise depending
38*287e80b3SSadaf Ebrahimion how _tcpu_ was opened, it will block. If _tcpu_ was opened with nonblock
39*287e80b3SSadaf Ebrahimiset, then this _nonblock_ will make no difference.
40*287e80b3SSadaf Ebrahimi
41*287e80b3SSadaf EbrahimiThe *tracefs_cpu_buffered_read()* is basically the same as *tracefs_cpu_read()*
42*287e80b3SSadaf Ebrahimiexcept that it uses a pipe through splice to buffer reads. This will batch
43*287e80b3SSadaf Ebrahimireads keeping the reading from the ring buffer less intrusive to the system,
44*287e80b3SSadaf Ebrahimias just reading all the time can cause quite a disturbance. Note, one
45*287e80b3SSadaf Ebrahimidifference between this and *tracefs_cpu_read()* is that it will read only in
46*287e80b3SSadaf Ebrahimisub buffer pages. If the ring buffer has not filled a page, then it will not
47*287e80b3SSadaf Ebrahimireturn anything, even with _nonblock_ set.  Calls to *tracefs_cpu_flush()*
48*287e80b3SSadaf Ebrahimishould be done to read the rest of the file at the end of the trace.
49*287e80b3SSadaf Ebrahimi
50*287e80b3SSadaf EbrahimiThe *tracefs_cpu_write()* will pipe the data from the trace_pipe_raw
51*287e80b3SSadaf Ebrahimifile associated with _tcpu_ into the _wfd_ file descriptor. If _nonblock_ is set,
52*287e80b3SSadaf Ebrahimithen it will not block on if there's nothing to write. Note, it will only write
53*287e80b3SSadaf Ebrahimisub buffer size data to _wfd_. Calls to tracefs_cpu_flush_write() are needed to
54*287e80b3SSadaf Ebrahimiwrite out the rest.
55*287e80b3SSadaf Ebrahimi
56*287e80b3SSadaf EbrahimiThe *tracefs_cpu_stop()* will attempt to unblock a task blocked on _tcpu_ reading it.
57*287e80b3SSadaf EbrahimiOn older kernels, it may not do anything for the pipe reads, as older kernels do not
58*287e80b3SSadaf Ebrahimiwake up tasks waiting on the ring buffer. Returns 0 if it definitely woke up any possible
59*287e80b3SSadaf Ebrahimiwaiters, but returns 1 if it is not sure it worked and waiters may need to have a signal
60*287e80b3SSadaf Ebrahimisent to them.
61*287e80b3SSadaf Ebrahimi
62*287e80b3SSadaf EbrahimiThe *tracefs_cpu_flush()* reads the trace_pipe_raw file associated by the _tcpu_ and puts it
63*287e80b3SSadaf Ebrahimiinto _buffer_, which must be the size of the sub buffer which is retrieved.
64*287e80b3SSadaf Ebrahimiby *tracefs_cpu_read_size()*. This should be called at the end of tracing
65*287e80b3SSadaf Ebrahimito get the rest of the data. This call will convert the file descriptor of
66*287e80b3SSadaf Ebrahimitrace_pipe_raw into non-blocking mode.
67*287e80b3SSadaf Ebrahimi
68*287e80b3SSadaf EbrahimiThe *tracefs_cpu_flush_write()* same as *trace_cpu_flush()* except it takes a file
69*287e80b3SSadaf Ebrahimidescriptor _wfd_ to flush the data into.
70*287e80b3SSadaf Ebrahimi
71*287e80b3SSadaf EbrahimiThe *tracefs_cpu_pipe()* is similar to *tracefs_cpu_write()* but the _wfd_ file descriptor
72*287e80b3SSadaf Ebrahimimust be a pipe. This call is an optimization of *tracefs_cpu_write()* that uses two calls
73*287e80b3SSadaf Ebrahimito *splice*(2) in order to connect the trace_pipe_raw file descriptor with the write file
74*287e80b3SSadaf Ebrahimidescriptor. *splice*(2) requires that one of the passed in file descriptors is a pipe.
75*287e80b3SSadaf EbrahimiIf the application wants to pass the data to an existing pipe, there's no reason for
76*287e80b3SSadaf Ebrahimithere to be two *splice*(2) system calls and *tracefs_cpu_pipe()* can simply use a single
77*287e80b3SSadaf Ebrahimicall to _wfd_.
78*287e80b3SSadaf Ebrahimi
79*287e80b3SSadaf EbrahimiRETURN VALUE
80*287e80b3SSadaf Ebrahimi------------
81*287e80b3SSadaf EbrahimiThe *tracefs_cpu_open()* returns a struct tracefs_cpu descriptor that can be
82*287e80b3SSadaf Ebrahimiused by the other functions or NULL on error.
83*287e80b3SSadaf Ebrahimi
84*287e80b3SSadaf EbrahimiThe *tracefs_cpu_read_size()* returns the minimum size of the buffers to be
85*287e80b3SSadaf Ebrahimiused with *tracefs_cpu_read()*, *tracefs_cpu_buffered_read()* and *tracefs_cpu_flush()*.
86*287e80b3SSadaf EbrahimiReturns negative on error.
87*287e80b3SSadaf Ebrahimi
88*287e80b3SSadaf EbrahimiThe *tracefs_cpu_read()* returns the number of bytes read, or negative on error.
89*287e80b3SSadaf Ebrahimi
90*287e80b3SSadaf EbrahimiThe *tracefs_cpu_buffered_read()* returns the number of bytes read or negative on error.
91*287e80b3SSadaf Ebrahimi
92*287e80b3SSadaf EbrahimiThe *tracefs_cpu_write()* returns the number of bytes written to the file
93*287e80b3SSadaf Ebrahimior negative on error.
94*287e80b3SSadaf Ebrahimi
95*287e80b3SSadaf EbrahimiThe *tracefs_cpu_stop()* returns zero if any waiters were guaranteed to be
96*287e80b3SSadaf Ebrahimiwoken up from waiting on input, or returns one if this is an older kernel
97*287e80b3SSadaf Ebrahimithat does not supply that guarantee, and a signal may need to be sent to
98*287e80b3SSadaf Ebrahimiany waiters. Returns negative on error.
99*287e80b3SSadaf Ebrahimi
100*287e80b3SSadaf EbrahimiThe *tracefs_cpu_flush()* returns the number of bytes read or negative on error.
101*287e80b3SSadaf Ebrahimi
102*287e80b3SSadaf EbrahimiThe *tracefs_cpu_flush_write()* returns the number of bytes written to the
103*287e80b3SSadaf Ebrahimifile  or negative on error.
104*287e80b3SSadaf Ebrahimi
105*287e80b3SSadaf EbrahimiEXAMPLE
106*287e80b3SSadaf Ebrahimi-------
107*287e80b3SSadaf Ebrahimi[source,c]
108*287e80b3SSadaf Ebrahimi--
109*287e80b3SSadaf Ebrahimi#define _LARGEFILE64_SOURCE
110*287e80b3SSadaf Ebrahimi#include <stdlib.h>
111*287e80b3SSadaf Ebrahimi#include <ctype.h>
112*287e80b3SSadaf Ebrahimi#include <pthread.h>
113*287e80b3SSadaf Ebrahimi#include <unistd.h>
114*287e80b3SSadaf Ebrahimi#include <tracefs.h>
115*287e80b3SSadaf Ebrahimi
116*287e80b3SSadaf Ebrahimistruct thread_data {
117*287e80b3SSadaf Ebrahimi	struct tracefs_cpu	*tcpu;
118*287e80b3SSadaf Ebrahimi	int			done;
119*287e80b3SSadaf Ebrahimi	int			fd;
120*287e80b3SSadaf Ebrahimi};
121*287e80b3SSadaf Ebrahimi
122*287e80b3SSadaf Ebrahimistatic void *thread_run(void *arg)
123*287e80b3SSadaf Ebrahimi{
124*287e80b3SSadaf Ebrahimi	struct thread_data *data = arg;
125*287e80b3SSadaf Ebrahimi	struct tracefs_cpu *tcpu = data->tcpu;
126*287e80b3SSadaf Ebrahimi	int fd = data->fd;
127*287e80b3SSadaf Ebrahimi	int ret;
128*287e80b3SSadaf Ebrahimi
129*287e80b3SSadaf Ebrahimi	while (!data->done) {
130*287e80b3SSadaf Ebrahimi		ret = tracefs_cpu_write(tcpu, fd, false);
131*287e80b3SSadaf Ebrahimi		printf("wrote %d\n", ret);
132*287e80b3SSadaf Ebrahimi	}
133*287e80b3SSadaf Ebrahimi	return NULL;
134*287e80b3SSadaf Ebrahimi}
135*287e80b3SSadaf Ebrahimi
136*287e80b3SSadaf Ebrahimiint main (int argc, char **argv)
137*287e80b3SSadaf Ebrahimi{
138*287e80b3SSadaf Ebrahimi	struct tracefs_instance *instance;
139*287e80b3SSadaf Ebrahimi	struct thread_data data;
140*287e80b3SSadaf Ebrahimi	pthread_t thread;
141*287e80b3SSadaf Ebrahimi	char *file;
142*287e80b3SSadaf Ebrahimi	int secs = 10;
143*287e80b3SSadaf Ebrahimi	int cpu;
144*287e80b3SSadaf Ebrahimi	int ret;
145*287e80b3SSadaf Ebrahimi
146*287e80b3SSadaf Ebrahimi	if (argc < 3 || !isdigit(argv[1][0])) {
147*287e80b3SSadaf Ebrahimi		printf("usage: %s cpu file_destination [sleep secs]\n\n", argv[0]);
148*287e80b3SSadaf Ebrahimi		exit(-1);
149*287e80b3SSadaf Ebrahimi	}
150*287e80b3SSadaf Ebrahimi
151*287e80b3SSadaf Ebrahimi	cpu = atoi(argv[1]);
152*287e80b3SSadaf Ebrahimi	file = argv[2];
153*287e80b3SSadaf Ebrahimi
154*287e80b3SSadaf Ebrahimi	if (argc > 3)
155*287e80b3SSadaf Ebrahimi		secs = atoi(argv[3]);
156*287e80b3SSadaf Ebrahimi
157*287e80b3SSadaf Ebrahimi	instance = tracefs_instance_create("cpu_write");
158*287e80b3SSadaf Ebrahimi	if (!instance) {
159*287e80b3SSadaf Ebrahimi		perror("create instance");
160*287e80b3SSadaf Ebrahimi		exit(-1);
161*287e80b3SSadaf Ebrahimi	}
162*287e80b3SSadaf Ebrahimi
163*287e80b3SSadaf Ebrahimi	memset(&data, 0, sizeof(data));
164*287e80b3SSadaf Ebrahimi
165*287e80b3SSadaf Ebrahimi	data.tcpu = tracefs_cpu_open(instance, cpu, 0);
166*287e80b3SSadaf Ebrahimi	if (!data.tcpu) {
167*287e80b3SSadaf Ebrahimi		perror("Open instance");
168*287e80b3SSadaf Ebrahimi		exit(-1);
169*287e80b3SSadaf Ebrahimi	}
170*287e80b3SSadaf Ebrahimi
171*287e80b3SSadaf Ebrahimi	data.fd = open(file, O_WRONLY | O_CREAT | O_TRUNC | O_LARGEFILE, 0644);
172*287e80b3SSadaf Ebrahimi	if (data.fd < 0) {
173*287e80b3SSadaf Ebrahimi		perror(file);
174*287e80b3SSadaf Ebrahimi		exit(-1);
175*287e80b3SSadaf Ebrahimi	}
176*287e80b3SSadaf Ebrahimi
177*287e80b3SSadaf Ebrahimi	pthread_create(&thread, NULL, thread_run, &data);
178*287e80b3SSadaf Ebrahimi
179*287e80b3SSadaf Ebrahimi	sleep(secs);
180*287e80b3SSadaf Ebrahimi
181*287e80b3SSadaf Ebrahimi	data.done = 1;
182*287e80b3SSadaf Ebrahimi	printf("stopping\n");
183*287e80b3SSadaf Ebrahimi	ret = tracefs_cpu_stop(data.tcpu);
184*287e80b3SSadaf Ebrahimi
185*287e80b3SSadaf Ebrahimi	printf("joining %d\n", ret);
186*287e80b3SSadaf Ebrahimi	pthread_join(thread, NULL);
187*287e80b3SSadaf Ebrahimi
188*287e80b3SSadaf Ebrahimi	tracefs_trace_off(instance);
189*287e80b3SSadaf Ebrahimi	do {
190*287e80b3SSadaf Ebrahimi		ret = tracefs_cpu_flush_write(data.tcpu, data.fd);
191*287e80b3SSadaf Ebrahimi		printf("flushed %d\n", ret);
192*287e80b3SSadaf Ebrahimi	} while (ret > 0);
193*287e80b3SSadaf Ebrahimi	tracefs_trace_on(instance);
194*287e80b3SSadaf Ebrahimi
195*287e80b3SSadaf Ebrahimi	tracefs_cpu_close(data.tcpu);
196*287e80b3SSadaf Ebrahimi	close(data.fd);
197*287e80b3SSadaf Ebrahimi
198*287e80b3SSadaf Ebrahimi	return 0;
199*287e80b3SSadaf Ebrahimi}
200*287e80b3SSadaf Ebrahimi--
201*287e80b3SSadaf EbrahimiFILES
202*287e80b3SSadaf Ebrahimi-----
203*287e80b3SSadaf Ebrahimi[verse]
204*287e80b3SSadaf Ebrahimi--
205*287e80b3SSadaf Ebrahimi*tracefs.h*
206*287e80b3SSadaf Ebrahimi	Header file to include in order to have access to the library APIs.
207*287e80b3SSadaf Ebrahimi*-ltracefs*
208*287e80b3SSadaf Ebrahimi	Linker switch to add when building a program that uses the library.
209*287e80b3SSadaf Ebrahimi--
210*287e80b3SSadaf Ebrahimi
211*287e80b3SSadaf EbrahimiSEE ALSO
212*287e80b3SSadaf Ebrahimi--------
213*287e80b3SSadaf Ebrahimi*tracefs_cpu_open*(3)
214*287e80b3SSadaf Ebrahimi*tracefs_cpu_close*(3)
215*287e80b3SSadaf Ebrahimi*libtracefs*(3),
216*287e80b3SSadaf Ebrahimi*libtraceevent*(3),
217*287e80b3SSadaf Ebrahimi*trace-cmd*(1)
218*287e80b3SSadaf Ebrahimi
219*287e80b3SSadaf EbrahimiAUTHOR
220*287e80b3SSadaf Ebrahimi------
221*287e80b3SSadaf Ebrahimi[verse]
222*287e80b3SSadaf Ebrahimi--
223*287e80b3SSadaf Ebrahimi*Steven Rostedt* <[email protected]>
224*287e80b3SSadaf Ebrahimi--
225*287e80b3SSadaf EbrahimiREPORTING BUGS
226*287e80b3SSadaf Ebrahimi--------------
227*287e80b3SSadaf EbrahimiReport bugs to  <[email protected]>
228*287e80b3SSadaf Ebrahimi
229*287e80b3SSadaf EbrahimiLICENSE
230*287e80b3SSadaf Ebrahimi-------
231*287e80b3SSadaf Ebrahimilibtracefs is Free Software licensed under the GNU LGPL 2.1
232*287e80b3SSadaf Ebrahimi
233*287e80b3SSadaf EbrahimiRESOURCES
234*287e80b3SSadaf Ebrahimi---------
235*287e80b3SSadaf Ebrahimihttps://git.kernel.org/pub/scm/libs/libtrace/libtracefs.git/
236*287e80b3SSadaf Ebrahimi
237*287e80b3SSadaf EbrahimiCOPYING
238*287e80b3SSadaf Ebrahimi-------
239*287e80b3SSadaf EbrahimiCopyright \(C) 2022 Google, Inc. Free use of this software is granted under
240*287e80b3SSadaf Ebrahimithe terms of the GNU Public License (GPL).
241