1*287e80b3SSadaf Ebrahimilibtracefs(3) 2*287e80b3SSadaf Ebrahimi============= 3*287e80b3SSadaf Ebrahimi 4*287e80b3SSadaf EbrahimiNAME 5*287e80b3SSadaf Ebrahimi---- 6*287e80b3SSadaf Ebrahimitracefs_hist_add_sort_key, tracefs_hist_set_sort_key, tracefs_hist_sort_key_direction, 7*287e80b3SSadaf Ebrahimitracefs_hist_add_name, tracefs_hist_append_filter, tracefs_hist_echo_cmd, tracefs_hist_command, 8*287e80b3SSadaf Ebrahimitracefs_hist_get_name, tracefs_hist_get_event, tracefs_hist_get_system - Update and describe an event histogram 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_hist_add_sort_key*(struct tracefs_hist pass:[*]_hist_, 17*287e80b3SSadaf Ebrahimi const char pass:[*]_sort_key_); 18*287e80b3SSadaf Ebrahimi 19*287e80b3SSadaf Ebrahimiint *tracefs_hist_set_sort_key*(struct tracefs_hist pass:[*]_hist_, 20*287e80b3SSadaf Ebrahimi const char pass:[*]_sort_key_, _..._); 21*287e80b3SSadaf Ebrahimiint *tracefs_hist_sort_key_direction*(struct tracefs_hist pass:[*]_hist_, 22*287e80b3SSadaf Ebrahimi const char pass:[*]_sort_key_, 23*287e80b3SSadaf Ebrahimi enum tracefs_hist_sort_direction _dir_); 24*287e80b3SSadaf Ebrahimi 25*287e80b3SSadaf Ebrahimiint *tracefs_hist_add_name*(struct tracefs_hist pass:[*]_hist_, const char pass:[*]_name_); 26*287e80b3SSadaf Ebrahimi 27*287e80b3SSadaf Ebrahimiint *tracefs_hist_append_filter*(struct tracefs_hist pass:[*]_hist_, 28*287e80b3SSadaf Ebrahimi enum tracefs_filter _type_, 29*287e80b3SSadaf Ebrahimi const char pass:[*]_field_, 30*287e80b3SSadaf Ebrahimi enum tracefs_compare _compare_, 31*287e80b3SSadaf Ebrahimi const char pass:[*]_val_); 32*287e80b3SSadaf Ebrahimi 33*287e80b3SSadaf Ebrahimiint *tracefs_hist_echo_cmd*(struct trace_seq pass:[*]_s_, struct tracefs_instance pass:[*]_instance_, 34*287e80b3SSadaf Ebrahimi struct tracefs_hist pass:[*]_hist_, 35*287e80b3SSadaf Ebrahimi enum tracefs_hist_command _command_); 36*287e80b3SSadaf Ebrahimi 37*287e80b3SSadaf Ebrahimiint *tracefs_hist_command*(struct tracefs_instance pass:[*]_instance_, 38*287e80b3SSadaf Ebrahimi struct tracefs_hist pass:[*]_hist_, 39*287e80b3SSadaf Ebrahimi enum tracefs_hist_command _command_); 40*287e80b3SSadaf Ebrahimi 41*287e80b3SSadaf Ebrahimiconst char pass:[*]*tracefs_hist_get_name*(struct tracefs_hist pass:[*]_hist_); 42*287e80b3SSadaf Ebrahimi 43*287e80b3SSadaf Ebrahimiconst char pass:[*]*tracefs_hist_get_event*(struct tracefs_hist pass:[*]_hist_); 44*287e80b3SSadaf Ebrahimi 45*287e80b3SSadaf Ebrahimiconst char pass:[*]*tracefs_hist_get_system*(struct tracefs_hist pass:[*]_hist_); 46*287e80b3SSadaf Ebrahimi 47*287e80b3SSadaf Ebrahimi-- 48*287e80b3SSadaf Ebrahimi 49*287e80b3SSadaf EbrahimiDESCRIPTION 50*287e80b3SSadaf Ebrahimi----------- 51*287e80b3SSadaf EbrahimiEvent histograms are created by the trigger file in the event directory. 52*287e80b3SSadaf EbrahimiThe syntax can be complex and difficult to get correct. This API handles the 53*287e80b3SSadaf Ebrahimisyntax, and facilitates the creation and interaction with the event histograms. 54*287e80b3SSadaf EbrahimiSee https://www.kernel.org/doc/html/latest/trace/histogram.html for more information. 55*287e80b3SSadaf Ebrahimi 56*287e80b3SSadaf Ebrahimi*tracefs_hist_add_sort_key*() will add a key to sort on. The _hist_ is the 57*287e80b3SSadaf Ebrahimihistogram descriptor to add the sort key to. The _sort_key_ is a string 58*287e80b3SSadaf Ebrahimithat must match either an already defined key of the histogram, or an already 59*287e80b3SSadaf Ebrahimidefined value. If _hist_ already has sorting keys (previously added) the new 60*287e80b3SSadaf Ebrahimi_sort_key_ will have lower priority(be secondary or so on) when sorting. 61*287e80b3SSadaf Ebrahimi 62*287e80b3SSadaf Ebrahimi*tracefs_hist_set_sort_key*() will reset the list of key to sort on. The _hist_ is 63*287e80b3SSadaf Ebrahimithe histogram descriptor to reset the sort key to. The _sort_key_ is a string 64*287e80b3SSadaf Ebrahimithat must match either an already defined key of the histogram, or an already 65*287e80b3SSadaf Ebrahimidefined value. Multiple sort keys may be added to denote a secondary, sort order 66*287e80b3SSadaf Ebrahimiand so on, but all sort keys must match an existing key or value, or be 67*287e80b3SSadaf EbrahimiTRACEFS_HIST_HITCOUNT. The last parameter of *tracefs_hist_add_sort_key*() must 68*287e80b3SSadaf Ebrahimibe NULL. 69*287e80b3SSadaf Ebrahimi 70*287e80b3SSadaf Ebrahimi*tracefs_hist_sort_key_direction*() allows to change the direction of an 71*287e80b3SSadaf Ebrahimiexisting sort key of _hist_. The _sort_key_ is the sort key to change, and 72*287e80b3SSadaf Ebrahimi_dir_ can be either TRACEFS_HIST_SORT_ASCENDING or TRACEFS_HIST_SORT_DESCENDING, 73*287e80b3SSadaf Ebrahimito make the direction of the sort key either ascending or descending respectively. 74*287e80b3SSadaf Ebrahimi 75*287e80b3SSadaf Ebrahimi*tracefs_hist_add_name*() adds a name to a histogram. A histogram may be 76*287e80b3SSadaf Ebrahiminamed and if the name matches between more than one event, and they have 77*287e80b3SSadaf Ebrahimicompatible keys, the multiple histograms with the same name will be merged 78*287e80b3SSadaf Ebrahimiinto a single histogram (shown by either event's hist file). The _hist_ 79*287e80b3SSadaf Ebrahimiis the histogram to name, and the _name_ is the name to give it. 80*287e80b3SSadaf Ebrahimi 81*287e80b3SSadaf Ebrahimi*tracefs_hist_append_filter*() creates a filter or appends to it for the 82*287e80b3SSadaf Ebrahimihistogram event. Depending on _type_, it will build a string of tokens for 83*287e80b3SSadaf Ebrahimiparenthesis or logic statements, or it may add a comparison of _field_ 84*287e80b3SSadaf Ebrahimito _val_ based on _compare_. 85*287e80b3SSadaf Ebrahimi 86*287e80b3SSadaf EbrahimiIf _type_ is: 87*287e80b3SSadaf Ebrahimi*TRACEFS_FILTER_COMPARE* - See below 88*287e80b3SSadaf Ebrahimi*TRACEFS_FILTER_AND* - Append "&&" to the filter 89*287e80b3SSadaf Ebrahimi*TRACEFS_FILTER_OR* - Append "||" to the filter 90*287e80b3SSadaf Ebrahimi*TRACEFS_FILTER_NOT* - Append "!" to the filter 91*287e80b3SSadaf Ebrahimi*TRACEFS_FILTER_OPEN_PAREN* - Append "(" to the filter 92*287e80b3SSadaf Ebrahimi*TRACEFS_FILTER_CLOSE_PAREN* - Append ")" to the filter 93*287e80b3SSadaf Ebrahimi 94*287e80b3SSadaf Ebrahimi_field_, _compare_, and _val_ are ignored unless _type_ is equal to 95*287e80b3SSadaf Ebrahimi*TRACEFS_FILTER_COMPARE*, then _compare_ will be used for the following: 96*287e80b3SSadaf Ebrahimi 97*287e80b3SSadaf Ebrahimi*TRACEFS_COMPARE_EQ* - _field_ == _val_ 98*287e80b3SSadaf Ebrahimi 99*287e80b3SSadaf Ebrahimi*TRACEFS_COMPARE_NE* - _field_ != _val_ 100*287e80b3SSadaf Ebrahimi 101*287e80b3SSadaf Ebrahimi*TRACEFS_COMPARE_GT* - _field_ > _val_ 102*287e80b3SSadaf Ebrahimi 103*287e80b3SSadaf Ebrahimi*TRACEFS_COMPARE_GE* - _field_ >= _val_ 104*287e80b3SSadaf Ebrahimi 105*287e80b3SSadaf Ebrahimi*TRACEFS_COMPARE_LT* - _field_ < _val_ 106*287e80b3SSadaf Ebrahimi 107*287e80b3SSadaf Ebrahimi*TRACEFS_COMPARE_LE* - _field_ <pass:[=] _val_ 108*287e80b3SSadaf Ebrahimi 109*287e80b3SSadaf Ebrahimi*TRACEFS_COMPARE_RE* - _field_ ~ "_val_" : where _field_ is a string. 110*287e80b3SSadaf Ebrahimi 111*287e80b3SSadaf Ebrahimi*TRACEFS_COMPARE_AND* - _field_ & _val_ : where _field_ is a flags field. 112*287e80b3SSadaf Ebrahimi 113*287e80b3SSadaf Ebrahimi*trace_hist_echo_cmd*() prints the commands needed to create the given histogram 114*287e80b3SSadaf Ebrahimiin the given _instance_, or NULL for the top level, into the _seq_. 115*287e80b3SSadaf EbrahimiThe command that is printed is described by _command_ and shows the functionality 116*287e80b3SSadaf Ebrahimithat would be done by *tracefs_hist_command*(3). 117*287e80b3SSadaf Ebrahimi 118*287e80b3SSadaf Ebrahimi*tracefs_hist_command*() is called to process a command on the histogram 119*287e80b3SSadaf Ebrahimi_hist_ for its event in the given _instance_, or NULL for the top level. 120*287e80b3SSadaf EbrahimiThe _cmd_ can be one of: 121*287e80b3SSadaf Ebrahimi 122*287e80b3SSadaf Ebrahimi*TRACEFS_HIST_CMD_START* or zero to start execution of the histogram. 123*287e80b3SSadaf Ebrahimi 124*287e80b3SSadaf Ebrahimi*TRACEFS_HIST_CMD_PAUSE* to pause the given histogram. 125*287e80b3SSadaf Ebrahimi 126*287e80b3SSadaf Ebrahimi*TRACEFS_HIST_CMD_CONT* to continue a paused histogram. 127*287e80b3SSadaf Ebrahimi 128*287e80b3SSadaf Ebrahimi*TRACEFS_HIST_CMD_CLEAR* to reset the values of a histogram. 129*287e80b3SSadaf Ebrahimi 130*287e80b3SSadaf Ebrahimi*TRACEFS_HIST_CMD_DESTROY* to destroy the histogram (undo a START). 131*287e80b3SSadaf Ebrahimi 132*287e80b3SSadaf EbrahimiThe below functions are wrappers to tracefs_hist_command() to make the 133*287e80b3SSadaf Ebrahimicalling conventions a bit easier to understand what is happening. 134*287e80b3SSadaf Ebrahimi 135*287e80b3SSadaf EbrahimiKEY TYPES 136*287e80b3SSadaf Ebrahimi--------- 137*287e80b3SSadaf Ebrahimi 138*287e80b3SSadaf Ebrahimi*tracefs_hist_alloc_nd*() and *tracefs_hist_add_key*() both add a key and requires 139*287e80b3SSadaf Ebrahimithat key to have a type. The types may be: 140*287e80b3SSadaf Ebrahimi 141*287e80b3SSadaf Ebrahimi*TRACEFS_HIST_KEY_NORMAL* or zero (0) which is to not modify the type. 142*287e80b3SSadaf Ebrahimi 143*287e80b3SSadaf Ebrahimi*TRACEFS_HIST_KEY_HEX* to display the key in hex. 144*287e80b3SSadaf Ebrahimi 145*287e80b3SSadaf Ebrahimi*TRACEFS_HIST_KEY_SYM* to display the key as a kernel symbol (if found). If 146*287e80b3SSadaf Ebrahimithe key is an address, this is useful as it will display the function names instead 147*287e80b3SSadaf Ebrahimiof just a number. 148*287e80b3SSadaf Ebrahimi 149*287e80b3SSadaf Ebrahimi*TRACEFS_HIST_KEY_SYM_OFFSET* similar to *TRACEFS_HIST_KEY_SYM* but will also include 150*287e80b3SSadaf Ebrahimithe offset of the function to match the exact address. 151*287e80b3SSadaf Ebrahimi 152*287e80b3SSadaf Ebrahimi*TRACEFS_HIST_KEY_SYSCALL* If the key is a system call "id" (the number passed from user 153*287e80b3SSadaf Ebrahimispace to the kernel to tell it what system call it is calling), then the name of 154*287e80b3SSadaf Ebrahimithe system call is displayed. 155*287e80b3SSadaf Ebrahimi 156*287e80b3SSadaf Ebrahimi*TRACEFS_HIST_KEY_EXECNAME* If "common_pid" is the key (the pid of the executing task), 157*287e80b3SSadaf Ebrahimiinstead of showing the number, show the name of the running task. 158*287e80b3SSadaf Ebrahimi 159*287e80b3SSadaf Ebrahimi*TRACEFS_HIST_KEY_LOG* will display the key in a binary logarithmic scale. 160*287e80b3SSadaf Ebrahimi 161*287e80b3SSadaf Ebrahimi*TRACEFS_HIST_KEY_USECS* for use with "common_timestamp" or TRACEFS_HIST_TIMESTAMP, 162*287e80b3SSadaf Ebrahimiin which case it will show the timestamp in microseconds instead of nanoseconds. 163*287e80b3SSadaf Ebrahimi 164*287e80b3SSadaf EbrahimiRETURN VALUE 165*287e80b3SSadaf Ebrahimi------------ 166*287e80b3SSadaf Ebrahimi*tracefs_hist_get_name*() returns the name of the histogram or NULL on error. 167*287e80b3SSadaf EbrahimiThe returned string belongs to the histogram object and is freed with the histogram 168*287e80b3SSadaf Ebrahimiby *tracefs_hist_free*(). 169*287e80b3SSadaf Ebrahimi 170*287e80b3SSadaf Ebrahimi*tracefs_hist_get_event*() returns the event name of the histogram or NULL on error. 171*287e80b3SSadaf EbrahimiThe returned string belongs to the histogram object and is freed with the histogram 172*287e80b3SSadaf Ebrahimiby *tracefs_hist_free*(). 173*287e80b3SSadaf Ebrahimi 174*287e80b3SSadaf Ebrahimi*tracefs_hist_get_system*() returns the system name of the histogram or NULL on error. 175*287e80b3SSadaf EbrahimiThe returned string belongs to the histogram object and is freed with the histogram 176*287e80b3SSadaf Ebrahimiby *tracefs_hist_free*(). 177*287e80b3SSadaf Ebrahimi 178*287e80b3SSadaf Ebrahimi*tracefs_hist_alloc_nd*() returns an allocated histogram descriptor which must 179*287e80b3SSadaf Ebrahimibe freed by *tracefs_hist_free*() or NULL on error. 180*287e80b3SSadaf Ebrahimi 181*287e80b3SSadaf Ebrahimi*tracefs_hist_get_name*(), *tracefs_hist_get_event*() and *tracefs_hist_get_system*() 182*287e80b3SSadaf Ebrahimireturn strings owned by the histogram object. 183*287e80b3SSadaf Ebrahimi 184*287e80b3SSadaf EbrahimiAll the other functions return zero on success or -1 on error. 185*287e80b3SSadaf Ebrahimi 186*287e80b3SSadaf EbrahimiEXAMPLE 187*287e80b3SSadaf Ebrahimi------- 188*287e80b3SSadaf Ebrahimi[source,c] 189*287e80b3SSadaf Ebrahimi-- 190*287e80b3SSadaf Ebrahimi#include <stdlib.h> 191*287e80b3SSadaf Ebrahimi#include <unistd.h> 192*287e80b3SSadaf Ebrahimi#include <tracefs.h> 193*287e80b3SSadaf Ebrahimi 194*287e80b3SSadaf Ebrahimienum commands { 195*287e80b3SSadaf Ebrahimi START, 196*287e80b3SSadaf Ebrahimi PAUSE, 197*287e80b3SSadaf Ebrahimi CONT, 198*287e80b3SSadaf Ebrahimi RESET, 199*287e80b3SSadaf Ebrahimi DELETE, 200*287e80b3SSadaf Ebrahimi SHOW, 201*287e80b3SSadaf Ebrahimi}; 202*287e80b3SSadaf Ebrahimi 203*287e80b3SSadaf Ebrahimistatic void parse_system_event(char *group, char **system, char **event) 204*287e80b3SSadaf Ebrahimi{ 205*287e80b3SSadaf Ebrahimi *system = strtok(group, "/"); 206*287e80b3SSadaf Ebrahimi *event = strtok(NULL, "/"); 207*287e80b3SSadaf Ebrahimi if (!*event) { 208*287e80b3SSadaf Ebrahimi *event = *system; 209*287e80b3SSadaf Ebrahimi *system = NULL; 210*287e80b3SSadaf Ebrahimi } 211*287e80b3SSadaf Ebrahimi} 212*287e80b3SSadaf Ebrahimi 213*287e80b3SSadaf Ebrahimistatic int parse_keys(char *keys, struct tracefs_hist_axis **axes) 214*287e80b3SSadaf Ebrahimi{ 215*287e80b3SSadaf Ebrahimi char *sav = NULL; 216*287e80b3SSadaf Ebrahimi char *key; 217*287e80b3SSadaf Ebrahimi int cnt = 0; 218*287e80b3SSadaf Ebrahimi 219*287e80b3SSadaf Ebrahimi for (key = strtok_r(keys, ",", &sav); key; key = strtok_r(NULL, ",", &sav)) { 220*287e80b3SSadaf Ebrahimi struct tracefs_hist_axis *ax; 221*287e80b3SSadaf Ebrahimi char *att; 222*287e80b3SSadaf Ebrahimi 223*287e80b3SSadaf Ebrahimi ax = realloc(*axes, sizeof(*ax) * (cnt + 2)); 224*287e80b3SSadaf Ebrahimi if (!ax) { 225*287e80b3SSadaf Ebrahimi perror("Failed to allocate axes"); 226*287e80b3SSadaf Ebrahimi exit(-1); 227*287e80b3SSadaf Ebrahimi } 228*287e80b3SSadaf Ebrahimi ax[cnt].key = key; 229*287e80b3SSadaf Ebrahimi ax[cnt].type = 0; 230*287e80b3SSadaf Ebrahimi ax[cnt + 1].key = NULL; 231*287e80b3SSadaf Ebrahimi ax[cnt + 1].type = 0; 232*287e80b3SSadaf Ebrahimi 233*287e80b3SSadaf Ebrahimi *axes = ax; 234*287e80b3SSadaf Ebrahimi 235*287e80b3SSadaf Ebrahimi att = strchr(key, '.'); 236*287e80b3SSadaf Ebrahimi if (att) { 237*287e80b3SSadaf Ebrahimi *att++ = '\0'; 238*287e80b3SSadaf Ebrahimi if (strcmp(att, "hex") == 0) 239*287e80b3SSadaf Ebrahimi ax[cnt].type = TRACEFS_HIST_KEY_HEX; 240*287e80b3SSadaf Ebrahimi else if (strcmp(att, "sym") == 0) 241*287e80b3SSadaf Ebrahimi ax[cnt].type = TRACEFS_HIST_KEY_SYM; 242*287e80b3SSadaf Ebrahimi else if (strcmp(att, "sym_offset") == 0) 243*287e80b3SSadaf Ebrahimi ax[cnt].type = TRACEFS_HIST_KEY_SYM_OFFSET; 244*287e80b3SSadaf Ebrahimi else if (strcmp(att, "syscall") == 0) 245*287e80b3SSadaf Ebrahimi ax[cnt].type = TRACEFS_HIST_KEY_SYSCALL; 246*287e80b3SSadaf Ebrahimi else if (strcmp(att, "exec") == 0) 247*287e80b3SSadaf Ebrahimi ax[cnt].type = TRACEFS_HIST_KEY_EXECNAME; 248*287e80b3SSadaf Ebrahimi else if (strcmp(att, "log") == 0) 249*287e80b3SSadaf Ebrahimi ax[cnt].type = TRACEFS_HIST_KEY_LOG; 250*287e80b3SSadaf Ebrahimi else if (strcmp(att, "usecs") == 0) 251*287e80b3SSadaf Ebrahimi ax[cnt].type = TRACEFS_HIST_KEY_USECS; 252*287e80b3SSadaf Ebrahimi else { 253*287e80b3SSadaf Ebrahimi fprintf(stderr, "Undefined attribute '%s'\n", att); 254*287e80b3SSadaf Ebrahimi fprintf(stderr," Acceptable attributes:\n"); 255*287e80b3SSadaf Ebrahimi fprintf(stderr," hex, sym, sym_offset, syscall, exe, log, usecs\n"); 256*287e80b3SSadaf Ebrahimi exit(-1); 257*287e80b3SSadaf Ebrahimi } 258*287e80b3SSadaf Ebrahimi } 259*287e80b3SSadaf Ebrahimi cnt++; 260*287e80b3SSadaf Ebrahimi } 261*287e80b3SSadaf Ebrahimi return cnt; 262*287e80b3SSadaf Ebrahimi} 263*287e80b3SSadaf Ebrahimi 264*287e80b3SSadaf Ebrahimistatic void process_hist(enum commands cmd, const char *instance_name, 265*287e80b3SSadaf Ebrahimi char *group, char *keys, char *vals, char *sort, 266*287e80b3SSadaf Ebrahimi char *ascend, char *desc) 267*287e80b3SSadaf Ebrahimi{ 268*287e80b3SSadaf Ebrahimi struct tracefs_instance *instance = NULL; 269*287e80b3SSadaf Ebrahimi struct tracefs_hist *hist; 270*287e80b3SSadaf Ebrahimi struct tep_handle *tep; 271*287e80b3SSadaf Ebrahimi struct tracefs_hist_axis *axes = NULL; 272*287e80b3SSadaf Ebrahimi char *system; 273*287e80b3SSadaf Ebrahimi char *event; 274*287e80b3SSadaf Ebrahimi char *sav; 275*287e80b3SSadaf Ebrahimi char *val; 276*287e80b3SSadaf Ebrahimi int ret; 277*287e80b3SSadaf Ebrahimi int cnt; 278*287e80b3SSadaf Ebrahimi 279*287e80b3SSadaf Ebrahimi if (instance_name) { 280*287e80b3SSadaf Ebrahimi instance = tracefs_instance_create(instance_name); 281*287e80b3SSadaf Ebrahimi if (!instance) { 282*287e80b3SSadaf Ebrahimi fprintf(stderr, "Failed instance create\n"); 283*287e80b3SSadaf Ebrahimi exit(-1); 284*287e80b3SSadaf Ebrahimi } 285*287e80b3SSadaf Ebrahimi } 286*287e80b3SSadaf Ebrahimi 287*287e80b3SSadaf Ebrahimi tep = tracefs_local_events(NULL); 288*287e80b3SSadaf Ebrahimi if (!tep) { 289*287e80b3SSadaf Ebrahimi perror("Could not read events"); 290*287e80b3SSadaf Ebrahimi exit(-1); 291*287e80b3SSadaf Ebrahimi } 292*287e80b3SSadaf Ebrahimi 293*287e80b3SSadaf Ebrahimi parse_system_event(group, &system, &event); 294*287e80b3SSadaf Ebrahimi 295*287e80b3SSadaf Ebrahimi if (cmd == SHOW) { 296*287e80b3SSadaf Ebrahimi char *content; 297*287e80b3SSadaf Ebrahimi content = tracefs_event_file_read(instance, system, event, 298*287e80b3SSadaf Ebrahimi "hist", NULL); 299*287e80b3SSadaf Ebrahimi if (!content) { 300*287e80b3SSadaf Ebrahimi perror("Reading hist file"); 301*287e80b3SSadaf Ebrahimi exit(-1); 302*287e80b3SSadaf Ebrahimi } 303*287e80b3SSadaf Ebrahimi printf("%s\n", content); 304*287e80b3SSadaf Ebrahimi free(content); 305*287e80b3SSadaf Ebrahimi return; 306*287e80b3SSadaf Ebrahimi } 307*287e80b3SSadaf Ebrahimi 308*287e80b3SSadaf Ebrahimi if (!keys) { 309*287e80b3SSadaf Ebrahimi fprintf(stderr, "Command needs -k option\n"); 310*287e80b3SSadaf Ebrahimi exit(-1); 311*287e80b3SSadaf Ebrahimi } 312*287e80b3SSadaf Ebrahimi 313*287e80b3SSadaf Ebrahimi cnt = parse_keys(keys, &axes); 314*287e80b3SSadaf Ebrahimi if (!cnt) { 315*287e80b3SSadaf Ebrahimi fprintf(stderr, "No keys??\n"); 316*287e80b3SSadaf Ebrahimi exit(-1); 317*287e80b3SSadaf Ebrahimi } 318*287e80b3SSadaf Ebrahimi 319*287e80b3SSadaf Ebrahimi /* Show examples of hist1d and hist2d */ 320*287e80b3SSadaf Ebrahimi switch (cnt) { 321*287e80b3SSadaf Ebrahimi case 1: 322*287e80b3SSadaf Ebrahimi hist = tracefs_hist_alloc(tep, system, event, 323*287e80b3SSadaf Ebrahimi axes[0].key, axes[0].type); 324*287e80b3SSadaf Ebrahimi break; 325*287e80b3SSadaf Ebrahimi case 2: 326*287e80b3SSadaf Ebrahimi hist = tracefs_hist_alloc_2d(tep, system, event, 327*287e80b3SSadaf Ebrahimi axes[0].key, axes[0].type, 328*287e80b3SSadaf Ebrahimi axes[1].key, axes[1].type); 329*287e80b3SSadaf Ebrahimi break; 330*287e80b3SSadaf Ebrahimi default: 331*287e80b3SSadaf Ebrahimi /* Really, 1 and 2 could use this too */ 332*287e80b3SSadaf Ebrahimi hist = tracefs_hist_alloc_nd(tep, system, event, axes); 333*287e80b3SSadaf Ebrahimi } 334*287e80b3SSadaf Ebrahimi if (!hist) { 335*287e80b3SSadaf Ebrahimi fprintf(stderr, "Failed hist create\n"); 336*287e80b3SSadaf Ebrahimi exit(-1); 337*287e80b3SSadaf Ebrahimi } 338*287e80b3SSadaf Ebrahimi 339*287e80b3SSadaf Ebrahimi if (vals) { 340*287e80b3SSadaf Ebrahimi sav = NULL; 341*287e80b3SSadaf Ebrahimi for (val = strtok_r(vals, ",", &sav); val; val = strtok_r(NULL, ",", &sav)) { 342*287e80b3SSadaf Ebrahimi ret = tracefs_hist_add_value(hist, val); 343*287e80b3SSadaf Ebrahimi if (ret) { 344*287e80b3SSadaf Ebrahimi fprintf(stderr, "Failed to add value %s\n", val); 345*287e80b3SSadaf Ebrahimi exit(-1); 346*287e80b3SSadaf Ebrahimi } 347*287e80b3SSadaf Ebrahimi } 348*287e80b3SSadaf Ebrahimi } 349*287e80b3SSadaf Ebrahimi 350*287e80b3SSadaf Ebrahimi if (sort) { 351*287e80b3SSadaf Ebrahimi sav = NULL; 352*287e80b3SSadaf Ebrahimi for (val = strtok_r(sort, ",", &sav); val; val = strtok_r(NULL, ",", &sav)) { 353*287e80b3SSadaf Ebrahimi ret = tracefs_hist_add_sort_key(hist, val); 354*287e80b3SSadaf Ebrahimi if (ret) { 355*287e80b3SSadaf Ebrahimi fprintf(stderr, "Failed to add sort key/val %s\n", val); 356*287e80b3SSadaf Ebrahimi exit(-1); 357*287e80b3SSadaf Ebrahimi } 358*287e80b3SSadaf Ebrahimi } 359*287e80b3SSadaf Ebrahimi } 360*287e80b3SSadaf Ebrahimi 361*287e80b3SSadaf Ebrahimi if (ascend) { 362*287e80b3SSadaf Ebrahimi sav = NULL; 363*287e80b3SSadaf Ebrahimi for (val = strtok_r(ascend, ",", &sav); val; val = strtok_r(NULL, ",", &sav)) { 364*287e80b3SSadaf Ebrahimi ret = tracefs_hist_sort_key_direction(hist, val, TRACEFS_HIST_SORT_ASCENDING); 365*287e80b3SSadaf Ebrahimi if (ret) { 366*287e80b3SSadaf Ebrahimi fprintf(stderr, "Failed to add ascending key/val %s\n", val); 367*287e80b3SSadaf Ebrahimi exit(-1); 368*287e80b3SSadaf Ebrahimi } 369*287e80b3SSadaf Ebrahimi } 370*287e80b3SSadaf Ebrahimi } 371*287e80b3SSadaf Ebrahimi 372*287e80b3SSadaf Ebrahimi if (desc) { 373*287e80b3SSadaf Ebrahimi sav = NULL; 374*287e80b3SSadaf Ebrahimi for (val = strtok_r(desc, ",", &sav); val; val = strtok_r(NULL, ",", &sav)) { 375*287e80b3SSadaf Ebrahimi ret = tracefs_hist_sort_key_direction(hist, val, TRACEFS_HIST_SORT_DESCENDING); 376*287e80b3SSadaf Ebrahimi if (ret) { 377*287e80b3SSadaf Ebrahimi fprintf(stderr, "Failed to add descending key/val %s\n", val); 378*287e80b3SSadaf Ebrahimi exit(-1); 379*287e80b3SSadaf Ebrahimi } 380*287e80b3SSadaf Ebrahimi } 381*287e80b3SSadaf Ebrahimi } 382*287e80b3SSadaf Ebrahimi 383*287e80b3SSadaf Ebrahimi tracefs_error_clear(instance); 384*287e80b3SSadaf Ebrahimi 385*287e80b3SSadaf Ebrahimi switch (cmd) { 386*287e80b3SSadaf Ebrahimi case START: 387*287e80b3SSadaf Ebrahimi ret = tracefs_hist_start(instance, hist); 388*287e80b3SSadaf Ebrahimi if (ret) { 389*287e80b3SSadaf Ebrahimi char *err = tracefs_error_last(instance); 390*287e80b3SSadaf Ebrahimi if (err) 391*287e80b3SSadaf Ebrahimi fprintf(stderr, "\n%s\n", err); 392*287e80b3SSadaf Ebrahimi } 393*287e80b3SSadaf Ebrahimi break; 394*287e80b3SSadaf Ebrahimi case PAUSE: 395*287e80b3SSadaf Ebrahimi ret = tracefs_hist_pause(instance, hist); 396*287e80b3SSadaf Ebrahimi break; 397*287e80b3SSadaf Ebrahimi case CONT: 398*287e80b3SSadaf Ebrahimi ret = tracefs_hist_continue(instance, hist); 399*287e80b3SSadaf Ebrahimi break; 400*287e80b3SSadaf Ebrahimi case RESET: 401*287e80b3SSadaf Ebrahimi ret = tracefs_hist_reset(instance, hist); 402*287e80b3SSadaf Ebrahimi break; 403*287e80b3SSadaf Ebrahimi case DELETE: 404*287e80b3SSadaf Ebrahimi ret = tracefs_hist_destroy(instance, hist); 405*287e80b3SSadaf Ebrahimi break; 406*287e80b3SSadaf Ebrahimi case SHOW: 407*287e80b3SSadaf Ebrahimi /* Show was already done */ 408*287e80b3SSadaf Ebrahimi break; 409*287e80b3SSadaf Ebrahimi } 410*287e80b3SSadaf Ebrahimi if (ret) 411*287e80b3SSadaf Ebrahimi fprintf(stderr, "Failed: command\n"); 412*287e80b3SSadaf Ebrahimi exit(ret); 413*287e80b3SSadaf Ebrahimi} 414*287e80b3SSadaf Ebrahimi 415*287e80b3SSadaf Ebrahimiint main (int argc, char **argv, char **env) 416*287e80b3SSadaf Ebrahimi{ 417*287e80b3SSadaf Ebrahimi enum commands cmd; 418*287e80b3SSadaf Ebrahimi char *instance = NULL; 419*287e80b3SSadaf Ebrahimi char *cmd_str; 420*287e80b3SSadaf Ebrahimi char *event = NULL; 421*287e80b3SSadaf Ebrahimi char *keys = NULL; 422*287e80b3SSadaf Ebrahimi char *vals = NULL; 423*287e80b3SSadaf Ebrahimi char *sort = NULL; 424*287e80b3SSadaf Ebrahimi char *desc = NULL; 425*287e80b3SSadaf Ebrahimi char *ascend = NULL; 426*287e80b3SSadaf Ebrahimi 427*287e80b3SSadaf Ebrahimi if (argc < 2) { 428*287e80b3SSadaf Ebrahimi fprintf(stderr, "usage: %s command [-B instance][-e [system/]event][-k keys][-v vals][-s sort]\n", argv[0]); 429*287e80b3SSadaf Ebrahimi fprintf(stderr, " [-a ascending][-d descending]\n"); 430*287e80b3SSadaf Ebrahimi exit(-1); 431*287e80b3SSadaf Ebrahimi } 432*287e80b3SSadaf Ebrahimi 433*287e80b3SSadaf Ebrahimi cmd_str = argv[1]; 434*287e80b3SSadaf Ebrahimi 435*287e80b3SSadaf Ebrahimi if (!strcmp(cmd_str, "start")) 436*287e80b3SSadaf Ebrahimi cmd = START; 437*287e80b3SSadaf Ebrahimi else if (!strcmp(cmd_str, "pause")) 438*287e80b3SSadaf Ebrahimi cmd = PAUSE; 439*287e80b3SSadaf Ebrahimi else if (!strcmp(cmd_str, "cont")) 440*287e80b3SSadaf Ebrahimi cmd = CONT; 441*287e80b3SSadaf Ebrahimi else if (!strcmp(cmd_str, "reset")) 442*287e80b3SSadaf Ebrahimi cmd = RESET; 443*287e80b3SSadaf Ebrahimi else if (!strcmp(cmd_str, "delete")) 444*287e80b3SSadaf Ebrahimi cmd = DELETE; 445*287e80b3SSadaf Ebrahimi else if (!strcmp(cmd_str, "show")) 446*287e80b3SSadaf Ebrahimi cmd = SHOW; 447*287e80b3SSadaf Ebrahimi else { 448*287e80b3SSadaf Ebrahimi fprintf(stderr, "Unknown command %s\n", cmd_str); 449*287e80b3SSadaf Ebrahimi exit(-1); 450*287e80b3SSadaf Ebrahimi } 451*287e80b3SSadaf Ebrahimi 452*287e80b3SSadaf Ebrahimi for (;;) { 453*287e80b3SSadaf Ebrahimi int c; 454*287e80b3SSadaf Ebrahimi 455*287e80b3SSadaf Ebrahimi c = getopt(argc - 1, argv + 1, "e:k:v:B:s:d:a:"); 456*287e80b3SSadaf Ebrahimi if (c == -1) 457*287e80b3SSadaf Ebrahimi break; 458*287e80b3SSadaf Ebrahimi 459*287e80b3SSadaf Ebrahimi switch (c) { 460*287e80b3SSadaf Ebrahimi case 'e': 461*287e80b3SSadaf Ebrahimi event = optarg; 462*287e80b3SSadaf Ebrahimi break; 463*287e80b3SSadaf Ebrahimi case 'k': 464*287e80b3SSadaf Ebrahimi keys = optarg; 465*287e80b3SSadaf Ebrahimi break; 466*287e80b3SSadaf Ebrahimi case 'v': 467*287e80b3SSadaf Ebrahimi vals = optarg; 468*287e80b3SSadaf Ebrahimi break; 469*287e80b3SSadaf Ebrahimi case 'B': 470*287e80b3SSadaf Ebrahimi instance = optarg; 471*287e80b3SSadaf Ebrahimi break; 472*287e80b3SSadaf Ebrahimi case 's': 473*287e80b3SSadaf Ebrahimi sort = optarg; 474*287e80b3SSadaf Ebrahimi break; 475*287e80b3SSadaf Ebrahimi case 'd': 476*287e80b3SSadaf Ebrahimi desc = optarg; 477*287e80b3SSadaf Ebrahimi break; 478*287e80b3SSadaf Ebrahimi case 'a': 479*287e80b3SSadaf Ebrahimi ascend = optarg; 480*287e80b3SSadaf Ebrahimi break; 481*287e80b3SSadaf Ebrahimi } 482*287e80b3SSadaf Ebrahimi } 483*287e80b3SSadaf Ebrahimi if (!event) { 484*287e80b3SSadaf Ebrahimi event = "kmem/kmalloc"; 485*287e80b3SSadaf Ebrahimi if (!keys) 486*287e80b3SSadaf Ebrahimi keys = "call_site.sym,bytes_req"; 487*287e80b3SSadaf Ebrahimi if (!vals) 488*287e80b3SSadaf Ebrahimi vals = "bytes_alloc"; 489*287e80b3SSadaf Ebrahimi if (!sort) 490*287e80b3SSadaf Ebrahimi sort = "bytes_req,bytes_alloc"; 491*287e80b3SSadaf Ebrahimi if (!desc) 492*287e80b3SSadaf Ebrahimi desc = "bytes_alloc"; 493*287e80b3SSadaf Ebrahimi } 494*287e80b3SSadaf Ebrahimi process_hist(cmd, instance, event, keys, vals, sort, ascend, desc); 495*287e80b3SSadaf Ebrahimi} 496*287e80b3SSadaf Ebrahimi-- 497*287e80b3SSadaf Ebrahimi 498*287e80b3SSadaf EbrahimiFILES 499*287e80b3SSadaf Ebrahimi----- 500*287e80b3SSadaf Ebrahimi[verse] 501*287e80b3SSadaf Ebrahimi-- 502*287e80b3SSadaf Ebrahimi*tracefs.h* 503*287e80b3SSadaf Ebrahimi Header file to include in order to have access to the library APIs. 504*287e80b3SSadaf Ebrahimi*-ltracefs* 505*287e80b3SSadaf Ebrahimi Linker switch to add when building a program that uses the library. 506*287e80b3SSadaf Ebrahimi-- 507*287e80b3SSadaf Ebrahimi 508*287e80b3SSadaf EbrahimiSEE ALSO 509*287e80b3SSadaf Ebrahimi-------- 510*287e80b3SSadaf Ebrahimi*libtracefs*(3), 511*287e80b3SSadaf Ebrahimi*libtraceevent*(3), 512*287e80b3SSadaf Ebrahimi*trace-cmd*(1), 513*287e80b3SSadaf Ebrahimi*tracefs_hist_pause*(3), 514*287e80b3SSadaf Ebrahimi*tracefs_hist_continue*(3), 515*287e80b3SSadaf Ebrahimi*tracefs_hist_reset*(3) 516*287e80b3SSadaf Ebrahimi 517*287e80b3SSadaf EbrahimiAUTHOR 518*287e80b3SSadaf Ebrahimi------ 519*287e80b3SSadaf Ebrahimi[verse] 520*287e80b3SSadaf Ebrahimi-- 521*287e80b3SSadaf Ebrahimi*Steven Rostedt* <[email protected]> 522*287e80b3SSadaf Ebrahimi*Tzvetomir Stoyanov* <[email protected]> 523*287e80b3SSadaf Ebrahimi*sameeruddin shaik* <[email protected]> 524*287e80b3SSadaf Ebrahimi-- 525*287e80b3SSadaf EbrahimiREPORTING BUGS 526*287e80b3SSadaf Ebrahimi-------------- 527*287e80b3SSadaf EbrahimiReport bugs to <[email protected]> 528*287e80b3SSadaf Ebrahimi 529*287e80b3SSadaf EbrahimiLICENSE 530*287e80b3SSadaf Ebrahimi------- 531*287e80b3SSadaf Ebrahimilibtracefs is Free Software licensed under the GNU LGPL 2.1 532*287e80b3SSadaf Ebrahimi 533*287e80b3SSadaf EbrahimiRESOURCES 534*287e80b3SSadaf Ebrahimi--------- 535*287e80b3SSadaf Ebrahimihttps://git.kernel.org/pub/scm/libs/libtrace/libtracefs.git/ 536*287e80b3SSadaf Ebrahimi 537*287e80b3SSadaf EbrahimiCOPYING 538*287e80b3SSadaf Ebrahimi------- 539*287e80b3SSadaf EbrahimiCopyright \(C) 2020 VMware, Inc. Free use of this software is granted under 540*287e80b3SSadaf Ebrahimithe terms of the GNU Public License (GPL). 541