1*287e80b3SSadaf Ebrahimilibtracefs(3) 2*287e80b3SSadaf Ebrahimi============= 3*287e80b3SSadaf Ebrahimi 4*287e80b3SSadaf EbrahimiNAME 5*287e80b3SSadaf Ebrahimi---- 6*287e80b3SSadaf Ebrahimitracefs_hist_alloc, tracefs_hist_alloc_2d, tracefs_hist_alloc_nd, tracefs_hist_alloc_nd_cnt, tracefs_hist_free, 7*287e80b3SSadaf Ebrahimitracefs_hist_add_key, tracefs_hist_add_key_cnt, tracefs_hist_add_value - Create and destroy event histograms 8*287e80b3SSadaf Ebrahimi 9*287e80b3SSadaf EbrahimiSYNOPSIS 10*287e80b3SSadaf Ebrahimi-------- 11*287e80b3SSadaf Ebrahimi[verse] 12*287e80b3SSadaf Ebrahimi-- 13*287e80b3SSadaf Ebrahimi*#include <tracefs.h>* 14*287e80b3SSadaf Ebrahimi 15*287e80b3SSadaf Ebrahimienum *tracefs_hist_key_type* { 16*287e80b3SSadaf Ebrahimi *TRACEFS_HIST_KEY_NORMAL* = 0, 17*287e80b3SSadaf Ebrahimi *TRACEFS_HIST_KEY_HEX*, 18*287e80b3SSadaf Ebrahimi *TRACEFS_HIST_KEY_SYM*, 19*287e80b3SSadaf Ebrahimi *TRACEFS_HIST_KEY_SYM_OFFSET*, 20*287e80b3SSadaf Ebrahimi *TRACEFS_HIST_KEY_SYSCALL*, 21*287e80b3SSadaf Ebrahimi *TRACEFS_HIST_KEY_EXECNAME*, 22*287e80b3SSadaf Ebrahimi *TRACEFS_HIST_KEY_LOG*, 23*287e80b3SSadaf Ebrahimi *TRACEFS_HIST_KEY_USECS*, 24*287e80b3SSadaf Ebrahimi *TRACEFS_HIST_KEY_MAX* 25*287e80b3SSadaf Ebrahimi}; 26*287e80b3SSadaf Ebrahimi 27*287e80b3SSadaf Ebrahimistruct *tracefs_hist_axis* { 28*287e80b3SSadaf Ebrahimi const char pass:[*]_key_; 29*287e80b3SSadaf Ebrahimi enum tracefs_hist_key_type _type_; 30*287e80b3SSadaf Ebrahimi}; 31*287e80b3SSadaf Ebrahimi 32*287e80b3SSadaf Ebrahimistruct tracefs_hist pass:[*]*tracefs_hist_alloc*(struct tracefs_tep pass:[*] _tep_, 33*287e80b3SSadaf Ebrahimi const char pass:[*]_system_, const char pass:[*]_event_, 34*287e80b3SSadaf Ebrahimi const char pass:[*]_key_, enum tracefs_hist_key_type _type_); 35*287e80b3SSadaf Ebrahimistruct tracefs_hist pass:[*]*tracefs_hist_alloc_2d*(struct tracefs_tep pass:[*] _tep_, 36*287e80b3SSadaf Ebrahimi const char pass:[*]_system_, const char pass:[*]_event_, 37*287e80b3SSadaf Ebrahimi const char pass:[*]_key1_, enum tracefs_hist_key_type _type1_, 38*287e80b3SSadaf Ebrahimi const char pass:[*]_key2_, enum tracefs_hist_key_type _type2_)); 39*287e80b3SSadaf Ebrahimistruct tracefs_hist pass:[*]*tracefs_hist_alloc_nd*(struct tracefs_tep pass:[*] _tep_, 40*287e80b3SSadaf Ebrahimi const char pass:[*]_system_, const char pass:[*]_event_, 41*287e80b3SSadaf Ebrahimi struct tracefs_hist_axis pass:[*]_axes_); 42*287e80b3SSadaf Ebrahimistruct tracefs_hist pass:[*]*tracefs_hist_alloc_nd_cnt*(struct tep_handle pass:[*]_tep_, 43*287e80b3SSadaf Ebrahimi const char pass:[*]_system_, const char pass:[*]_event_name_, 44*287e80b3SSadaf Ebrahimi struct tracefs_hist_axis_cnt pass:[*]_axes_); 45*287e80b3SSadaf Ebrahimivoid *tracefs_hist_free*(struct tracefs_hist pass:[*]_hist_); 46*287e80b3SSadaf Ebrahimi 47*287e80b3SSadaf Ebrahimiint *tracefs_hist_add_key*(struct tracefs_hist pass:[*]_hist_, const char pass:[*]_key_, 48*287e80b3SSadaf Ebrahimi enum tracefs_hist_key_type _type_); 49*287e80b3SSadaf Ebrahimiint *tracefs_hist_add_key_cnt*(struct tracefs_hist pass:[*]_hist_, const char pass:[*]_key_, 50*287e80b3SSadaf Ebrahimi enum tracefs_hist_key_type _type_, int _cnt_); 51*287e80b3SSadaf Ebrahimiint *tracefs_hist_add_value*(struct tracefs_hist pass:[*]_hist_, const char pass:[*]_value_); 52*287e80b3SSadaf Ebrahimi-- 53*287e80b3SSadaf Ebrahimi 54*287e80b3SSadaf EbrahimiDESCRIPTION 55*287e80b3SSadaf Ebrahimi----------- 56*287e80b3SSadaf EbrahimiEvent histograms are created by the trigger file in the event directory. 57*287e80b3SSadaf EbrahimiThe syntax can be complex and difficult to get correct. This API handles the 58*287e80b3SSadaf Ebrahimisyntax, and facilitates the creation and interaction with the event histograms. 59*287e80b3SSadaf EbrahimiSee https://www.kernel.org/doc/html/latest/trace/histogram.html for more information. 60*287e80b3SSadaf Ebrahimi 61*287e80b3SSadaf Ebrahimi*tracefs_hist_alloc*() allocates a "struct tracefs_hist" descriptor of a one-dimensional 62*287e80b3SSadaf Ebrahimihistogram and returns the address of it. This descriptor must be freed by *tracefs_hist_free*(). 63*287e80b3SSadaf EbrahimiThe _tep_ is a trace event handle (see *tracefs_local_events*(3)), that holds the 64*287e80b3SSadaf Ebrahimi_system_ and _event_ that the histogram will be attached to. The _system_ is the 65*287e80b3SSadaf Ebrahimisystem or group of the event. The _event_ is the event to attach the histogram to. 66*287e80b3SSadaf EbrahimiThe _key_ is a field of the event that will be used as the key(dimension) of the histogram. 67*287e80b3SSadaf EbrahimiThe _type_ is the type of the _key_. See KEY TYPES below. 68*287e80b3SSadaf Ebrahimi 69*287e80b3SSadaf Ebrahimi*tracefs_hist_alloc_2d*() allocates a "struct tracefs_hist" descriptor of a two-dimensional 70*287e80b3SSadaf Ebrahimihistogram and returns the address of it. This descriptor must be freed by *tracefs_hist_free*(). 71*287e80b3SSadaf EbrahimiThe _tep_ is a trace event handle (see *tracefs_local_events*(3)), that holds the 72*287e80b3SSadaf Ebrahimi_system_ and _event_ that the histogram will be attached to. The _system_ is the 73*287e80b3SSadaf Ebrahimisystem or group of the event. The _event_ is the event to attach the histogram to. 74*287e80b3SSadaf EbrahimiThe _key1_ is the first field of the event that will be used as the key(dimension) 75*287e80b3SSadaf Ebrahimiof the histogram. The _type1_ is the type of the _key1_. See KEY TYPES below. 76*287e80b3SSadaf EbrahimiThe _key2_ is the second field of the event that will be used as the key(dimension) 77*287e80b3SSadaf Ebrahimiof the histogram. The _type2_ is the type of the _key2_. See KEY TYPES below. 78*287e80b3SSadaf Ebrahimi 79*287e80b3SSadaf Ebrahimi*tracefs_hist_alloc_nd*() allocates a "struct tracefs_hist" descriptor of an N-dimensional 80*287e80b3SSadaf Ebrahimihistogram and returns the address of it. This descriptor must be freed by *tracefs_hist_free*(). 81*287e80b3SSadaf EbrahimiThe _tep_ is a trace event handle (see *tracefs_local_events*(3)), that holds the 82*287e80b3SSadaf Ebrahimi_system_ and _event_ that the histogram will be attached to. The _system_ is the 83*287e80b3SSadaf Ebrahimisystem or group of the event. The _event_ is the event to attach the histogram to. 84*287e80b3SSadaf EbrahimiThe _axes_ is an array of _key_ / _type_ pairs, defining the dimensions of the histogram. 85*287e80b3SSadaf Ebrahimi 86*287e80b3SSadaf Ebrahimi*tracefs_hist_alloc_nd_cnt*() will initialize a histogram descriptor that will be attached to 87*287e80b3SSadaf Ebrahimithe _system_/_event_. This only initializes the descriptor with the given _axes_ keys as primaries. 88*287e80b3SSadaf EbrahimiThis only initializes the descriptor, it does not start the histogram in the kernel. 89*287e80b3SSadaf EbrahimiThe difference between this and *tracefs_hist_alloc_nd()* is that the _axes_ parameter 90*287e80b3SSadaf Ebrahimiis of type *struct tracefs_hist_axis_cnt* and not *struct tracefs_hist_axis*. 91*287e80b3SSadaf Ebrahimi 92*287e80b3SSadaf Ebrahimi*tracefs_hist_free*() frees the _tracefs_hist_ descriptor. Note, it does not stop 93*287e80b3SSadaf Ebrahimior disable the running histogram if it was started. *tracefs_hist_destroy*() needs 94*287e80b3SSadaf Ebrahimito be called to do so. 95*287e80b3SSadaf Ebrahimi 96*287e80b3SSadaf Ebrahimi*tracefs_hist_add_key*() Adds a secondary or tertiary key to the histogram. 97*287e80b3SSadaf EbrahimiThe key passed to *tracefs_hist_alloc_nd*() is the primary key of the histogram. 98*287e80b3SSadaf EbrahimiThe first time this function is called, it will add a secondary key (or two dimensional 99*287e80b3SSadaf Ebrahimihistogram). If this function is called again on the same histogram, it will add 100*287e80b3SSadaf Ebrahimia _tertiary_ key (or three dimensional histogram). The _hist_ parameter is the 101*287e80b3SSadaf Ebrahimihistogram descriptor to add the _key_ to. The _type_ is the type of key to add 102*287e80b3SSadaf Ebrahimi(See KEY TYPES below). 103*287e80b3SSadaf Ebrahimi 104*287e80b3SSadaf EbrahimiThe *tracefs_hist_add_key_cnt*() is the same as *tracefs_hist_add_key*() except 105*287e80b3SSadaf Ebrahimithat it allows to add a counter for the given type. Currently, there's only 106*287e80b3SSadaf Ebrahimithe *buckets* type that requires a counter. When adding a key with the buckets 107*287e80b3SSadaf Ebrahimitype, *tracefs_hist_add_key*() is not sufficient, as the *buckets* type requires 108*287e80b3SSadaf Ebrahimia counter or bucket size. Use *tracefs_hist_add_key_cnt*() when specifing 109*287e80b3SSadaf Ebrahimia key that is broken up into buckets, and pass in the size of those buckets 110*287e80b3SSadaf Ebrahimiinto _cnt_. 111*287e80b3SSadaf Ebrahimi 112*287e80b3SSadaf Ebrahimi*tracefs_hist_add_value*() will add a value to record. By default, the value is 113*287e80b3SSadaf Ebrahimisimply the "hitcount" of the number of times a instance of the histogram's 114*287e80b3SSadaf Ebrahimikey was hit. The _hist_ is the histogram descriptor to add the value to. 115*287e80b3SSadaf EbrahimiThe _value_ is a field in the histogram to add to when an instance of the 116*287e80b3SSadaf Ebrahimikey is hit. 117*287e80b3SSadaf Ebrahimi 118*287e80b3SSadaf EbrahimiKEY TYPES 119*287e80b3SSadaf Ebrahimi--------- 120*287e80b3SSadaf Ebrahimi 121*287e80b3SSadaf Ebrahimi*tracefs_hist_alloc_nd*() and *tracefs_hist_add_key*() both add a key and requires 122*287e80b3SSadaf Ebrahimithat key to have a type. The types may be: 123*287e80b3SSadaf Ebrahimi 124*287e80b3SSadaf Ebrahimi*TRACEFS_HIST_KEY_NORMAL* or zero (0) which is to not modify the type. 125*287e80b3SSadaf Ebrahimi 126*287e80b3SSadaf Ebrahimi*TRACEFS_HIST_KEY_HEX* to display the key in hex. 127*287e80b3SSadaf Ebrahimi 128*287e80b3SSadaf Ebrahimi*TRACEFS_HIST_KEY_SYM* to display the key as a kernel symbol (if found). If 129*287e80b3SSadaf Ebrahimithe key is an address, this is useful as it will display the function names instead 130*287e80b3SSadaf Ebrahimiof just a number. 131*287e80b3SSadaf Ebrahimi 132*287e80b3SSadaf Ebrahimi*TRACEFS_HIST_KEY_SYM_OFFSET* similar to *TRACEFS_HIST_KEY_SYM* but will also include 133*287e80b3SSadaf Ebrahimithe offset of the function to match the exact address. 134*287e80b3SSadaf Ebrahimi 135*287e80b3SSadaf Ebrahimi*TRACEFS_HIST_KEY_SYSCALL* If the key is a system call "id" (the number passed from user 136*287e80b3SSadaf Ebrahimispace to the kernel to tell it what system call it is calling), then the name of 137*287e80b3SSadaf Ebrahimithe system call is displayed. 138*287e80b3SSadaf Ebrahimi 139*287e80b3SSadaf Ebrahimi*TRACEFS_HIST_KEY_EXECNAME* If "common_pid" is the key (the pid of the executing task), 140*287e80b3SSadaf Ebrahimiinstead of showing the number, show the name of the running task. 141*287e80b3SSadaf Ebrahimi 142*287e80b3SSadaf Ebrahimi*TRACEFS_HIST_KEY_LOG* will display the key in a binary logarithmic scale. 143*287e80b3SSadaf Ebrahimi 144*287e80b3SSadaf Ebrahimi*TRACEFS_HIST_KEY_USECS* for use with "common_timestamp" or TRACEFS_HIST_TIMESTAMP, 145*287e80b3SSadaf Ebrahimiin which case it will show the timestamp in microseconds instead of nanoseconds. 146*287e80b3SSadaf Ebrahimi 147*287e80b3SSadaf EbrahimiRETURN VALUE 148*287e80b3SSadaf Ebrahimi------------ 149*287e80b3SSadaf Ebrahimi*tracefs_hist_alloc_nd*() returns an allocated histogram descriptor which must 150*287e80b3SSadaf Ebrahimibe freed by *tracefs_hist_free*() or NULL on error. 151*287e80b3SSadaf Ebrahimi 152*287e80b3SSadaf EbrahimiAll the other functions return zero on success or -1 on error. 153*287e80b3SSadaf Ebrahimi 154*287e80b3SSadaf EbrahimiIf *tracefs_hist_start*() returns an error, a message may be displayed 155*287e80b3SSadaf Ebrahimiin the kernel that can be retrieved by *tracefs_error_last()*. 156*287e80b3SSadaf Ebrahimi 157*287e80b3SSadaf EbrahimiEXAMPLE 158*287e80b3SSadaf Ebrahimi------- 159*287e80b3SSadaf Ebrahimi[source,c] 160*287e80b3SSadaf Ebrahimi-- 161*287e80b3SSadaf Ebrahimi#include <stdlib.h> 162*287e80b3SSadaf Ebrahimi#include <ctype.h> 163*287e80b3SSadaf Ebrahimi#include <unistd.h> 164*287e80b3SSadaf Ebrahimi#include <tracefs.h> 165*287e80b3SSadaf Ebrahimi 166*287e80b3SSadaf Ebrahimienum commands { 167*287e80b3SSadaf Ebrahimi START, 168*287e80b3SSadaf Ebrahimi PAUSE, 169*287e80b3SSadaf Ebrahimi CONT, 170*287e80b3SSadaf Ebrahimi RESET, 171*287e80b3SSadaf Ebrahimi DELETE, 172*287e80b3SSadaf Ebrahimi SHOW, 173*287e80b3SSadaf Ebrahimi}; 174*287e80b3SSadaf Ebrahimi 175*287e80b3SSadaf Ebrahimistatic void parse_system_event(char *group, char **system, char **event) 176*287e80b3SSadaf Ebrahimi{ 177*287e80b3SSadaf Ebrahimi *system = strtok(group, "/"); 178*287e80b3SSadaf Ebrahimi *event = strtok(NULL, "/"); 179*287e80b3SSadaf Ebrahimi if (!*event) { 180*287e80b3SSadaf Ebrahimi *event = *system; 181*287e80b3SSadaf Ebrahimi *system = NULL; 182*287e80b3SSadaf Ebrahimi } 183*287e80b3SSadaf Ebrahimi} 184*287e80b3SSadaf Ebrahimi 185*287e80b3SSadaf Ebrahimistatic int parse_keys(char *keys, struct tracefs_hist_axis_cnt **axes) 186*287e80b3SSadaf Ebrahimi{ 187*287e80b3SSadaf Ebrahimi char *sav = NULL; 188*287e80b3SSadaf Ebrahimi char *key; 189*287e80b3SSadaf Ebrahimi int cnt = 0; 190*287e80b3SSadaf Ebrahimi 191*287e80b3SSadaf Ebrahimi for (key = strtok_r(keys, ",", &sav); key; key = strtok_r(NULL, ",", &sav)) { 192*287e80b3SSadaf Ebrahimi struct tracefs_hist_axis_cnt *ax; 193*287e80b3SSadaf Ebrahimi char *att; 194*287e80b3SSadaf Ebrahimi 195*287e80b3SSadaf Ebrahimi ax = realloc(*axes, sizeof(*ax) * (cnt + 2)); 196*287e80b3SSadaf Ebrahimi if (!ax) { 197*287e80b3SSadaf Ebrahimi perror("Failed to allocate axes"); 198*287e80b3SSadaf Ebrahimi exit(-1); 199*287e80b3SSadaf Ebrahimi } 200*287e80b3SSadaf Ebrahimi ax[cnt].key = key; 201*287e80b3SSadaf Ebrahimi ax[cnt].type = 0; 202*287e80b3SSadaf Ebrahimi ax[cnt + 1].key = NULL; 203*287e80b3SSadaf Ebrahimi ax[cnt + 1].type = 0; 204*287e80b3SSadaf Ebrahimi 205*287e80b3SSadaf Ebrahimi *axes = ax; 206*287e80b3SSadaf Ebrahimi 207*287e80b3SSadaf Ebrahimi att = strchr(key, '.'); 208*287e80b3SSadaf Ebrahimi if (att) { 209*287e80b3SSadaf Ebrahimi *att++ = '\0'; 210*287e80b3SSadaf Ebrahimi if (strcmp(att, "hex") == 0) 211*287e80b3SSadaf Ebrahimi ax[cnt].type = TRACEFS_HIST_KEY_HEX; 212*287e80b3SSadaf Ebrahimi else if (strcmp(att, "sym") == 0) 213*287e80b3SSadaf Ebrahimi ax[cnt].type = TRACEFS_HIST_KEY_SYM; 214*287e80b3SSadaf Ebrahimi else if (strcmp(att, "sym_offset") == 0) 215*287e80b3SSadaf Ebrahimi ax[cnt].type = TRACEFS_HIST_KEY_SYM_OFFSET; 216*287e80b3SSadaf Ebrahimi else if (strcmp(att, "syscall") == 0) 217*287e80b3SSadaf Ebrahimi ax[cnt].type = TRACEFS_HIST_KEY_SYSCALL; 218*287e80b3SSadaf Ebrahimi else if (strcmp(att, "exec") == 0) 219*287e80b3SSadaf Ebrahimi ax[cnt].type = TRACEFS_HIST_KEY_EXECNAME; 220*287e80b3SSadaf Ebrahimi else if (strcmp(att, "log") == 0) 221*287e80b3SSadaf Ebrahimi ax[cnt].type = TRACEFS_HIST_KEY_LOG; 222*287e80b3SSadaf Ebrahimi else if (strcmp(att, "usecs") == 0) 223*287e80b3SSadaf Ebrahimi ax[cnt].type = TRACEFS_HIST_KEY_USECS; 224*287e80b3SSadaf Ebrahimi else if (strncmp(att, "buckets", 7) == 0) { 225*287e80b3SSadaf Ebrahimi if (att[7] != '=' && !isdigit(att[8])) { 226*287e80b3SSadaf Ebrahimi fprintf(stderr, "'buckets' key type requires '=<size>'\n"); 227*287e80b3SSadaf Ebrahimi exit(-1); 228*287e80b3SSadaf Ebrahimi } 229*287e80b3SSadaf Ebrahimi ax[cnt].type = TRACEFS_HIST_KEY_BUCKETS; 230*287e80b3SSadaf Ebrahimi ax[cnt].cnt = atoi(&att[8]); 231*287e80b3SSadaf Ebrahimi } else { 232*287e80b3SSadaf Ebrahimi fprintf(stderr, "Undefined attribute '%s'\n", att); 233*287e80b3SSadaf Ebrahimi fprintf(stderr," Acceptable attributes:\n"); 234*287e80b3SSadaf Ebrahimi fprintf(stderr," hex, sym, sym_offset, syscall, exe, log, usecs\n"); 235*287e80b3SSadaf Ebrahimi exit(-1); 236*287e80b3SSadaf Ebrahimi } 237*287e80b3SSadaf Ebrahimi } 238*287e80b3SSadaf Ebrahimi cnt++; 239*287e80b3SSadaf Ebrahimi } 240*287e80b3SSadaf Ebrahimi return cnt; 241*287e80b3SSadaf Ebrahimi} 242*287e80b3SSadaf Ebrahimi 243*287e80b3SSadaf Ebrahimistatic void process_hist(enum commands cmd, const char *instance_name, 244*287e80b3SSadaf Ebrahimi char *group, char *keys, char *vals, char *sort, 245*287e80b3SSadaf Ebrahimi char *ascend, char *desc) 246*287e80b3SSadaf Ebrahimi{ 247*287e80b3SSadaf Ebrahimi struct tracefs_instance *instance = NULL; 248*287e80b3SSadaf Ebrahimi struct tracefs_hist *hist; 249*287e80b3SSadaf Ebrahimi struct tep_handle *tep; 250*287e80b3SSadaf Ebrahimi struct tracefs_hist_axis_cnt *axes = NULL; 251*287e80b3SSadaf Ebrahimi char *system; 252*287e80b3SSadaf Ebrahimi char *event; 253*287e80b3SSadaf Ebrahimi char *sav; 254*287e80b3SSadaf Ebrahimi char *val; 255*287e80b3SSadaf Ebrahimi int ret; 256*287e80b3SSadaf Ebrahimi int cnt; 257*287e80b3SSadaf Ebrahimi 258*287e80b3SSadaf Ebrahimi if (instance_name) { 259*287e80b3SSadaf Ebrahimi instance = tracefs_instance_create(instance_name); 260*287e80b3SSadaf Ebrahimi if (!instance) { 261*287e80b3SSadaf Ebrahimi fprintf(stderr, "Failed instance create\n"); 262*287e80b3SSadaf Ebrahimi exit(-1); 263*287e80b3SSadaf Ebrahimi } 264*287e80b3SSadaf Ebrahimi } 265*287e80b3SSadaf Ebrahimi 266*287e80b3SSadaf Ebrahimi tep = tracefs_local_events(NULL); 267*287e80b3SSadaf Ebrahimi if (!tep) { 268*287e80b3SSadaf Ebrahimi perror("Could not read events"); 269*287e80b3SSadaf Ebrahimi exit(-1); 270*287e80b3SSadaf Ebrahimi } 271*287e80b3SSadaf Ebrahimi 272*287e80b3SSadaf Ebrahimi parse_system_event(group, &system, &event); 273*287e80b3SSadaf Ebrahimi 274*287e80b3SSadaf Ebrahimi if (cmd == SHOW) { 275*287e80b3SSadaf Ebrahimi char *content; 276*287e80b3SSadaf Ebrahimi content = tracefs_event_file_read(instance, system, event, 277*287e80b3SSadaf Ebrahimi "hist", NULL); 278*287e80b3SSadaf Ebrahimi if (!content) { 279*287e80b3SSadaf Ebrahimi perror("Reading hist file"); 280*287e80b3SSadaf Ebrahimi exit(-1); 281*287e80b3SSadaf Ebrahimi } 282*287e80b3SSadaf Ebrahimi printf("%s\n", content); 283*287e80b3SSadaf Ebrahimi free(content); 284*287e80b3SSadaf Ebrahimi return; 285*287e80b3SSadaf Ebrahimi } 286*287e80b3SSadaf Ebrahimi 287*287e80b3SSadaf Ebrahimi if (!keys) { 288*287e80b3SSadaf Ebrahimi fprintf(stderr, "Command needs -k option\n"); 289*287e80b3SSadaf Ebrahimi exit(-1); 290*287e80b3SSadaf Ebrahimi } 291*287e80b3SSadaf Ebrahimi 292*287e80b3SSadaf Ebrahimi cnt = parse_keys(keys, &axes); 293*287e80b3SSadaf Ebrahimi if (!cnt) { 294*287e80b3SSadaf Ebrahimi fprintf(stderr, "No keys??\n"); 295*287e80b3SSadaf Ebrahimi exit(-1); 296*287e80b3SSadaf Ebrahimi } 297*287e80b3SSadaf Ebrahimi 298*287e80b3SSadaf Ebrahimi /* buckets require the nd_cnt function */ 299*287e80b3SSadaf Ebrahimi switch (cnt) { 300*287e80b3SSadaf Ebrahimi case 2: 301*287e80b3SSadaf Ebrahimi if (axes[1].type == TRACEFS_HIST_KEY_BUCKETS) 302*287e80b3SSadaf Ebrahimi cnt = -1; 303*287e80b3SSadaf Ebrahimi /* fall through */ 304*287e80b3SSadaf Ebrahimi case 1: 305*287e80b3SSadaf Ebrahimi if (axes[0].type == TRACEFS_HIST_KEY_BUCKETS) 306*287e80b3SSadaf Ebrahimi cnt = -1; 307*287e80b3SSadaf Ebrahimi } 308*287e80b3SSadaf Ebrahimi 309*287e80b3SSadaf Ebrahimi /* Show examples of hist1d and hist2d */ 310*287e80b3SSadaf Ebrahimi switch (cnt) { 311*287e80b3SSadaf Ebrahimi case 1: 312*287e80b3SSadaf Ebrahimi hist = tracefs_hist_alloc(tep, system, event, 313*287e80b3SSadaf Ebrahimi axes[0].key, axes[0].type); 314*287e80b3SSadaf Ebrahimi break; 315*287e80b3SSadaf Ebrahimi case 2: 316*287e80b3SSadaf Ebrahimi hist = tracefs_hist_alloc_2d(tep, system, event, 317*287e80b3SSadaf Ebrahimi axes[0].key, axes[0].type, 318*287e80b3SSadaf Ebrahimi axes[1].key, axes[1].type); 319*287e80b3SSadaf Ebrahimi break; 320*287e80b3SSadaf Ebrahimi default: 321*287e80b3SSadaf Ebrahimi /* Really, 1 and 2 could use this too */ 322*287e80b3SSadaf Ebrahimi hist = tracefs_hist_alloc_nd_cnt(tep, system, event, axes); 323*287e80b3SSadaf Ebrahimi } 324*287e80b3SSadaf Ebrahimi if (!hist) { 325*287e80b3SSadaf Ebrahimi fprintf(stderr, "Failed hist create\n"); 326*287e80b3SSadaf Ebrahimi exit(-1); 327*287e80b3SSadaf Ebrahimi } 328*287e80b3SSadaf Ebrahimi 329*287e80b3SSadaf Ebrahimi if (vals) { 330*287e80b3SSadaf Ebrahimi sav = NULL; 331*287e80b3SSadaf Ebrahimi for (val = strtok_r(vals, ",", &sav); val; val = strtok_r(NULL, ",", &sav)) { 332*287e80b3SSadaf Ebrahimi ret = tracefs_hist_add_value(hist, val); 333*287e80b3SSadaf Ebrahimi if (ret) { 334*287e80b3SSadaf Ebrahimi fprintf(stderr, "Failed to add value %s\n", val); 335*287e80b3SSadaf Ebrahimi exit(-1); 336*287e80b3SSadaf Ebrahimi } 337*287e80b3SSadaf Ebrahimi } 338*287e80b3SSadaf Ebrahimi } 339*287e80b3SSadaf Ebrahimi 340*287e80b3SSadaf Ebrahimi if (sort) { 341*287e80b3SSadaf Ebrahimi sav = NULL; 342*287e80b3SSadaf Ebrahimi for (val = strtok_r(sort, ",", &sav); val; val = strtok_r(NULL, ",", &sav)) { 343*287e80b3SSadaf Ebrahimi ret = tracefs_hist_add_sort_key(hist, val); 344*287e80b3SSadaf Ebrahimi if (ret) { 345*287e80b3SSadaf Ebrahimi fprintf(stderr, "Failed to add sort key/val %s\n", val); 346*287e80b3SSadaf Ebrahimi exit(-1); 347*287e80b3SSadaf Ebrahimi } 348*287e80b3SSadaf Ebrahimi } 349*287e80b3SSadaf Ebrahimi } 350*287e80b3SSadaf Ebrahimi 351*287e80b3SSadaf Ebrahimi if (ascend) { 352*287e80b3SSadaf Ebrahimi sav = NULL; 353*287e80b3SSadaf Ebrahimi for (val = strtok_r(ascend, ",", &sav); val; val = strtok_r(NULL, ",", &sav)) { 354*287e80b3SSadaf Ebrahimi ret = tracefs_hist_sort_key_direction(hist, val, TRACEFS_HIST_SORT_ASCENDING); 355*287e80b3SSadaf Ebrahimi if (ret) { 356*287e80b3SSadaf Ebrahimi fprintf(stderr, "Failed to add ascending key/val %s\n", val); 357*287e80b3SSadaf Ebrahimi exit(-1); 358*287e80b3SSadaf Ebrahimi } 359*287e80b3SSadaf Ebrahimi } 360*287e80b3SSadaf Ebrahimi } 361*287e80b3SSadaf Ebrahimi 362*287e80b3SSadaf Ebrahimi if (desc) { 363*287e80b3SSadaf Ebrahimi sav = NULL; 364*287e80b3SSadaf Ebrahimi for (val = strtok_r(desc, ",", &sav); val; val = strtok_r(NULL, ",", &sav)) { 365*287e80b3SSadaf Ebrahimi ret = tracefs_hist_sort_key_direction(hist, val, TRACEFS_HIST_SORT_DESCENDING); 366*287e80b3SSadaf Ebrahimi if (ret) { 367*287e80b3SSadaf Ebrahimi fprintf(stderr, "Failed to add descending key/val %s\n", val); 368*287e80b3SSadaf Ebrahimi exit(-1); 369*287e80b3SSadaf Ebrahimi } 370*287e80b3SSadaf Ebrahimi } 371*287e80b3SSadaf Ebrahimi } 372*287e80b3SSadaf Ebrahimi 373*287e80b3SSadaf Ebrahimi tracefs_error_clear(instance); 374*287e80b3SSadaf Ebrahimi 375*287e80b3SSadaf Ebrahimi switch (cmd) { 376*287e80b3SSadaf Ebrahimi case START: 377*287e80b3SSadaf Ebrahimi ret = tracefs_hist_start(instance, hist); 378*287e80b3SSadaf Ebrahimi if (ret) { 379*287e80b3SSadaf Ebrahimi char *err = tracefs_error_last(instance); 380*287e80b3SSadaf Ebrahimi if (err) 381*287e80b3SSadaf Ebrahimi fprintf(stderr, "\n%s\n", err); 382*287e80b3SSadaf Ebrahimi } 383*287e80b3SSadaf Ebrahimi break; 384*287e80b3SSadaf Ebrahimi case PAUSE: 385*287e80b3SSadaf Ebrahimi ret = tracefs_hist_pause(instance, hist); 386*287e80b3SSadaf Ebrahimi break; 387*287e80b3SSadaf Ebrahimi case CONT: 388*287e80b3SSadaf Ebrahimi ret = tracefs_hist_continue(instance, hist); 389*287e80b3SSadaf Ebrahimi break; 390*287e80b3SSadaf Ebrahimi case RESET: 391*287e80b3SSadaf Ebrahimi ret = tracefs_hist_reset(instance, hist); 392*287e80b3SSadaf Ebrahimi break; 393*287e80b3SSadaf Ebrahimi case DELETE: 394*287e80b3SSadaf Ebrahimi ret = tracefs_hist_destroy(instance, hist); 395*287e80b3SSadaf Ebrahimi break; 396*287e80b3SSadaf Ebrahimi case SHOW: 397*287e80b3SSadaf Ebrahimi /* Show was already done */ 398*287e80b3SSadaf Ebrahimi break; 399*287e80b3SSadaf Ebrahimi } 400*287e80b3SSadaf Ebrahimi if (ret) 401*287e80b3SSadaf Ebrahimi fprintf(stderr, "Failed: command\n"); 402*287e80b3SSadaf Ebrahimi exit(ret); 403*287e80b3SSadaf Ebrahimi} 404*287e80b3SSadaf Ebrahimi 405*287e80b3SSadaf Ebrahimiint main (int argc, char **argv, char **env) 406*287e80b3SSadaf Ebrahimi{ 407*287e80b3SSadaf Ebrahimi enum commands cmd; 408*287e80b3SSadaf Ebrahimi char *instance = NULL; 409*287e80b3SSadaf Ebrahimi char *cmd_str; 410*287e80b3SSadaf Ebrahimi char *event = NULL; 411*287e80b3SSadaf Ebrahimi char *keys = NULL; 412*287e80b3SSadaf Ebrahimi char *vals = NULL; 413*287e80b3SSadaf Ebrahimi char *sort = NULL; 414*287e80b3SSadaf Ebrahimi char *desc = NULL; 415*287e80b3SSadaf Ebrahimi char *ascend = NULL; 416*287e80b3SSadaf Ebrahimi 417*287e80b3SSadaf Ebrahimi if (argc < 2) { 418*287e80b3SSadaf Ebrahimi fprintf(stderr, "usage: %s command [-B instance][-e [system/]event][-k keys][-v vals][-s sort]\n", argv[0]); 419*287e80b3SSadaf Ebrahimi fprintf(stderr, " [-a ascending][-d descending]\n"); 420*287e80b3SSadaf Ebrahimi exit(-1); 421*287e80b3SSadaf Ebrahimi } 422*287e80b3SSadaf Ebrahimi 423*287e80b3SSadaf Ebrahimi cmd_str = argv[1]; 424*287e80b3SSadaf Ebrahimi 425*287e80b3SSadaf Ebrahimi if (!strcmp(cmd_str, "start")) 426*287e80b3SSadaf Ebrahimi cmd = START; 427*287e80b3SSadaf Ebrahimi else if (!strcmp(cmd_str, "pause")) 428*287e80b3SSadaf Ebrahimi cmd = PAUSE; 429*287e80b3SSadaf Ebrahimi else if (!strcmp(cmd_str, "cont")) 430*287e80b3SSadaf Ebrahimi cmd = CONT; 431*287e80b3SSadaf Ebrahimi else if (!strcmp(cmd_str, "reset")) 432*287e80b3SSadaf Ebrahimi cmd = RESET; 433*287e80b3SSadaf Ebrahimi else if (!strcmp(cmd_str, "delete")) 434*287e80b3SSadaf Ebrahimi cmd = DELETE; 435*287e80b3SSadaf Ebrahimi else if (!strcmp(cmd_str, "show")) 436*287e80b3SSadaf Ebrahimi cmd = SHOW; 437*287e80b3SSadaf Ebrahimi else { 438*287e80b3SSadaf Ebrahimi fprintf(stderr, "Unknown command %s\n", cmd_str); 439*287e80b3SSadaf Ebrahimi exit(-1); 440*287e80b3SSadaf Ebrahimi } 441*287e80b3SSadaf Ebrahimi 442*287e80b3SSadaf Ebrahimi for (;;) { 443*287e80b3SSadaf Ebrahimi int c; 444*287e80b3SSadaf Ebrahimi 445*287e80b3SSadaf Ebrahimi c = getopt(argc - 1, argv + 1, "e:k:v:B:s:d:a:"); 446*287e80b3SSadaf Ebrahimi if (c == -1) 447*287e80b3SSadaf Ebrahimi break; 448*287e80b3SSadaf Ebrahimi 449*287e80b3SSadaf Ebrahimi switch (c) { 450*287e80b3SSadaf Ebrahimi case 'e': 451*287e80b3SSadaf Ebrahimi event = optarg; 452*287e80b3SSadaf Ebrahimi break; 453*287e80b3SSadaf Ebrahimi case 'k': 454*287e80b3SSadaf Ebrahimi keys = optarg; 455*287e80b3SSadaf Ebrahimi break; 456*287e80b3SSadaf Ebrahimi case 'v': 457*287e80b3SSadaf Ebrahimi vals = optarg; 458*287e80b3SSadaf Ebrahimi break; 459*287e80b3SSadaf Ebrahimi case 'B': 460*287e80b3SSadaf Ebrahimi instance = optarg; 461*287e80b3SSadaf Ebrahimi break; 462*287e80b3SSadaf Ebrahimi case 's': 463*287e80b3SSadaf Ebrahimi sort = optarg; 464*287e80b3SSadaf Ebrahimi break; 465*287e80b3SSadaf Ebrahimi case 'd': 466*287e80b3SSadaf Ebrahimi desc = optarg; 467*287e80b3SSadaf Ebrahimi break; 468*287e80b3SSadaf Ebrahimi case 'a': 469*287e80b3SSadaf Ebrahimi ascend = optarg; 470*287e80b3SSadaf Ebrahimi break; 471*287e80b3SSadaf Ebrahimi } 472*287e80b3SSadaf Ebrahimi } 473*287e80b3SSadaf Ebrahimi if (!event) { 474*287e80b3SSadaf Ebrahimi event = "kmem/kmalloc"; 475*287e80b3SSadaf Ebrahimi if (!keys) 476*287e80b3SSadaf Ebrahimi keys = "call_site.sym,bytes_req"; 477*287e80b3SSadaf Ebrahimi if (!vals) 478*287e80b3SSadaf Ebrahimi vals = "bytes_alloc"; 479*287e80b3SSadaf Ebrahimi if (!sort) 480*287e80b3SSadaf Ebrahimi sort = "bytes_req,bytes_alloc"; 481*287e80b3SSadaf Ebrahimi if (!desc) 482*287e80b3SSadaf Ebrahimi desc = "bytes_alloc"; 483*287e80b3SSadaf Ebrahimi } 484*287e80b3SSadaf Ebrahimi process_hist(cmd, instance, event, keys, vals, sort, ascend, desc); 485*287e80b3SSadaf Ebrahimi} 486*287e80b3SSadaf Ebrahimi 487*287e80b3SSadaf Ebrahimi-- 488*287e80b3SSadaf Ebrahimi 489*287e80b3SSadaf EbrahimiFILES 490*287e80b3SSadaf Ebrahimi----- 491*287e80b3SSadaf Ebrahimi[verse] 492*287e80b3SSadaf Ebrahimi-- 493*287e80b3SSadaf Ebrahimi*tracefs.h* 494*287e80b3SSadaf Ebrahimi Header file to include in order to have access to the library APIs. 495*287e80b3SSadaf Ebrahimi*-ltracefs* 496*287e80b3SSadaf Ebrahimi Linker switch to add when building a program that uses the library. 497*287e80b3SSadaf Ebrahimi-- 498*287e80b3SSadaf Ebrahimi 499*287e80b3SSadaf EbrahimiSEE ALSO 500*287e80b3SSadaf Ebrahimi-------- 501*287e80b3SSadaf Ebrahimi*libtracefs*(3), 502*287e80b3SSadaf Ebrahimi*libtraceevent*(3), 503*287e80b3SSadaf Ebrahimi*trace-cmd*(1), 504*287e80b3SSadaf Ebrahimi*tracefs_hist_pause*(3), 505*287e80b3SSadaf Ebrahimi*tracefs_hist_continue*(3), 506*287e80b3SSadaf Ebrahimi*tracefs_hist_reset*(3) 507*287e80b3SSadaf Ebrahimi 508*287e80b3SSadaf EbrahimiAUTHOR 509*287e80b3SSadaf Ebrahimi------ 510*287e80b3SSadaf Ebrahimi[verse] 511*287e80b3SSadaf Ebrahimi-- 512*287e80b3SSadaf Ebrahimi*Steven Rostedt* <[email protected]> 513*287e80b3SSadaf Ebrahimi*Tzvetomir Stoyanov* <[email protected]> 514*287e80b3SSadaf Ebrahimi*sameeruddin shaik* <[email protected]> 515*287e80b3SSadaf Ebrahimi-- 516*287e80b3SSadaf EbrahimiREPORTING BUGS 517*287e80b3SSadaf Ebrahimi-------------- 518*287e80b3SSadaf EbrahimiReport bugs to <[email protected]> 519*287e80b3SSadaf Ebrahimi 520*287e80b3SSadaf EbrahimiLICENSE 521*287e80b3SSadaf Ebrahimi------- 522*287e80b3SSadaf Ebrahimilibtracefs is Free Software licensed under the GNU LGPL 2.1 523*287e80b3SSadaf Ebrahimi 524*287e80b3SSadaf EbrahimiRESOURCES 525*287e80b3SSadaf Ebrahimi--------- 526*287e80b3SSadaf Ebrahimihttps://git.kernel.org/pub/scm/libs/libtrace/libtracefs.git/ 527*287e80b3SSadaf Ebrahimi 528*287e80b3SSadaf EbrahimiCOPYING 529*287e80b3SSadaf Ebrahimi------- 530*287e80b3SSadaf EbrahimiCopyright \(C) 2020 VMware, Inc. Free use of this software is granted under 531*287e80b3SSadaf Ebrahimithe terms of the GNU Public License (GPL). 532