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