tracefs_synth_alloc(3) — Linux manual page

NAME | SYNOPSIS | DESCRIPTION | RETURN VALUE | ERRORS | EXAMPLE | FILES | SEE ALSO | AUTHOR | REPORTING BUGS | LICENSE | RESOURCES | COPYING | NOTES | COLOPHON

LIBTRACEFS(3)               libtracefs Manual              LIBTRACEFS(3)

NAME         top

       tracefs_synth_alloc, tracefs_synth_add_match_field,
       tracefs_synth_add_compare_field, tracefs_synth_add_start_field,
       tracefs_synth_add_end_field, tracefs_synth_append_start_filter,
       tracefs_synth_append_end_filter, tracefs_synth_free,  - Creation
       of a synthetic event descriptor

SYNOPSIS         top

       #include <tracefs.h>

       struct tracefs_synth *tracefs_synth_alloc(struct tep_handle *tep,
                                                const char *name,
                                                const char *start_system,
                                                const char *start_event,
                                                const char *end_system,
                                                const char *end_event,
                                                const char *start_match_field,
                                                const char *end_match_field,
                                                const char *match_name);
       int tracefs_synth_add_match_field(struct tracefs_synth *synth,
                                         const char *start_match_field,
                                         const char *end_match_field,
                                         const char *name);
       int tracefs_synth_add_compare_field(struct tracefs_synth *synth,
                                           const char *start_compare_field,
                                           const char *end_compare_field,
                                           enum tracefs_synth_calc calc,
                                           const char *name);
       int tracefs_synth_add_start_field(struct tracefs_synth *synth,
                                         const char *start_field,
                                         const char *name);
       int tracefs_synth_add_end_field(struct tracefs_synth *synth,
                                       const char *end_field,
                                       const char *name);
       int tracefs_synth_append_start_filter(struct tracefs_synth *synth,
                                             struct tracefs_filter type,
                                             const char *field,
                                             enum tracefs_synth_compare compare,
                                             const char *val);
       int tracefs_synth_append_end_filter(struct tracefs_synth *synth,
                                           struct tracefs_filter type,
                                           const char *field,
                                           enum tracefs_synth_compare compare,
                                           const char *val);
       void tracefs_synth_free(struct tracefs_synth *synth);

DESCRIPTION         top

       Synthetic events are dynamic events that are created by matching
       two other events which triggers a synthetic event. One event is
       the starting event which some field is recorded, and when the
       second event is executed, if it has a field (or fields) that
       matches the starting event’s field (or fields) then it will
       trigger the synthetic event. The field values other than the
       matching fields may be passed from the starting event to the end
       event to perform calculations on, or to simply pass as a
       parameter to the synthetic event.

       One common use case is to set "sched_waking" as the starting
       event. This event is triggered when a process is awoken. Then set
       "sched_switch" as the ending event. This event is triggered when
       a new task is scheduled on the CPU. By setting the "common_pid"
       of both events as the matching fields, the time between the two
       events is considered the wake up latency of that process. Use
       TRACEFS_TIMESTAMP as a field for both events to calculate the
       delta in nanoseconds, or use *TRACEFS_TIMESTAMP_USECS" as the
       compare fields for both events to calculate the delta in
       microseconds. This is used as the example below.

       tracefs_synth_alloc() allocates and initializes a synthetic
       event. It does not create the synthetic event, but supplies the
       minimal information to do so. See tracefs_synth_create(3) for how
       to create the synthetic event in the system. It requires a tep
       handler that can be created by tracefs_local_events(3) for more
       information. The name holds the name of the synthetic event that
       will be created. The start_system is the name of the system for
       the starting event. It may be NULL and the first event with the
       name of start_event will be chosen. The end_system is the name of
       the system for theh ending event. It may be NULL and the first
       event with the name of end_event will be chosen as the ending
       event. If match_name is given, then this will be the field of the
       created synthetic event that holds the matching keys of the
       starting event’s start_match_field and the ending event’s
       end_match_field. If match_name is NULL, then it will not be
       recorded in the created synthetic event.

       tracefs_synth_add_match_field() will add a second key to match
       between the starting event and the ending event. If name is
       given, then the content of the matching field will be saved by
       this name in the synthetic event. The start_match_field is the
       field of the starting event to mach with the ending event’s
       end_match_field.

       tracefs_synth_add_compare_field() is used to compare the
       start_compare_field of the starting event with the
       end_compare_field of the ending event. The name must be given so
       that the result will be saved by the synthetic event. It makes no
       sense to not pass this to the synthetic event after doing the
       work of the compared fields, as it serves no other purpose. The
       calc parameter can be one of:

       TRACEFS_SYNTH_DELTA_END - calculate the difference between the
       content in the end_compare_field from the content of the
       start_compare_field.

       name = end_compare_field - start_compare_field

       TRACEFS_SYNTH_DELTA_START - calculate the difference between the
       content in the start_compare_field from the content of the
       end_compare_field.

       name = start_compare_field - end_compare_field

       TRACEFS_SYNTH_ADD - Add the content of the start_compare_field to
       the content of the end_compare_field.

       name = start_compare_field + end_compare_field

       tracefs_synth_add_start_field() - Records the start_field of the
       starting event as name in the synthetic event. If name is NULL,
       then the name used will be the same as start_field.

       tracefs_synth_add_end_field() - Records the end_field of the
       ending event as name in the synthetic event. If name is NULL,
       then the name used will be the same as end_field.

       tracefs_synth_append_start_filter() creates a filter or appends
       to it for the starting event. Depending on type, it will build a
       string of tokens for parenthesis or logic statements, or it may
       add a comparison of field to val based on compare.

       If type is: TRACEFS_FILTER_COMPARE - See below TRACEFS_FILTER_AND
       - Append "&&" to the filter TRACEFS_FILTER_OR - Append "||" to
       the filter TRACEFS_FILTER_NOT - Append "!" to the filter
       TRACEFS_FILTER_OPEN_PAREN - Append "(" to the filter
       TRACEFS_FILTER_CLOSE_PAREN - Append ")" to the filter

       field, compare, and val are ignored unless type is equal to
       TRACEFS_FILTER_COMPARE, then _compare will be used for the
       following:

       TRACEFS_COMPARE_EQ - field == val

       TRACEFS_COMPARE_NE - field != val

       TRACEFS_COMPARE_GT - field > val

       TRACEFS_COMPARE_GE - field >= val

       TRACEFS_COMPARE_LT - field < val

       TRACEFS_COMPARE_LE - field <= val

       TRACEFS_COMPARE_RE - field ~ "val" : where field is a string.

       TRACEFS_COMPARE_AND - field & val : where field is a flags field.

       tracefs_synth_append_end_filter() is the same as
       tracefs_synth_append_start_filter but filters on the ending
       event.

       tracefs_synth_free() frees the allocated descriptor returned by
       tracefs_synth_alloc().

RETURN VALUE         top

       tracefs_synth_alloc() returns an allocated struct tracefs_synth
       descriptor on success or NULL on error.

       All other functions that return an integer returns zero on
       success or -1 on error.

ERRORS         top

       The following errors are for all the above calls:

       EPERM Not run as root user when required.

       EINVAL Either a parameter is not valid (NULL when it should not
       be) or a field that is not compatible for calculations.

       ENODEV An event or one of its fields is not found.

       EBADE The fields of the start and end events are not compatible
       for either matching or comparing.

       ENOMEM not enough memory is available.

       And more errors may have happened from the system calls to the
       system.

EXAMPLE         top

           #include <stdlib.h>
           #include <tracefs.h>

           #define start_event "sched_waking"
           #define start_field "pid"

           #define end_event "sched_switch"
           #define end_field "next_pid"

           #define match_name "pid"

           static struct tracefs_synth *synth;

           static void make_event(void)
           {
                   struct tep_handle *tep;

                   /* Load all events from the system */
                   tep = tracefs_local_events(NULL);

                   /* Initialize the synthetic event */
                   synth = tracefs_synth_alloc(tep, "wakeup_lat",
                                               NULL, start_event,
                                               NULL, end_event,
                                               start_field, end_field,
                                               match_name);

                   /* The tep is no longer needed */
                   tep_free(tep);

                   /* Save the "prio" field as "prio" from the start event */
                   tracefs_synth_add_start_field(synth, "prio", NULL);

                   /* Save the "next_comm" as "comm" from the end event */
                   tracefs_synth_add_end_field(synth, "next_comm", "comm");

                   /* Save the "prev_prio" as "prev_prio" from the end event */
                   tracefs_synth_add_end_field(synth, "prev_prio", NULL);

                   /*
                    * Take a microsecond time difference between end and start
                    * and record as "delta"
                    */
                   tracefs_synth_add_compare_field(synth, TRACEFS_TIMESTAMP_USECS,
                                                   TRACEFS_TIMESTAMP_USECS,
                                                   TRACEFS_SYNTH_DELTA_END, "delta");

                   /* Only record if start event "prio" is less than 100 */
                   tracefs_synth_append_start_filter(synth, TRACEFS_FILTER_COMPARE,
                                                     "prio", TRACEFS_COMPARE_LT, "100");

                   /*
                    * Only record if end event "next_prio" is less than 50
                    * or the previous task's prio was not greater than or equal to 100.
                    *   next_prio < 50 || !(prev_prio >= 100)
                    */
                   tracefs_synth_append_end_filter(synth, TRACEFS_FILTER_COMPARE,
                                                   "next_prio", TRACEFS_COMPARE_LT, "50");
                   tracefs_synth_append_end_filter(synth, TRACEFS_FILTER_OR, NULL, 0, NULL);
                   tracefs_synth_append_end_filter(synth, TRACEFS_FILTER_NOT, NULL, 0, NULL);
                   tracefs_synth_append_end_filter(synth, TRACEFS_FILTER_OPEN_PAREN, NULL, 0, NULL);
                   tracefs_synth_append_end_filter(synth, TRACEFS_FILTER_COMPARE,
                                                   "prev_prio", TRACEFS_COMPARE_GE, "100");
                   /*
                    * Note, the above only added: "next_prio < 50 || !(prev_prio >= 100"
                    * That's because, when the synth is executed, the remaining close parenthesis
                    * will be added. That is, the string will end up being:
                    * "next_prio < 50 || !(prev_prio >= 100)" when one of tracefs_sync_create()
                    * or tracefs_sync_echo_cmd() is run.
                    */
           }

           /* Display how to create the synthetic event */
           static void show_event(void)
           {
                   struct trace_seq s;

                   trace_seq_init(&s);

                   tracefs_synth_echo_cmd(&s, synth);
                   trace_seq_terminate(&s);
                   trace_seq_do_printf(&s);
                   trace_seq_destroy(&s);
           }

           int main (int argc, char **argv)
           {
                   make_event();

                   if (argc > 1) {
                           if (!strcmp(argv[1], "create")) {
                                   /* Create the synthetic event */
                                   tracefs_synth_create(synth);
                           } else if (!strcmp(argv[1], "delete")) {
                                   /* Delete the synthetic event */
                                   tracefs_synth_destroy(synth);
                           } else {
                                   printf("usage: %s [create|delete]\n", argv[0]);
                                   exit(-1);
                           }
                   } else
                           show_event();

                   tracefs_synth_free(synth);

                   return 0;
           }

FILES         top

           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         top

       tracefs_synth_create(3), tracefs_synth_destroy(3),
       tracfes_synth_echo_cmd(3), libtracefs(3), libtraceevent(3),
       trace-cmd(1), tracefs_hist_alloc(3), tracefs_hist_alloc_2d(3),
       tracefs_hist_alloc_nd(3), tracefs_hist_free(3),
       tracefs_hist_add_key(3), tracefs_hist_add_value(3),
       tracefs_hist_add_name(3), tracefs_hist_start(3),
       tracefs_hist_destory(3), tracefs_hist_add_sort_key(3),
       tracefs_hist_sort_key_direction(3), tracefs_synth_create(3),
       tracefs_synth_destroy(3), tracefs_synth_complete(3),
       tracefs_synth_trace(3), tracefs_synth_snapshot(3),
       tracefs_synth_save(3), tracefs_synth_echo_cmd(3),
       tracefs_synth_get_start_hist(3), tracefs_synth_get_name(3),
       tracefs_synth_raw_fmt(3), tracefs_synth_show_event(3),
       tracefs_synth_show_start_hist(3), tracefs_synth_show_end_hist(3),
       tracefs_synth_get_event(3),

AUTHOR         top

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

REPORTING BUGS         top

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

LICENSE         top

       libtracefs is Free Software licensed under the GNU LGPL 2.1

RESOURCES         top

       https://git.kernel.org/pub/scm/libs/libtrace/libtracefs.git/ 

COPYING         top

       Copyright (C) 2020 VMware, Inc. Free use of this software is
       granted under the terms of the GNU Public License (GPL).

NOTES         top

        1. rostedt@goodmis.org
           mailto:rostedt@goodmis.org

        2. tz.stoyanov@gmail.com
           mailto:tz.stoyanov@gmail.com

        3. sameeruddin.shaik8@gmail.com
           mailto:sameeruddin.shaik8@gmail.com

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

COLOPHON         top

       This page is part of the libtracefs (Linux kernel trace file
       system library) project.  Information about the project can be
       found at ⟨https://www.trace-cmd.org/⟩.  If you have a bug report
       for this manual page, see ⟨https://www.trace-cmd.org/⟩.  This
       page was obtained from the project's upstream Git repository
       ⟨https://git.kernel.org/pub/scm/libs/libtrace/libtracefs.git⟩ on
       2023-12-22.  (At that time, the date of the most recent commit
       that was found in the repository was 2023-07-05.)  If you
       discover any rendering problems in this HTML version of the page,
       or you believe there is a better or more up-to-date source for
       the page, or you have corrections or improvements to the
       information in this COLOPHON (which is not part of the original
       manual page), send a mail to man-pages@man7.org

libtracefs 1.7.0               12/22/2023                  LIBTRACEFS(3)

Pages that refer to this page: tracefs_sql(3)tracefs_synth_create(3)tracefs_synth_echo_cmd(3)