1libtracefs(3) 2============= 3 4NAME 5---- 6tracefs_synth_echo_cmd, tracefs_synth_get_start_hist, tracefs_synth_get_name, 7tracefs_synth_raw_fmt, tracefs_synth_show_event, tracefs_synth_show_start_hist, tracefs_synth_show_end_hist, 8tracefs_synth_get_event - Retrieve data of synthetic events. 9 10SYNOPSIS 11-------- 12[verse] 13-- 14*#include <tracefs.h>* 15 16int *tracefs_synth_echo_cmd*(struct trace_seq pass:[*]_seq_, struct tracefs_synth pass:[*]_synth_); 17struct tracefs_hist pass:[*]*tracefs_synth_get_start_hist*(struct tracefs_synth pass:[*]_synth_); 18 19const char pass:[*]*tracefs_synth_get_name*(struct tracefs_synth pass:[*]_synth_); 20int *tracefs_synth_raw_fmt*(struct trace_seq pass:[*]_seq_, struct tracefs_synth pass:[*]_synth_); 21const char pass:[*]*tracefs_synth_show_event*(struct tracefs_synth pass:[*]_synth_); 22const char pass:[*]*tracefs_synth_show_start_hist*(struct tracefs_synth pass:[*]_synth_); 23const char pass:[*]*tracefs_synth_show_end_hist*(struct tracefs_synth pass:[*]_synth_); 24struct tep_event pass:[*]*tracefs_synth_get_event*(struct tep_handle pass:[*]_tep_, struct tracefs_synth pass:[*]_synth_); 25 26-- 27 28DESCRIPTION 29----------- 30Synthetic events are dynamic events that are created by matching 31two other events which triggers a synthetic event. One event is the starting 32event which some field is recorded, and when the second event is executed, 33if it has a field (or fields) that matches the starting event's field (or fields) 34then it will trigger the synthetic event. The field values other than the matching 35fields may be passed from the starting event to the end event to perform calculations 36on, or to simply pass as a parameter to the synthetic event. 37 38One common use case is to set "sched_waking" as the starting event. This event is 39triggered when a process is awoken. Then set "sched_switch" as the ending event. 40This event is triggered when a new task is scheduled on the CPU. By setting 41the "common_pid" of both events as the matching fields, the time between the 42two events is considered the wake up latency of that process. Use *TRACEFS_TIMESTAMP* 43as a field for both events to calculate the delta in nanoseconds, or use 44*TRACEFS_TIMESTAMP_USECS* as the compare fields for both events to calculate the 45delta in microseconds. This is used as the example below. 46 47See *tracefs_synth_alloc*(3) for allocation of synthetic events, and 48*tracefs_synth_create*() for creating the synthetic event on the system. 49 50*tracefs_synth_echo_cmd*() acts like *tracefs_synth_create*(), but instead of creating 51the synthetic event in the system, it will write the echo commands to manually create 52it in the _seq_ given. 53 54*tracefs_synth_get_start_hist*() returns a struct tracefs_hist descriptor describing 55the histogram used to create the synthetic event. 56 57[verse] 58-- 59enum tracefs_synth_handler { 60 *TRACEFS_SYNTH_HANDLE_MATCH*, 61 *TRACEFS_SYNTH_HANDLE_MAX*, 62 *TRACEFS_SYNTH_HANDLE_CHANGE*, 63}; 64-- 65 66*tracefs_synth_get_name*() returns the name of the synthetic event or NULL on error. 67The returned string belongs to the synth event object and is freed with the event 68by *tracefs_synth_free*(). 69 70*tracefs_synth_raw_fmt*() writes the raw format strings (dynamic event and histograms) of 71the synthetic event in the _seq_ given. 72 73*tracefs_synth_show_event*() returns the format of the dynamic event used by the synthetic 74event or NULL on error. The returned string belongs to the synth event object and is freed 75with the event by *tracefs_synth_free*(). 76 77*tracefs_synth_show_start_hist*() returns the format of the start histogram used by the 78synthetic event or NULL on error. The returned string belongs to the synth event object 79and is freed with the event by *tracefs_synth_free*(). 80 81*tracefs_synth_show_end_hist*() returns the format of the end histogram used by the 82synthetic event or NULL on error. The returned string belongs to the synth event object 83and is freed with the event by *tracefs_synth_free*(). 84 85The *tracefs_synth_get_event*() function returns a tep event, describing the given synthetic 86event. The API detects any newly created or removed dynamic events. The returned pointer to 87tep event is controlled by @tep and must not be freed. 88 89RETURN VALUE 90------------ 91*tracefs_synth_get_name*(), *tracefs_synth_show_event*(), *tracefs_synth_show_start_hist*() 92and *tracefs_synth_show_end_hist*() return a string owned by the synth event object. 93 94The *tracefs_synth_get_event*() function returns a pointer to a tep event or NULL in case of an 95error or if the requested synthetic event is missing. The returned pointer to tep event is 96controlled by @tep and must not be freed. 97 98All other functions return zero on success or -1 on error. 99 100ERRORS 101------ 102The following errors are for all the above calls: 103 104*EPERM* Not run as root user when required. 105 106*EINVAL* Either a parameter is not valid (NULL when it should not be) 107 or a field that is not compatible for calculations. 108 109*ENODEV* An event or one of its fields is not found. 110 111*EBADE* The fields of the start and end events are not compatible for 112 either matching or comparing. 113 114*ENOMEM* not enough memory is available. 115 116And more errors may have happened from the system calls to the system. 117 118EXAMPLE 119------- 120See *tracefs_sql*(3) for a more indepth use of some of this code. 121 122[source,c] 123-- 124#include <stdlib.h> 125#include <tracefs.h> 126 127#define start_event "sched_waking" 128#define start_field "pid" 129 130#define end_event "sched_switch" 131#define end_field "next_pid" 132 133#define match_name "pid" 134 135static struct tracefs_synth *synth; 136 137static void make_event(void) 138{ 139 struct tep_handle *tep; 140 141 /* Load all events from the system */ 142 tep = tracefs_local_events(NULL); 143 144 /* Initialize the synthetic event */ 145 synth = tracefs_synth_alloc(tep, "wakeup_lat", 146 NULL, start_event, 147 NULL, end_event, 148 start_field, end_field, 149 match_name); 150 151 /* The tep is no longer needed */ 152 tep_free(tep); 153 154 155 /* Save the "prio" field as "prio" from the start event */ 156 tracefs_synth_add_start_field(synth, "prio", NULL); 157 158 /* Save the "next_comm" as "comm" from the end event */ 159 tracefs_synth_add_end_field(synth, "next_comm", "comm"); 160 161 /* Save the "prev_prio" as "prev_prio" from the end event */ 162 tracefs_synth_add_end_field(synth, "prev_prio", NULL); 163 164 /* 165 * Take a microsecond time difference between end and start 166 * and record as "delta" 167 */ 168 tracefs_synth_add_compare_field(synth, TRACEFS_TIMESTAMP_USECS, 169 TRACEFS_TIMESTAMP_USECS, 170 TRACEFS_SYNTH_DELTA_END, "delta"); 171 172 /* Only record if start event "prio" is less than 100 */ 173 tracefs_synth_append_start_filter(synth, TRACEFS_FILTER_COMPARE, 174 "prio", TRACEFS_COMPARE_LT, "100"); 175 176 /* 177 * Only record if end event "next_prio" is less than 50 178 * or the previous task's prio was not greater than or equal to 100. 179 * next_prio < 50 || !(prev_prio >= 100) 180 */ 181 tracefs_synth_append_end_filter(synth, TRACEFS_FILTER_COMPARE, 182 "next_prio", TRACEFS_COMPARE_LT, "50"); 183 tracefs_synth_append_end_filter(synth, TRACEFS_FILTER_OR, NULL, 0, NULL); 184 tracefs_synth_append_end_filter(synth, TRACEFS_FILTER_NOT, NULL, 0, NULL); 185 tracefs_synth_append_end_filter(synth, TRACEFS_FILTER_OPEN_PAREN, NULL, 0, NULL); 186 tracefs_synth_append_end_filter(synth, TRACEFS_FILTER_COMPARE, 187 "prev_prio", TRACEFS_COMPARE_GE, "100"); 188 /* 189 * Note, the above only added: "next_prio < 50 || !(prev_prio >= 100" 190 * That's because, when the synth is executed, the remaining close parenthesis 191 * will be added. That is, the string will end up being: 192 * "next_prio < 50 || !(prev_prio >= 100)" when one of tracefs_sync_create() 193 * or tracefs_sync_echo_cmd() is run. 194 */ 195} 196 197/* Display how to create the synthetic event */ 198static void show_event(void) 199{ 200 struct trace_seq s; 201 202 trace_seq_init(&s); 203 204 tracefs_synth_echo_cmd(&s, synth); 205 trace_seq_terminate(&s); 206 trace_seq_do_printf(&s); 207 trace_seq_destroy(&s); 208} 209 210int main (int argc, char **argv) 211{ 212 make_event(); 213 214 if (argc > 1) { 215 if (!strcmp(argv[1], "create")) { 216 /* Create the synthetic event */ 217 tracefs_synth_create(synth); 218 } else if (!strcmp(argv[1], "delete")) { 219 /* Delete the synthetic event */ 220 tracefs_synth_destroy(synth); 221 } else { 222 printf("usage: %s [create|delete]\n", argv[0]); 223 exit(-1); 224 } 225 } else 226 show_event(); 227 228 tracefs_synth_free(synth); 229 230 return 0; 231} 232-- 233 234FILES 235----- 236[verse] 237-- 238*tracefs.h* 239 Header file to include in order to have access to the library APIs. 240*-ltracefs* 241 Linker switch to add when building a program that uses the library. 242-- 243 244SEE ALSO 245-------- 246*libtracefs*(3), 247*libtraceevent*(3), 248*trace-cmd*(1), 249*tracefs_hist_alloc*(3), 250*tracefs_hist_alloc_2d*(3), 251*tracefs_hist_alloc_nd*(3), 252*tracefs_hist_free*(3), 253*tracefs_hist_add_key*(3), 254*tracefs_hist_add_value*(3), 255*tracefs_hist_add_name*(3), 256*tracefs_hist_start*(3), 257*tracefs_hist_destory*(3), 258*tracefs_hist_add_sort_key*(3), 259*tracefs_hist_sort_key_direction*(3), 260*tracefs_synth_alloc*(3), 261*tracefs_synth_add_match_field*(3), 262*tracefs_synth_add_compare_field*(3), 263*tracefs_synth_add_start_field*(3), 264*tracefs_synth_add_end_field*(3), 265*tracefs_synth_append_start_filter*(3), 266*tracefs_synth_append_end_filter*(3), 267*tracefs_synth_free*(3), 268*tracefs_synth_create*(3), 269*tracefs_synth_destroy*(3), 270*tracefs_synth_complete*(3), 271*tracefs_synth_trace*(3), 272*tracefs_synth_snapshot*(3), 273*tracefs_synth_save*(3), 274 275AUTHOR 276------ 277[verse] 278-- 279*Steven Rostedt* <[email protected]> 280*Tzvetomir Stoyanov* <[email protected]> 281*sameeruddin shaik* <[email protected]> 282-- 283REPORTING BUGS 284-------------- 285Report bugs to <[email protected]> 286 287LICENSE 288------- 289libtracefs is Free Software licensed under the GNU LGPL 2.1 290 291RESOURCES 292--------- 293https://git.kernel.org/pub/scm/libs/libtrace/libtracefs.git/ 294 295COPYING 296------- 297Copyright \(C) 2020 VMware, Inc. Free use of this software is granted under 298the terms of the GNU Public License (GPL). 299