NAME |SYNOPSIS |DESCRIPTION |RETURN VALUE |ERRORS |EXAMPLE |FILES |SEE ALSO |AUTHOR |REPORTING BUGS |LICENSE |RESOURCES |COPYING |NOTES |COLOPHON | |
LIBTRACEFS(3) libtracefs ManualLIBTRACEFS(3)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
#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); inttracefs_synth_add_match_field(struct tracefs_synth *synth, const char *start_match_field, const char *end_match_field, const char *name); inttracefs_synth_add_compare_field(struct tracefs_synth *synth, const char *start_compare_field, const char *end_compare_field, enum tracefs_synth_calccalc, const char *name); inttracefs_synth_add_start_field(struct tracefs_synth *synth, const char *start_field, const char *name); inttracefs_synth_add_end_field(struct tracefs_synth *synth, const char *end_field, const char *name); inttracefs_synth_append_start_filter(struct tracefs_synth *synth, struct tracefs_filtertype, const char *field, enum tracefs_synth_comparecompare, const char *val); inttracefs_synth_append_end_filter(struct tracefs_synth *synth, struct tracefs_filtertype, const char *field, enum tracefs_synth_comparecompare, const char *val); voidtracefs_synth_free(struct tracefs_synth *synth);
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. UseTRACEFS_TIMESTAMPas 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. Seetracefs_synth_create(3) for how to create the synthetic event in the system. It requires atep handler that can be created bytracefs_local_events(3) for more information. Thename holds the name of the synthetic event that will be created. Thestart_system is the name of the system for the starting event. It may be NULL and the first event with the name ofstart_event will be chosen. Theend_system is the name of the system for theh ending event. It may be NULL and the first event with the name ofend_event will be chosen as the ending event. Ifmatch_name is given, then this will be the field of the created synthetic event that holds the matching keys of the starting event’sstart_match_field and the ending event’send_match_field. Ifmatch_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. Ifname is given, then the content of the matching field will be saved by thisname in the synthetic event. Thestart_match_field is the field of the starting event to mach with the ending event’send_match_field.tracefs_synth_add_compare_field() is used to compare thestart_compare_field of the starting event with theend_compare_field of the ending event. Thename 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. Thecalc parameter can be one of:TRACEFS_SYNTH_DELTA_END- calculate the difference between the content in theend_compare_field from the content of thestart_compare_field.name =end_compare_field -start_compare_fieldTRACEFS_SYNTH_DELTA_START- calculate the difference between the content in thestart_compare_field from the content of theend_compare_field.name =start_compare_field -end_compare_fieldTRACEFS_SYNTH_ADD- Add the content of thestart_compare_field to the content of theend_compare_field.name =start_compare_field +end_compare_fieldtracefs_synth_add_start_field() - Records thestart_field of the starting event asname in the synthetic event. Ifname is NULL, then the name used will be the same asstart_field.tracefs_synth_add_end_field() - Records theend_field of the ending event asname in the synthetic event. Ifname is NULL, then the name used will be the same asend_field.tracefs_synth_append_start_filter() creates a filter or appends to it for the starting event. Depending ontype, it will build a string of tokens for parenthesis or logic statements, or it may add a comparison offield toval based oncompare. Iftype is:TRACEFS_FILTER_COMPARE- See belowTRACEFS_FILTER_AND - Append "&&" to the filterTRACEFS_FILTER_OR- Append "||" to the filterTRACEFS_FILTER_NOT- Append "!" to the filterTRACEFS_FILTER_OPEN_PAREN- Append "(" to the filterTRACEFS_FILTER_CLOSE_PAREN- Append ")" to the filterfield,compare, andval are ignored unlesstype is equal toTRACEFS_FILTER_COMPARE, then _compare will be used for the following:TRACEFS_COMPARE_EQ-field ==valTRACEFS_COMPARE_NE-field !=valTRACEFS_COMPARE_GT-field >valTRACEFS_COMPARE_GE-field >=valTRACEFS_COMPARE_LT-field <valTRACEFS_COMPARE_LE-field <=valTRACEFS_COMPARE_RE-field ~ "val" : wherefield is a string.TRACEFS_COMPARE_AND-field &val : wherefield is a flags field.tracefs_synth_append_end_filter() is the same astracefs_synth_append_start_filterbut filters on the ending event.tracefs_synth_free() frees the allocated descriptor returned bytracefs_synth_alloc().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.
The following errors are for all the above calls:EPERMNot run as root user when required.EINVALEither a parameter is not valid (NULL when it should not be) or a field that is not compatible for calculations.ENODEVAn event or one of its fields is not found.EBADEThe fields of the start and end events are not compatible for either matching or comparing.ENOMEMnot enough memory is available. And more errors may have happened from the system calls to the system.
#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; }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.
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),
Steven Rostedt<rostedt@goodmis.org[1]>Tzvetomir Stoyanov<tz.stoyanov@gmail.com[2]>sameeruddin shaik<sameeruddin.shaik8@gmail.com[3]>
Report bugs to <linux-trace-devel@vger.kernel.org[4]>
libtracefs is Free Software licensed under the GNU LGPL 2.1
https://git.kernel.org/pub/scm/libs/libtrace/libtracefs.git/
Copyright (C) 2020 VMware, Inc. Free use of this software is granted under the terms of the GNU Public License (GPL).
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
This page is part of thelibtracefs (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 2025-08-11. (At that time, the date of the most recent commit that was found in the repository was 2025-06-02.) 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 isnot part of the original manual page), send a mail to man-pages@man7.orglibtracefs 1.7.0 12/22/2023LIBTRACEFS(3)Pages that refer to this page:tracefs_sql(3), tracefs_synth_create(3), tracefs_synth_echo_cmd(3)
HTML rendering created 2025-09-06 byMichael Kerrisk, author ofThe Linux Programming Interface. For details of in-depthLinux/UNIX system programming training courses that I teach, lookhere. Hosting byjambit GmbH. | ![]() |