Provided by: libtracefs-doc_1.6.4-1ubuntu1_all bug

NAME

       tracefs_iterate_raw_events, tracefs_iterate_stop, tracefs_follow_event,
       tracefs_follow_missed_events - Iterate over events in the ring buffer

SYNOPSIS

       #include <tracefs.h>

       int tracefs_iterate_raw_events(struct tep_handle *tep, struct tracefs_instance *instance,
                                        cpu_set_t *cpus, int cpu_size,
                                        int (*callback)(struct tep_event *, struct tep_record *, int, void *),
                                        void *callback_context);
       void tracefs_iterate_stop(struct tracefs_instance *instance);

       int tracefs_follow_event(struct tep_handle *tep, struct tracefs_instance *instance,
                                 const char *system, const char *event_name,
                                 int (*callback)(struct tep_event *,
                                                 struct tep_record *,
                                                 int, void *),
                                 void *callback_data);
       int tracefs_follow_missed_events(struct tracefs_instance *instance,
                                 int (*callback)(struct tep_event *,
                                                 struct tep_record *,
                                                 int, void *),
                                 void *callback_data);

DESCRIPTION

       Trace iterator over raw events.

       The tracefs_iterate_raw_events() function will read the tracefs raw data buffers and call
       the specified callback function for every event it encounters. Events are iterated in
       sorted order: oldest first. An initialized tep handler is required (See
       tracefs_local_events(3)). If instance is NULL, then the toplevel tracefs buffer is used,
       otherwise the buffer for the corresponding instance is read. To filter only on a subset of
       CPUs, cpus and cpu_size may be set to only call callback with events that occurred on the
       CPUs specified, otherwise if cpus is NULL then the callback function will be called for
       all events, and cpu_size is ignored. The callback function will be called with the
       following parameters: A pointer to a struct tep_event that corresponds to the type of
       event the record is; The record representing the event; The CPU that the event occurred
       on; and a pointer to user specified callback_context. If the callback returns non-zero,
       the iteration stops.

       Use tracefs_iterate_stop() to force a executing tracefs_iterate_raw_events() to halt. This
       can be called from either a callback that is called by the iterator (even though a return
       of non-zero will stop it), or from another thread.

       The tracefs_follow_event() is used with tracefs_iterate_raw_events() but intead of the
       callback being called for every event, it is only called for the specified system /
       event_name given to the function. The callback is the same as for
       tracefs_iterate_raw_events(), and the passed in callback_context will be passed to the
       callback as well. Note, if it returns something other than 0, it will stop the loop before
       the callback of tracefs_iterate_raw_events() is called.

       The tracefs_follow_missed_events() will call the callback when missed events are detected.
       It will set the record parameter of the callback to the record that came after the missed
       events and event will be of the type of event record is. cpu will be set to the CPU that
       missed the events, and callback_data will be the content that was passed in to the
       function.

RETURN VALUE

       The tracefs_iterate_raw_events() function returns -1 in case of an error or 0 otherwise.

EXAMPLE

           #include <unistd.h>
           #include <tracefs.h>
           #include <stdbool.h>
           #include <signal.h>

           struct my_struct {
                   bool            stopped;
           };

           #define MAX_COUNT 500000
           static int counter;

           static int callback(struct tep_event *event, struct tep_record *record,
                               int cpu, void *data)
           {
                   struct my_struct *my_data = data;
                   static struct trace_seq seq;

                   if (counter++ > MAX_COUNT) {
                           my_data->stopped = true;
                           return 1;
                   }

                   if (!seq.buffer)
                           trace_seq_init(&seq);

                   tep_print_event(event->tep, &seq, record, "%16s-%-5d [%03d] %6.1000d %s: %s\n",
                                   TEP_PRINT_COMM, TEP_PRINT_PID, TEP_PRINT_CPU,
                                   TEP_PRINT_TIME, TEP_PRINT_NAME, TEP_PRINT_INFO);
                   trace_seq_terminate(&seq);
                   trace_seq_do_printf(&seq);
                   trace_seq_reset(&seq);
                   return 0;
           }

           static int sched_callback(struct tep_event *event, struct tep_record *record,
                                     int cpu, void *data)
           {
                   static struct tep_format_field *prev_pid;
                   static struct tep_format_field *next_pid;
                   unsigned long long pid;
                   int this_pid = *(int *)data;

                   if (!prev_pid) {
                           prev_pid = tep_find_field(event, "prev_pid");
                           next_pid = tep_find_field(event, "next_pid");
                           if (!prev_pid || !next_pid) {
                                   fprintf(stderr, "No pid fields??\n");
                                   return -1;
                           }
                   }

                   tep_read_number_field(prev_pid, record->data, &pid);
                   if (pid == this_pid)
                           printf("WE ARE LEAVING!\n");
                   tep_read_number_field(next_pid, record->data, &pid);
                   if (pid == this_pid)
                           printf("WE ARE ARRIVING!\n");
                   return 0;
           }

           static int missed_callback(struct tep_event *event, struct tep_record *record,
                                      int cpu, void *data)
           {
                   printf("OOPS! cpu %d dropped ", cpu);
                   if (record->missed_events > 0)
                           printf("%lld ", record->missed_events);
                   printf("events\n");
                   return 0;
           }

           static struct tracefs_instance *instance;
           static struct my_struct my_data;

           static void sig(int s)
           {
                   tracefs_iterate_stop(instance);
                   my_data.stopped = true;
           }

           int main (int argc, char **argv, char **env)
           {
                   struct tep_handle *tep;
                   int this_pid = getpid();

                   instance = tracefs_instance_create("my-buffer");
                   if (!instance)
                           return -1;

                   signal(SIGINT, sig);

                   tracefs_event_enable(instance, NULL, NULL);
                   sleep(1);
                   tracefs_event_disable(instance, NULL, NULL);
                   tep = tracefs_local_events(NULL);
                   tep_load_plugins(tep);
                   tracefs_follow_missed_events(instance, missed_callback, NULL);
                   tracefs_follow_event(tep, instance, "sched", "sched_switch", sched_callback, &this_pid);
                   tracefs_iterate_raw_events(tep, instance, NULL, 0, callback, &my_data);
                   tracefs_instance_destroy(instance);

                   if (my_data.stopped) {
                           if (counter > MAX_COUNT)
                                   printf("Finished max count\n");
                           else
                                   printf("Finished via signal\n");
                   }

                   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

       libtracefs(3), libtraceevent(3), trace-cmd(1)

AUTHOR

           Steven Rostedt <rostedt@goodmis.org[1]>
           Tzvetomir Stoyanov <tz.stoyanov@gmail.com[2]>

REPORTING BUGS

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

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) 2020 VMware, 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. tz.stoyanov@gmail.com
           mailto:tz.stoyanov@gmail.com

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