---
name: "tracefs_follow_event"
section: "3"
platform: "linux"
package: "libtracefs-doc"
version: "1.8.1-1"
release: "Debian 13 (Trixie)"
platforms: ["linux"]
url: "https://new.carta.tech/tracefs_iterate_raw_events"
---

# tracefs\_follow\_event(3)

Iterate over events in the ring buffer

Part of [tracefs\_iterate\_raw\_events(3)](/tracefs_iterate_raw_events/3.md).

## NAME

tracefs\_iterate\_raw\_events, tracefs\_iterate\_stop, tracefs\_follow\_event, tracefs\_follow\_missed\_events, tracefs\_follow\_event\_clear, tracefs\_follow\_missed\_events\_clear, tracefs\_iterate\_snapshot\_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);
int tracefs_follow_event_clear(struct tracefs_instance *instance,
                          const char *system, const char *event_name);
int tracefs_follow_missed_events_clear(struct tracefs_instance *instance);
int tracefs_iterate_snapshot_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);
```

## 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)](/tracefs_local_events/3.md)). 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.

The **tracefs\_iterate\_snapshot\_events()** works the same as **tracefs\_iterate\_raw\_events()** except that it works on the snapshot buffer.

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.

The **tracefs\_follow\_event\_clear()** will remove followers from *instance* that match *system* and *event\_name*. If *system* and *event\_name* are both NULL, then it will remove all event followers associated to *instance*. If just *system* is NULL, then it will remove all followers that follow events that match *event\_name*. If just *event\_name* is NULL, then it will remove all followers that are attached to events that are apart of a system that matches *system*.

The **tracefs\_follow\_missed\_events\_clear()** will remove all followers for missed events.

## RETURN VALUE

The **tracefs\_iterate\_raw\_events()** function returns -1 in case of an error or 0 otherwise.

Both **tracefs\_follow\_event\_clear()** and **tracefs\_follow\_missed\_events\_clear()** return 0 on success and -1 on error, or if it found no followers that match and should be removed.

## 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);
        /* Note, the clear here is to show how to clear all followers
         * in case tracefs_iterate_raw_events() is called again, but
         * does not want to include the followers. It's not needed
         * here because tracefs_instance_free() will clean them up.
         */
        tracefs_follow_event_clear(instance, NULL, NULL);
        tracefs_follow_missed_events_clear(instance);
        tracefs_instance_destroy(instance);
        tracefs_instance_free(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)](/libtracefs/3.md), [**libtraceevent**(3)](/libtraceevent/3.md), [**trace-cmd**(1)](/trace-cmd/1.md)

## 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
