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