Provided by: libtracefs-doc_1.7.0-1_all bug

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

       #include <tracefs.h>

       int tracefs_cpu_read_size(struct tracefs_cpu *tcpu);
       int tracefs_cpu_read(struct tracefs_cpu *tcpu, void *buffer, bool nonblock);
       int tracefs_cpu_buffered_read(struct tracefs_cpu *tcpu, void *buffer, bool nonblock);
       int tracefs_cpu_write(struct tracefs_cpu *tcpu, int wfd, bool nonblock);
       int tracefs_cpu_stop(struct tracefs_cpu *tcpu);
       int tracefs_cpu_flush(struct tracefs_cpu *tcpu, void *buffer);
       int tracefs_cpu_flush_write(struct tracefs_cpu *tcpu, int wfd);
       int tracefs_cpu_pipe(struct tracefs_cpu *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

           #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

           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

           Steven Rostedt <rostedt@goodmis.org[1]>

REPORTING BUGS

       Report bugs to <linux-trace-devel@vger.kernel.org[2]>

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).

NOTES

        1. rostedt@goodmis.org
           mailto:rostedt@goodmis.org

        2. linux-trace-devel@vger.kernel.org
           mailto:linux-trace-devel@vger.kernel.org