1libtracefs(3) 2============= 3 4NAME 5---- 6tracefs_iterate_raw_events, tracefs_iterate_stop, tracefs_follow_event, tracefs_follow_missed_events, 7tracefs_follow_event_clear, tracefs_follow_missed_events_clear, tracefs_iterate_snapshot_events - Iterate over events in the ring buffer 8 9SYNOPSIS 10-------- 11[verse] 12-- 13*#include <tracefs.h>* 14 15int *tracefs_iterate_raw_events*(struct tep_handle pass:[*]_tep_, struct tracefs_instance pass:[*]_instance_, 16 cpu_set_t pass:[*]_cpus_, int _cpu_size_, 17 int (pass:[*]_callback_)(struct tep_event pass:[*], struct tep_record pass:[*], int, void pass:[*]), 18 void pass:[*]_callback_context_); 19void *tracefs_iterate_stop*(struct tracefs_instance pass:[*]_instance_); 20 21int *tracefs_follow_event*(struct tep_handle pass:[*]_tep_, struct tracefs_instance pass:[*]_instance_, 22 const char pass:[*]_system_, const char pass:[*]_event_name_, 23 int (pass:[*]_callback_)(struct tep_event pass:[*], 24 struct tep_record pass:[*], 25 int, void pass:[*]), 26 void pass:[*]_callback_data_); 27int *tracefs_follow_missed_events*(struct tracefs_instance pass:[*]_instance_, 28 int (pass:[*]_callback_)(struct tep_event pass:[*], 29 struct tep_record pass:[*], 30 int, void pass:[*]), 31 void pass:[*]_callback_data_); 32 33int *tracefs_follow_event_clear*(struct tracefs_instance pass:[*]_instance_, 34 const char pass:[*]_system_, const char pass:[*]_event_name_); 35int *tracefs_follow_missed_events_clear*(struct tracefs_instance pass:[*]_instance_); 36 37int *tracefs_iterate_snapshot_events*(struct tep_handle pass:[*]_tep_, struct tracefs_instance pass:[*]_instance_, 38 cpu_set_t pass:[*]_cpus_, int _cpu_size_, 39 int (pass:[*]_callback_)(struct tep_event pass:[*], struct tep_record pass:[*], int, void pass:[*]), 40 void pass:[*]_callback_context_); 41-- 42 43DESCRIPTION 44----------- 45Trace iterator over raw events. 46 47The *tracefs_iterate_raw_events()* function will read the tracefs raw 48data buffers and call the specified _callback_ function for every event it 49encounters. Events are iterated in sorted order: oldest first. An initialized 50_tep_ handler is required (See *tracefs_local_events*(3)). If _instance_ is 51NULL, then the toplevel tracefs buffer is used, otherwise the buffer for 52the corresponding _instance_ is read. To filter only on a subset of CPUs, 53_cpus_ and _cpu_size_ may be set to only call _callback_ with events that 54occurred on the CPUs specified, otherwise if _cpus_ is NULL then the _callback_ 55function will be called for all events, and _cpu_size_ is ignored. The 56_callback_ function will be called with the following parameters: A 57pointer to a struct tep_event that corresponds to the type of event the 58record is; The record representing the event; The CPU that the event 59occurred on; and a pointer to user specified _callback_context_. If the _callback_ 60returns non-zero, the iteration stops. 61 62The *tracefs_iterate_snapshot_events()* works the same as *tracefs_iterate_raw_events()* 63except that it works on the snapshot buffer. 64 65Use *tracefs_iterate_stop()* to force a executing *tracefs_iterate_raw_events()* 66to halt. This can be called from either a callback that is called by 67the iterator (even though a return of non-zero will stop it), or from another 68thread. 69 70The *tracefs_follow_event()* is used with *tracefs_iterate_raw_events()* but 71intead of the callback being called for every event, it is only called for the 72specified _system_ / _event_name_ given to the function. The _callback_ is the 73same as for *tracefs_iterate_raw_events()*, and the passed in _callback_context_ 74will be passed to the _callback_ as well. Note, if it returns something other 75than 0, it will stop the loop before the _callback_ of *tracefs_iterate_raw_events()* 76is called. 77 78The *tracefs_follow_missed_events()* will call the _callback_ when missed 79events are detected. It will set the _record_ parameter of the callback to the 80record that came after the missed events and _event_ will be of the type of 81event _record_ is. _cpu_ will be set to the CPU that missed the events, and 82_callback_data_ will be the content that was passed in to the function. 83 84The *tracefs_follow_event_clear()* will remove followers from _instance_ that 85match _system_ and _event_name_. If _system_ and _event_name_ are both NULL, 86then it will remove all event followers associated to _instance_. If just _system_ 87is NULL, then it will remove all followers that follow events that match _event_name_. If just _event_name_ 88is NULL, then it will remove all followers that are attached to events that are 89apart of a system that matches _system_. 90 91The *tracefs_follow_missed_events_clear()* will remove all followers for missed 92events. 93 94RETURN VALUE 95------------ 96The *tracefs_iterate_raw_events()* function returns -1 in case of an error or 970 otherwise. 98 99Both *tracefs_follow_event_clear()* and *tracefs_follow_missed_events_clear()* return 1000 on success and -1 on error, or if it found no followers that match and should be removed. 101 102EXAMPLE 103------- 104[source,c] 105-- 106#include <unistd.h> 107#include <tracefs.h> 108#include <stdbool.h> 109#include <signal.h> 110 111struct my_struct { 112 bool stopped; 113}; 114 115#define MAX_COUNT 500000 116static int counter; 117 118static int callback(struct tep_event *event, struct tep_record *record, 119 int cpu, void *data) 120{ 121 struct my_struct *my_data = data; 122 static struct trace_seq seq; 123 124 if (counter++ > MAX_COUNT) { 125 my_data->stopped = true; 126 return 1; 127 } 128 129 if (!seq.buffer) 130 trace_seq_init(&seq); 131 132 tep_print_event(event->tep, &seq, record, "%16s-%-5d [%03d] %6.1000d %s: %s\n", 133 TEP_PRINT_COMM, TEP_PRINT_PID, TEP_PRINT_CPU, 134 TEP_PRINT_TIME, TEP_PRINT_NAME, TEP_PRINT_INFO); 135 trace_seq_terminate(&seq); 136 trace_seq_do_printf(&seq); 137 trace_seq_reset(&seq); 138 return 0; 139} 140 141static int sched_callback(struct tep_event *event, struct tep_record *record, 142 int cpu, void *data) 143{ 144 static struct tep_format_field *prev_pid; 145 static struct tep_format_field *next_pid; 146 unsigned long long pid; 147 int this_pid = *(int *)data; 148 149 if (!prev_pid) { 150 prev_pid = tep_find_field(event, "prev_pid"); 151 next_pid = tep_find_field(event, "next_pid"); 152 if (!prev_pid || !next_pid) { 153 fprintf(stderr, "No pid fields??\n"); 154 return -1; 155 } 156 } 157 158 tep_read_number_field(prev_pid, record->data, &pid); 159 if (pid == this_pid) 160 printf("WE ARE LEAVING!\n"); 161 tep_read_number_field(next_pid, record->data, &pid); 162 if (pid == this_pid) 163 printf("WE ARE ARRIVING!\n"); 164 return 0; 165} 166 167static int missed_callback(struct tep_event *event, struct tep_record *record, 168 int cpu, void *data) 169{ 170 printf("OOPS! cpu %d dropped ", cpu); 171 if (record->missed_events > 0) 172 printf("%lld ", record->missed_events); 173 printf("events\n"); 174 return 0; 175} 176 177static struct tracefs_instance *instance; 178static struct my_struct my_data; 179 180static void sig(int s) 181{ 182 tracefs_iterate_stop(instance); 183 my_data.stopped = true; 184} 185 186int main (int argc, char **argv, char **env) 187{ 188 struct tep_handle *tep; 189 int this_pid = getpid(); 190 191 instance = tracefs_instance_create("my-buffer"); 192 if (!instance) 193 return -1; 194 195 signal(SIGINT, sig); 196 197 tracefs_event_enable(instance, NULL, NULL); 198 sleep(1); 199 tracefs_event_disable(instance, NULL, NULL); 200 tep = tracefs_local_events(NULL); 201 tep_load_plugins(tep); 202 tracefs_follow_missed_events(instance, missed_callback, NULL); 203 tracefs_follow_event(tep, instance, "sched", "sched_switch", sched_callback, &this_pid); 204 tracefs_iterate_raw_events(tep, instance, NULL, 0, callback, &my_data); 205 206 /* Note, the clear here is to show how to clear all followers 207 * in case tracefs_iterate_raw_events() is called again, but 208 * does not want to include the followers. It's not needed 209 * here because tracefs_instance_free() will clean them up. 210 */ 211 tracefs_follow_event_clear(instance, NULL, NULL); 212 tracefs_follow_missed_events_clear(instance); 213 214 tracefs_instance_destroy(instance); 215 tracefs_instance_free(instance); 216 217 if (my_data.stopped) { 218 if (counter > MAX_COUNT) 219 printf("Finished max count\n"); 220 else 221 printf("Finished via signal\n"); 222 } 223 224 return 0; 225} 226-- 227FILES 228----- 229[verse] 230-- 231*tracefs.h* 232 Header file to include in order to have access to the library APIs. 233*-ltracefs* 234 Linker switch to add when building a program that uses the library. 235-- 236 237SEE ALSO 238-------- 239*libtracefs*(3), 240*libtraceevent*(3), 241*trace-cmd*(1) 242 243AUTHOR 244------ 245[verse] 246-- 247*Steven Rostedt* <rostedt@goodmis.org> 248*Tzvetomir Stoyanov* <tz.stoyanov@gmail.com> 249-- 250REPORTING BUGS 251-------------- 252Report bugs to <linux-trace-devel@vger.kernel.org> 253 254LICENSE 255------- 256libtracefs is Free Software licensed under the GNU LGPL 2.1 257 258RESOURCES 259--------- 260https://git.kernel.org/pub/scm/libs/libtrace/libtracefs.git/ 261 262COPYING 263------- 264Copyright \(C) 2020 VMware, Inc. Free use of this software is granted under 265the terms of the GNU Public License (GPL). 266