1*287e80b3SSadaf Ebrahimilibtracefs(3) 2*287e80b3SSadaf Ebrahimi============= 3*287e80b3SSadaf Ebrahimi 4*287e80b3SSadaf EbrahimiNAME 5*287e80b3SSadaf Ebrahimi---- 6*287e80b3SSadaf Ebrahimitracefs_synth_create, tracefs_synth_destroy, tracefs_synth_complete, 7*287e80b3SSadaf Ebrahimitracefs_synth_trace, tracefs_synth_snapshot, tracefs_synth_save 8*287e80b3SSadaf Ebrahimi- Creation of synthetic events 9*287e80b3SSadaf Ebrahimi 10*287e80b3SSadaf EbrahimiSYNOPSIS 11*287e80b3SSadaf Ebrahimi-------- 12*287e80b3SSadaf Ebrahimi[verse] 13*287e80b3SSadaf Ebrahimi-- 14*287e80b3SSadaf Ebrahimi*#include <tracefs.h>* 15*287e80b3SSadaf Ebrahimi 16*287e80b3SSadaf Ebrahimiint *tracefs_synth_create*(struct tracefs_synth pass:[*]_synth_); 17*287e80b3SSadaf Ebrahimiint *tracefs_synth_destroy*(struct tracefs_synth pass:[*]_synth_); 18*287e80b3SSadaf Ebrahimibool *tracefs_synth_complete*(struct tracefs_synth pass:[*]_synth_); 19*287e80b3SSadaf Ebrahimi 20*287e80b3SSadaf Ebrahimiint *tracefs_synth_trace*(struct tracefs_synth pass:[*]_synth_, 21*287e80b3SSadaf Ebrahimi enum tracefs_synth_handler _type_, const char pass:[*]_var_); 22*287e80b3SSadaf Ebrahimiint *tracefs_synth_snapshot*(struct tracefs_synth pass:[*]_synth_, 23*287e80b3SSadaf Ebrahimi enum tracefs_synth_handler _type_, const char pass:[*]_var_); 24*287e80b3SSadaf Ebrahimiint *tracefs_synth_save*(struct tracefs_synth pass:[*]_synth_, 25*287e80b3SSadaf Ebrahimi enum tracefs_synth_handler _type_, const char pass:[*]_var_, 26*287e80b3SSadaf Ebrahimi char pass:[**]_save_fields_); 27*287e80b3SSadaf Ebrahimi-- 28*287e80b3SSadaf Ebrahimi 29*287e80b3SSadaf EbrahimiDESCRIPTION 30*287e80b3SSadaf Ebrahimi----------- 31*287e80b3SSadaf EbrahimiSynthetic events are dynamic events that are created by matching 32*287e80b3SSadaf Ebrahimitwo other events which triggers a synthetic event. One event is the starting 33*287e80b3SSadaf Ebrahimievent which some field is recorded, and when the second event is executed, 34*287e80b3SSadaf Ebrahimiif it has a field (or fields) that matches the starting event's field (or fields) 35*287e80b3SSadaf Ebrahimithen it will trigger the synthetic event. The field values other than the matching 36*287e80b3SSadaf Ebrahimifields may be passed from the starting event to the end event to perform calculations 37*287e80b3SSadaf Ebrahimion, or to simply pass as a parameter to the synthetic event. 38*287e80b3SSadaf Ebrahimi 39*287e80b3SSadaf EbrahimiOne common use case is to set "sched_waking" as the starting event. This event is 40*287e80b3SSadaf Ebrahimitriggered when a process is awoken. Then set "sched_switch" as the ending event. 41*287e80b3SSadaf EbrahimiThis event is triggered when a new task is scheduled on the CPU. By setting 42*287e80b3SSadaf Ebrahimithe "common_pid" of both events as the matching fields, the time between the 43*287e80b3SSadaf Ebrahimitwo events is considered the wake up latency of that process. Use *TRACEFS_TIMESTAMP* 44*287e80b3SSadaf Ebrahimias a field for both events to calculate the delta in nanoseconds, or use 45*287e80b3SSadaf Ebrahimi*TRACEFS_TIMESTAMP_USECS* as the compare fields for both events to calculate the 46*287e80b3SSadaf Ebrahimidelta in microseconds. This is used as the example below. 47*287e80b3SSadaf Ebrahimi 48*287e80b3SSadaf Ebrahimi*tracefs_synth_create*() creates the synthetic event in the system. The synthetic events apply 49*287e80b3SSadaf Ebrahimiacross all instances. A synthetic event must be created with *tracefs_synth_alloc*(3) before 50*287e80b3SSadaf Ebrahimiit can be created. 51*287e80b3SSadaf Ebrahimi 52*287e80b3SSadaf Ebrahimi*tracefs_synth_destroy*() destroys the synthetic event. It will attempt to stop the running of it in 53*287e80b3SSadaf Ebrahimiits instance (top by default), but if its running in another instance this may fail as busy. 54*287e80b3SSadaf Ebrahimi 55*287e80b3SSadaf Ebrahimi*tracefs_synth_complete*() returns true if the synthetic event _synth_ has both 56*287e80b3SSadaf Ebrahimia starting and ending event. 57*287e80b3SSadaf Ebrahimi 58*287e80b3SSadaf Ebrahimi*tracefs_synth_trace*() Instead of doing just a trace on matching of the start and 59*287e80b3SSadaf Ebrahimiend events, do the _type_ handler where *TRACEFS_SYNTH_HANDLE_MAX* will do a trace 60*287e80b3SSadaf Ebrahimiwhen the given variable _var_ hits a new max for the matching keys. Or 61*287e80b3SSadaf Ebrahimi*TRACEFS_SYNTH_HANDLE_CHANGE* for when the _var_ changes. _var_ must be one of 62*287e80b3SSadaf Ebrahimithe _name_ elements used in *tracefs_synth_add_end_field*(3). 63*287e80b3SSadaf Ebrahimi 64*287e80b3SSadaf Ebrahimi*tracefs_synth_snapshot*() When the given variable _var_ is either a new max if 65*287e80b3SSadaf Ebrahimi_handler_ is *TRACEFS_SYNTH_HANDLE_MAX* or simply changed if *TRACEFS_SYNTH_HANDLE_CHANGE* 66*287e80b3SSadaf Ebrahimithen take a "snapshot" of the buffer. The snapshot moves the normal "trace" buffer 67*287e80b3SSadaf Ebrahimiinto a "snapshot" buffer, that can be accessed via the "snapshot" file in the 68*287e80b3SSadaf Ebrahimitop level tracefs directory, or one of the instances. _var_ changes. _var_ must be one of 69*287e80b3SSadaf Ebrahimithe _name_ elements used in *tracefs_synth_add_end_field*(3). 70*287e80b3SSadaf Ebrahimi 71*287e80b3SSadaf Ebrahimi*tracefs_synth_save*() When the given variable _var_ is either a new max if 72*287e80b3SSadaf Ebrahimi_handler_ is *TRACEFS_SYNTH_HANDLE_MAX* or simpy changed if *TRACEFS_SYNTH_HANDLE_CHANGE* 73*287e80b3SSadaf Ebrahimithen save the given _save_fields_ list. The fields will be stored in the histogram 74*287e80b3SSadaf Ebrahimi"hist" file of the event that can be retrieved with *tracefs_event_file_read*(3). 75*287e80b3SSadaf Ebrahimi_var_ must be one of the _name_ elements used in *tracefs_synth_add_end_field*(3). 76*287e80b3SSadaf Ebrahimi 77*287e80b3SSadaf EbrahimiRETURN VALUE 78*287e80b3SSadaf Ebrahimi------------ 79*287e80b3SSadaf EbrahimiAll functions return zero on success or -1 on error. 80*287e80b3SSadaf Ebrahimi 81*287e80b3SSadaf EbrahimiERRORS 82*287e80b3SSadaf Ebrahimi------ 83*287e80b3SSadaf EbrahimiThe following errors are for all the above calls: 84*287e80b3SSadaf Ebrahimi 85*287e80b3SSadaf Ebrahimi*EPERM* Not run as root user when required. 86*287e80b3SSadaf Ebrahimi 87*287e80b3SSadaf Ebrahimi*EINVAL* Either a parameter is not valid (NULL when it should not be) 88*287e80b3SSadaf Ebrahimi or a field that is not compatible for calculations. 89*287e80b3SSadaf Ebrahimi 90*287e80b3SSadaf Ebrahimi*ENODEV* An event or one of its fields is not found. 91*287e80b3SSadaf Ebrahimi 92*287e80b3SSadaf Ebrahimi*EBADE* The fields of the start and end events are not compatible for 93*287e80b3SSadaf Ebrahimi either matching or comparing. 94*287e80b3SSadaf Ebrahimi 95*287e80b3SSadaf Ebrahimi*ENOMEM* not enough memory is available. 96*287e80b3SSadaf Ebrahimi 97*287e80b3SSadaf EbrahimiAnd more errors may have happened from the system calls to the system. 98*287e80b3SSadaf Ebrahimi 99*287e80b3SSadaf EbrahimiEXAMPLE 100*287e80b3SSadaf Ebrahimi------- 101*287e80b3SSadaf EbrahimiSee *tracefs_sql*(3) for a more indepth use of some of this code. 102*287e80b3SSadaf Ebrahimi 103*287e80b3SSadaf Ebrahimi[source,c] 104*287e80b3SSadaf Ebrahimi-- 105*287e80b3SSadaf Ebrahimi#include <stdlib.h> 106*287e80b3SSadaf Ebrahimi#include <tracefs.h> 107*287e80b3SSadaf Ebrahimi 108*287e80b3SSadaf Ebrahimi#define start_event "sched_waking" 109*287e80b3SSadaf Ebrahimi#define start_field "pid" 110*287e80b3SSadaf Ebrahimi 111*287e80b3SSadaf Ebrahimi#define end_event "sched_switch" 112*287e80b3SSadaf Ebrahimi#define end_field "next_pid" 113*287e80b3SSadaf Ebrahimi 114*287e80b3SSadaf Ebrahimi#define match_name "pid" 115*287e80b3SSadaf Ebrahimi 116*287e80b3SSadaf Ebrahimistatic struct tracefs_synth *synth; 117*287e80b3SSadaf Ebrahimi 118*287e80b3SSadaf Ebrahimistatic void make_event(void) 119*287e80b3SSadaf Ebrahimi{ 120*287e80b3SSadaf Ebrahimi struct tep_handle *tep; 121*287e80b3SSadaf Ebrahimi 122*287e80b3SSadaf Ebrahimi /* Load all events from the system */ 123*287e80b3SSadaf Ebrahimi tep = tracefs_local_events(NULL); 124*287e80b3SSadaf Ebrahimi 125*287e80b3SSadaf Ebrahimi /* Initialize the synthetic event */ 126*287e80b3SSadaf Ebrahimi synth = tracefs_synth_alloc(tep, "wakeup_lat", 127*287e80b3SSadaf Ebrahimi NULL, start_event, 128*287e80b3SSadaf Ebrahimi NULL, end_event, 129*287e80b3SSadaf Ebrahimi start_field, end_field, 130*287e80b3SSadaf Ebrahimi match_name); 131*287e80b3SSadaf Ebrahimi 132*287e80b3SSadaf Ebrahimi /* The tep is no longer needed */ 133*287e80b3SSadaf Ebrahimi tep_free(tep); 134*287e80b3SSadaf Ebrahimi 135*287e80b3SSadaf Ebrahimi 136*287e80b3SSadaf Ebrahimi /* Save the "prio" field as "prio" from the start event */ 137*287e80b3SSadaf Ebrahimi tracefs_synth_add_start_field(synth, "prio", NULL); 138*287e80b3SSadaf Ebrahimi 139*287e80b3SSadaf Ebrahimi /* Save the "next_comm" as "comm" from the end event */ 140*287e80b3SSadaf Ebrahimi tracefs_synth_add_end_field(synth, "next_comm", "comm"); 141*287e80b3SSadaf Ebrahimi 142*287e80b3SSadaf Ebrahimi /* Save the "prev_prio" as "prev_prio" from the end event */ 143*287e80b3SSadaf Ebrahimi tracefs_synth_add_end_field(synth, "prev_prio", NULL); 144*287e80b3SSadaf Ebrahimi 145*287e80b3SSadaf Ebrahimi /* 146*287e80b3SSadaf Ebrahimi * Take a microsecond time difference between end and start 147*287e80b3SSadaf Ebrahimi * and record as "delta" 148*287e80b3SSadaf Ebrahimi */ 149*287e80b3SSadaf Ebrahimi tracefs_synth_add_compare_field(synth, TRACEFS_TIMESTAMP_USECS, 150*287e80b3SSadaf Ebrahimi TRACEFS_TIMESTAMP_USECS, 151*287e80b3SSadaf Ebrahimi TRACEFS_SYNTH_DELTA_END, "delta"); 152*287e80b3SSadaf Ebrahimi 153*287e80b3SSadaf Ebrahimi /* Only record if start event "prio" is less than 100 */ 154*287e80b3SSadaf Ebrahimi tracefs_synth_append_start_filter(synth, TRACEFS_FILTER_COMPARE, 155*287e80b3SSadaf Ebrahimi "prio", TRACEFS_COMPARE_LT, "100"); 156*287e80b3SSadaf Ebrahimi 157*287e80b3SSadaf Ebrahimi /* 158*287e80b3SSadaf Ebrahimi * Only record if end event "next_prio" is less than 50 159*287e80b3SSadaf Ebrahimi * or the previous task's prio was not greater than or equal to 100. 160*287e80b3SSadaf Ebrahimi * next_prio < 50 || !(prev_prio >= 100) 161*287e80b3SSadaf Ebrahimi */ 162*287e80b3SSadaf Ebrahimi tracefs_synth_append_end_filter(synth, TRACEFS_FILTER_COMPARE, 163*287e80b3SSadaf Ebrahimi "next_prio", TRACEFS_COMPARE_LT, "50"); 164*287e80b3SSadaf Ebrahimi tracefs_synth_append_end_filter(synth, TRACEFS_FILTER_OR, NULL, 0, NULL); 165*287e80b3SSadaf Ebrahimi tracefs_synth_append_end_filter(synth, TRACEFS_FILTER_NOT, NULL, 0, NULL); 166*287e80b3SSadaf Ebrahimi tracefs_synth_append_end_filter(synth, TRACEFS_FILTER_OPEN_PAREN, NULL, 0, NULL); 167*287e80b3SSadaf Ebrahimi tracefs_synth_append_end_filter(synth, TRACEFS_FILTER_COMPARE, 168*287e80b3SSadaf Ebrahimi "prev_prio", TRACEFS_COMPARE_GE, "100"); 169*287e80b3SSadaf Ebrahimi /* 170*287e80b3SSadaf Ebrahimi * Note, the above only added: "next_prio < 50 || !(prev_prio >= 100" 171*287e80b3SSadaf Ebrahimi * That's because, when the synth is executed, the remaining close parenthesis 172*287e80b3SSadaf Ebrahimi * will be added. That is, the string will end up being: 173*287e80b3SSadaf Ebrahimi * "next_prio < 50 || !(prev_prio >= 100)" when one of tracefs_sync_create() 174*287e80b3SSadaf Ebrahimi * or tracefs_sync_echo_cmd() is run. 175*287e80b3SSadaf Ebrahimi */ 176*287e80b3SSadaf Ebrahimi} 177*287e80b3SSadaf Ebrahimi 178*287e80b3SSadaf Ebrahimi/* Display how to create the synthetic event */ 179*287e80b3SSadaf Ebrahimistatic void show_event(void) 180*287e80b3SSadaf Ebrahimi{ 181*287e80b3SSadaf Ebrahimi struct trace_seq s; 182*287e80b3SSadaf Ebrahimi 183*287e80b3SSadaf Ebrahimi trace_seq_init(&s); 184*287e80b3SSadaf Ebrahimi 185*287e80b3SSadaf Ebrahimi tracefs_synth_echo_cmd(&s, synth); 186*287e80b3SSadaf Ebrahimi trace_seq_terminate(&s); 187*287e80b3SSadaf Ebrahimi trace_seq_do_printf(&s); 188*287e80b3SSadaf Ebrahimi trace_seq_destroy(&s); 189*287e80b3SSadaf Ebrahimi} 190*287e80b3SSadaf Ebrahimi 191*287e80b3SSadaf Ebrahimiint main (int argc, char **argv) 192*287e80b3SSadaf Ebrahimi{ 193*287e80b3SSadaf Ebrahimi make_event(); 194*287e80b3SSadaf Ebrahimi 195*287e80b3SSadaf Ebrahimi if (argc > 1) { 196*287e80b3SSadaf Ebrahimi if (!strcmp(argv[1], "create")) { 197*287e80b3SSadaf Ebrahimi /* Create the synthetic event */ 198*287e80b3SSadaf Ebrahimi tracefs_synth_create(synth); 199*287e80b3SSadaf Ebrahimi } else if (!strcmp(argv[1], "delete")) { 200*287e80b3SSadaf Ebrahimi /* Delete the synthetic event */ 201*287e80b3SSadaf Ebrahimi tracefs_synth_destroy(synth); 202*287e80b3SSadaf Ebrahimi } else { 203*287e80b3SSadaf Ebrahimi printf("usage: %s [create|delete]\n", argv[0]); 204*287e80b3SSadaf Ebrahimi exit(-1); 205*287e80b3SSadaf Ebrahimi } 206*287e80b3SSadaf Ebrahimi } else 207*287e80b3SSadaf Ebrahimi show_event(); 208*287e80b3SSadaf Ebrahimi 209*287e80b3SSadaf Ebrahimi tracefs_synth_free(synth); 210*287e80b3SSadaf Ebrahimi 211*287e80b3SSadaf Ebrahimi return 0; 212*287e80b3SSadaf Ebrahimi} 213*287e80b3SSadaf Ebrahimi-- 214*287e80b3SSadaf Ebrahimi 215*287e80b3SSadaf EbrahimiFILES 216*287e80b3SSadaf Ebrahimi----- 217*287e80b3SSadaf Ebrahimi[verse] 218*287e80b3SSadaf Ebrahimi-- 219*287e80b3SSadaf Ebrahimi*tracefs.h* 220*287e80b3SSadaf Ebrahimi Header file to include in order to have access to the library APIs. 221*287e80b3SSadaf Ebrahimi*-ltracefs* 222*287e80b3SSadaf Ebrahimi Linker switch to add when building a program that uses the library. 223*287e80b3SSadaf Ebrahimi-- 224*287e80b3SSadaf Ebrahimi 225*287e80b3SSadaf EbrahimiSEE ALSO 226*287e80b3SSadaf Ebrahimi-------- 227*287e80b3SSadaf Ebrahimi*libtracefs*(3), 228*287e80b3SSadaf Ebrahimi*libtraceevent*(3), 229*287e80b3SSadaf Ebrahimi*trace-cmd*(1), 230*287e80b3SSadaf Ebrahimi*tracefs_hist_alloc*(3), 231*287e80b3SSadaf Ebrahimi*tracefs_hist_alloc_2d*(3), 232*287e80b3SSadaf Ebrahimi*tracefs_hist_alloc_nd*(3), 233*287e80b3SSadaf Ebrahimi*tracefs_hist_free*(3), 234*287e80b3SSadaf Ebrahimi*tracefs_hist_add_key*(3), 235*287e80b3SSadaf Ebrahimi*tracefs_hist_add_value*(3), 236*287e80b3SSadaf Ebrahimi*tracefs_hist_add_name*(3), 237*287e80b3SSadaf Ebrahimi*tracefs_hist_start*(3), 238*287e80b3SSadaf Ebrahimi*tracefs_hist_destory*(3), 239*287e80b3SSadaf Ebrahimi*tracefs_hist_add_sort_key*(3), 240*287e80b3SSadaf Ebrahimi*tracefs_hist_sort_key_direction*(3), 241*287e80b3SSadaf Ebrahimi*tracefs_synth_alloc*(3), 242*287e80b3SSadaf Ebrahimi*tracefs_synth_add_match_field*(3), 243*287e80b3SSadaf Ebrahimi*tracefs_synth_add_compare_field*(3), 244*287e80b3SSadaf Ebrahimi*tracefs_synth_add_start_field*(3), 245*287e80b3SSadaf Ebrahimi*tracefs_synth_add_end_field*(3), 246*287e80b3SSadaf Ebrahimi*tracefs_synth_append_start_filter*(3), 247*287e80b3SSadaf Ebrahimi*tracefs_synth_append_end_filter*(3), 248*287e80b3SSadaf Ebrahimi*tracefs_synth_free*(3), 249*287e80b3SSadaf Ebrahimi*tracefs_synth_echo_cmd*(3), 250*287e80b3SSadaf Ebrahimi*tracefs_synth_get_start_hist*(3), 251*287e80b3SSadaf Ebrahimi*tracefs_synth_get_name*(3), 252*287e80b3SSadaf Ebrahimi*tracefs_synth_raw_fmt*(3), 253*287e80b3SSadaf Ebrahimi*tracefs_synth_show_event*(3), 254*287e80b3SSadaf Ebrahimi*tracefs_synth_show_start_hist*(3), 255*287e80b3SSadaf Ebrahimi*tracefs_synth_show_end_hist*(3), 256*287e80b3SSadaf Ebrahimi*tracefs_synth_get_event*(3), 257*287e80b3SSadaf Ebrahimi 258*287e80b3SSadaf EbrahimiAUTHOR 259*287e80b3SSadaf Ebrahimi------ 260*287e80b3SSadaf Ebrahimi[verse] 261*287e80b3SSadaf Ebrahimi-- 262*287e80b3SSadaf Ebrahimi*Steven Rostedt* <[email protected]> 263*287e80b3SSadaf Ebrahimi*Tzvetomir Stoyanov* <[email protected]> 264*287e80b3SSadaf Ebrahimi*sameeruddin shaik* <[email protected]> 265*287e80b3SSadaf Ebrahimi-- 266*287e80b3SSadaf EbrahimiREPORTING BUGS 267*287e80b3SSadaf Ebrahimi-------------- 268*287e80b3SSadaf EbrahimiReport bugs to <[email protected]> 269*287e80b3SSadaf Ebrahimi 270*287e80b3SSadaf EbrahimiLICENSE 271*287e80b3SSadaf Ebrahimi------- 272*287e80b3SSadaf Ebrahimilibtracefs is Free Software licensed under the GNU LGPL 2.1 273*287e80b3SSadaf Ebrahimi 274*287e80b3SSadaf EbrahimiRESOURCES 275*287e80b3SSadaf Ebrahimi--------- 276*287e80b3SSadaf Ebrahimihttps://git.kernel.org/pub/scm/libs/libtrace/libtracefs.git/ 277*287e80b3SSadaf Ebrahimi 278*287e80b3SSadaf EbrahimiCOPYING 279*287e80b3SSadaf Ebrahimi------- 280*287e80b3SSadaf EbrahimiCopyright \(C) 2020 VMware, Inc. Free use of this software is granted under 281*287e80b3SSadaf Ebrahimithe terms of the GNU Public License (GPL). 282