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