summaryrefslogtreecommitdiffstats
path: root/Documentation/libtracefs-cpu.txt
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--Documentation/libtracefs-cpu.txt240
1 files changed, 240 insertions, 0 deletions
diff --git a/Documentation/libtracefs-cpu.txt b/Documentation/libtracefs-cpu.txt
new file mode 100644
index 0000000..d6215d9
--- /dev/null
+++ b/Documentation/libtracefs-cpu.txt
@@ -0,0 +1,240 @@
+libtracefs(3)
+=============
+
+NAME
+----
+tracefs_cpu_read_size, tracefs_cpu_read, tracefs_cpu_buffered_read, tracefs_cpu_write,
+tracefs_cpu_stop, tracefs_cpu_flush, tracefs_cpu_flush_write, tracefs_cpu_pipe
+- Reading trace_pipe_raw data
+
+SYNOPSIS
+--------
+[verse]
+--
+*#include <tracefs.h>*
+
+int *tracefs_cpu_read_size*(struct tracefs_cpu pass:[*]_tcpu_);
+int *tracefs_cpu_read*(struct tracefs_cpu pass:[*]_tcpu_, void pass:[*]_buffer_, bool _nonblock_);
+int *tracefs_cpu_buffered_read*(struct tracefs_cpu pass:[*]_tcpu_, void pass:[*]_buffer_, bool _nonblock_);
+int *tracefs_cpu_write*(struct tracefs_cpu pass:[*]_tcpu_, int _wfd_, bool _nonblock_);
+int *tracefs_cpu_stop*(struct tracefs_cpu pass:[*]_tcpu_);
+int *tracefs_cpu_flush*(struct tracefs_cpu pass:[*]_tcpu_, void pass:[*]_buffer_);
+int *tracefs_cpu_flush_write*(struct tracefs_cpu pass:[*]_tcpu_, int _wfd_);
+int *tracefs_cpu_pipe*(struct tracefs_cpu pass:[*]_tcpu_, int _wfd_, bool _nonblock_);
+--
+
+DESCRIPTION
+-----------
+This set of APIs can be used to read the raw data from the trace_pipe_raw
+files in the tracefs file system.
+
+The *tracefs_cpu_read_size()* returns the subbuffer size of the trace_pipe_raw. This
+returns the minimum size of the buffer that is passed to the below functions.
+
+The *tracefs_cpu_read()* reads the trace_pipe_raw files associated to _tcpu_ into _buffer_.
+_buffer_ must be at least the size of the sub buffer of the ring buffer,
+which is returned by *tracefs_cpu_read_size()*. If _nonblock_ is set, and
+there's no data available, it will return immediately. Otherwise depending
+on how _tcpu_ was opened, it will block. If _tcpu_ was opened with nonblock
+set, then this _nonblock_ will make no difference.
+
+The *tracefs_cpu_buffered_read()* is basically the same as *tracefs_cpu_read()*
+except that it uses a pipe through splice to buffer reads. This will batch
+reads keeping the reading from the ring buffer less intrusive to the system,
+as just reading all the time can cause quite a disturbance. Note, one
+difference between this and *tracefs_cpu_read()* is that it will read only in
+sub buffer pages. If the ring buffer has not filled a page, then it will not
+return anything, even with _nonblock_ set. Calls to *tracefs_cpu_flush()*
+should be done to read the rest of the file at the end of the trace.
+
+The *tracefs_cpu_write()* will pipe the data from the trace_pipe_raw
+file associated with _tcpu_ into the _wfd_ file descriptor. If _nonblock_ is set,
+then it will not block on if there's nothing to write. Note, it will only write
+sub buffer size data to _wfd_. Calls to tracefs_cpu_flush_write() are needed to
+write out the rest.
+
+The *tracefs_cpu_stop()* will attempt to unblock a task blocked on _tcpu_ reading it.
+On older kernels, it may not do anything for the pipe reads, as older kernels do not
+wake up tasks waiting on the ring buffer. Returns 0 if it definitely woke up any possible
+waiters, but returns 1 if it is not sure it worked and waiters may need to have a signal
+sent to them.
+
+The *tracefs_cpu_flush()* reads the trace_pipe_raw file associated by the _tcpu_ and puts it
+into _buffer_, which must be the size of the sub buffer which is retrieved.
+by *tracefs_cpu_read_size()*. This should be called at the end of tracing
+to get the rest of the data. This call will convert the file descriptor of
+trace_pipe_raw into non-blocking mode.
+
+The *tracefs_cpu_flush_write()* same as *trace_cpu_flush()* except it takes a file
+descriptor _wfd_ to flush the data into.
+
+The *tracefs_cpu_pipe()* is similar to *tracefs_cpu_write()* but the _wfd_ file descriptor
+must be a pipe. This call is an optimization of *tracefs_cpu_write()* that uses two calls
+to *splice*(2) in order to connect the trace_pipe_raw file descriptor with the write file
+descriptor. *splice*(2) requires that one of the passed in file descriptors is a pipe.
+If the application wants to pass the data to an existing pipe, there's no reason for
+there to be two *splice*(2) system calls and *tracefs_cpu_pipe()* can simply use a single
+call to _wfd_.
+
+RETURN VALUE
+------------
+The *tracefs_cpu_open()* returns a struct tracefs_cpu descriptor that can be
+used by the other functions or NULL on error.
+
+The *tracefs_cpu_read_size()* returns the minimum size of the buffers to be
+used with *tracefs_cpu_read()*, *tracefs_cpu_buffered_read()* and *tracefs_cpu_flush()*.
+Returns negative on error.
+
+The *tracefs_cpu_read()* returns the number of bytes read, or negative on error.
+
+The *tracefs_cpu_buffered_read()* returns the number of bytes read or negative on error.
+
+The *tracefs_cpu_write()* returns the number of bytes written to the file
+or negative on error.
+
+The *tracefs_cpu_stop()* returns zero if any waiters were guaranteed to be
+woken up from waiting on input, or returns one if this is an older kernel
+that does not supply that guarantee, and a signal may need to be sent to
+any waiters. Returns negative on error.
+
+The *tracefs_cpu_flush()* returns the number of bytes read or negative on error.
+
+The *tracefs_cpu_flush_write()* returns the number of bytes written to the
+file or negative on error.
+
+EXAMPLE
+-------
+[source,c]
+--
+#define _LARGEFILE64_SOURCE
+#include <stdlib.h>
+#include <ctype.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <tracefs.h>
+
+struct thread_data {
+ struct tracefs_cpu *tcpu;
+ int done;
+ int fd;
+};
+
+static void *thread_run(void *arg)
+{
+ struct thread_data *data = arg;
+ struct tracefs_cpu *tcpu = data->tcpu;
+ int fd = data->fd;
+ int ret;
+
+ while (!data->done) {
+ ret = tracefs_cpu_write(tcpu, fd, false);
+ printf("wrote %d\n", ret);
+ }
+ return NULL;
+}
+
+int main (int argc, char **argv)
+{
+ struct tracefs_instance *instance;
+ struct thread_data data;
+ pthread_t thread;
+ char *file;
+ int secs = 10;
+ int cpu;
+ int ret;
+
+ if (argc < 3 || !isdigit(argv[1][0])) {
+ printf("usage: %s cpu file_destination [sleep secs]\n\n", argv[0]);
+ exit(-1);
+ }
+
+ cpu = atoi(argv[1]);
+ file = argv[2];
+
+ if (argc > 3)
+ secs = atoi(argv[3]);
+
+ instance = tracefs_instance_create("cpu_write");
+ if (!instance) {
+ perror("create instance");
+ exit(-1);
+ }
+
+ memset(&data, 0, sizeof(data));
+
+ data.tcpu = tracefs_cpu_open(instance, cpu, 0);
+ if (!data.tcpu) {
+ perror("Open instance");
+ exit(-1);
+ }
+
+ data.fd = open(file, O_WRONLY | O_CREAT | O_TRUNC | O_LARGEFILE, 0644);
+ if (data.fd < 0) {
+ perror(file);
+ exit(-1);
+ }
+
+ pthread_create(&thread, NULL, thread_run, &data);
+
+ sleep(secs);
+
+ data.done = 1;
+ printf("stopping\n");
+ ret = tracefs_cpu_stop(data.tcpu);
+
+ printf("joining %d\n", ret);
+ pthread_join(thread, NULL);
+
+ tracefs_trace_off(instance);
+ do {
+ ret = tracefs_cpu_flush_write(data.tcpu, data.fd);
+ printf("flushed %d\n", ret);
+ } while (ret > 0);
+ tracefs_trace_on(instance);
+
+ tracefs_cpu_close(data.tcpu);
+ close(data.fd);
+
+ 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
+--------
+*tracefs_cpu_open*(3)
+*tracefs_cpu_close*(3)
+*libtracefs*(3),
+*libtraceevent*(3),
+*trace-cmd*(1)
+
+AUTHOR
+------
+[verse]
+--
+*Steven Rostedt* <rostedt@goodmis.org>
+--
+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) 2022 Google, Inc. Free use of this software is granted under
+the terms of the GNU Public License (GPL).