1*4882a593Smuzhiyun.. SPDX-License-Identifier: GPL-2.0 2*4882a593Smuzhiyun 3*4882a593Smuzhiyun====================== 4*4882a593SmuzhiyunHistogram Design Notes 5*4882a593Smuzhiyun====================== 6*4882a593Smuzhiyun 7*4882a593Smuzhiyun:Author: Tom Zanussi <zanussi@kernel.org> 8*4882a593Smuzhiyun 9*4882a593SmuzhiyunThis document attempts to provide a description of how the ftrace 10*4882a593Smuzhiyunhistograms work and how the individual pieces map to the data 11*4882a593Smuzhiyunstructures used to implement them in trace_events_hist.c and 12*4882a593Smuzhiyuntracing_map.c. 13*4882a593Smuzhiyun 14*4882a593SmuzhiyunNote: All the ftrace histogram command examples assume the working 15*4882a593Smuzhiyun directory is the ftrace /tracing directory. For example:: 16*4882a593Smuzhiyun 17*4882a593Smuzhiyun # cd /sys/kernel/debug/tracing 18*4882a593Smuzhiyun 19*4882a593SmuzhiyunAlso, the histogram output displayed for those commands will be 20*4882a593Smuzhiyungenerally be truncated - only enough to make the point is displayed. 21*4882a593Smuzhiyun 22*4882a593Smuzhiyun'hist_debug' trace event files 23*4882a593Smuzhiyun============================== 24*4882a593Smuzhiyun 25*4882a593SmuzhiyunIf the kernel is compiled with CONFIG_HIST_TRIGGERS_DEBUG set, an 26*4882a593Smuzhiyunevent file named 'hist_debug' will appear in each event's 27*4882a593Smuzhiyunsubdirectory. This file can be read at any time and will display some 28*4882a593Smuzhiyunof the hist trigger internals described in this document. Specific 29*4882a593Smuzhiyunexamples and output will be described in test cases below. 30*4882a593Smuzhiyun 31*4882a593SmuzhiyunBasic histograms 32*4882a593Smuzhiyun================ 33*4882a593Smuzhiyun 34*4882a593SmuzhiyunFirst, basic histograms. Below is pretty much the simplest thing you 35*4882a593Smuzhiyuncan do with histograms - create one with a single key on a single 36*4882a593Smuzhiyunevent and cat the output:: 37*4882a593Smuzhiyun 38*4882a593Smuzhiyun # echo 'hist:keys=pid' >> events/sched/sched_waking/trigger 39*4882a593Smuzhiyun 40*4882a593Smuzhiyun # cat events/sched/sched_waking/hist 41*4882a593Smuzhiyun 42*4882a593Smuzhiyun { pid: 18249 } hitcount: 1 43*4882a593Smuzhiyun { pid: 13399 } hitcount: 1 44*4882a593Smuzhiyun { pid: 17973 } hitcount: 1 45*4882a593Smuzhiyun { pid: 12572 } hitcount: 1 46*4882a593Smuzhiyun ... 47*4882a593Smuzhiyun { pid: 10 } hitcount: 921 48*4882a593Smuzhiyun { pid: 18255 } hitcount: 1444 49*4882a593Smuzhiyun { pid: 25526 } hitcount: 2055 50*4882a593Smuzhiyun { pid: 5257 } hitcount: 2055 51*4882a593Smuzhiyun { pid: 27367 } hitcount: 2055 52*4882a593Smuzhiyun { pid: 1728 } hitcount: 2161 53*4882a593Smuzhiyun 54*4882a593Smuzhiyun Totals: 55*4882a593Smuzhiyun Hits: 21305 56*4882a593Smuzhiyun Entries: 183 57*4882a593Smuzhiyun Dropped: 0 58*4882a593Smuzhiyun 59*4882a593SmuzhiyunWhat this does is create a histogram on the sched_waking event using 60*4882a593Smuzhiyunpid as a key and with a single value, hitcount, which even if not 61*4882a593Smuzhiyunexplicitly specified, exists for every histogram regardless. 62*4882a593Smuzhiyun 63*4882a593SmuzhiyunThe hitcount value is a per-bucket value that's automatically 64*4882a593Smuzhiyunincremented on every hit for the given key, which in this case is the 65*4882a593Smuzhiyunpid. 66*4882a593Smuzhiyun 67*4882a593SmuzhiyunSo in this histogram, there's a separate bucket for each pid, and each 68*4882a593Smuzhiyunbucket contains a value for that bucket, counting the number of times 69*4882a593Smuzhiyunsched_waking was called for that pid. 70*4882a593Smuzhiyun 71*4882a593SmuzhiyunEach histogram is represented by a hist_data struct. 72*4882a593Smuzhiyun 73*4882a593SmuzhiyunTo keep track of each key and value field in the histogram, hist_data 74*4882a593Smuzhiyunkeeps an array of these fields named fields[]. The fields[] array is 75*4882a593Smuzhiyunan array containing struct hist_field representations of each 76*4882a593Smuzhiyunhistogram val and key in the histogram (variables are also included 77*4882a593Smuzhiyunhere, but are discussed later). So for the above histogram we have one 78*4882a593Smuzhiyunkey and one value; in this case the one value is the hitcount value, 79*4882a593Smuzhiyunwhich all histograms have, regardless of whether they define that 80*4882a593Smuzhiyunvalue or not, which the above histogram does not. 81*4882a593Smuzhiyun 82*4882a593SmuzhiyunEach struct hist_field contains a pointer to the ftrace_event_field 83*4882a593Smuzhiyunfrom the event's trace_event_file along with various bits related to 84*4882a593Smuzhiyunthat such as the size, offset, type, and a hist_field_fn_t function, 85*4882a593Smuzhiyunwhich is used to grab the field's data from the ftrace event buffer 86*4882a593Smuzhiyun(in most cases - some hist_fields such as hitcount don't directly map 87*4882a593Smuzhiyunto an event field in the trace buffer - in these cases the function 88*4882a593Smuzhiyunimplementation gets its value from somewhere else). The flags field 89*4882a593Smuzhiyunindicates which type of field it is - key, value, variable, variable 90*4882a593Smuzhiyunreference, etc., with value being the default. 91*4882a593Smuzhiyun 92*4882a593SmuzhiyunThe other important hist_data data structure in addition to the 93*4882a593Smuzhiyunfields[] array is the tracing_map instance created for the histogram, 94*4882a593Smuzhiyunwhich is held in the .map member. The tracing_map implements the 95*4882a593Smuzhiyunlock-free hash table used to implement histograms (see 96*4882a593Smuzhiyunkernel/trace/tracing_map.h for much more discussion about the 97*4882a593Smuzhiyunlow-level data structures implementing the tracing_map). For the 98*4882a593Smuzhiyunpurposes of this discussion, the tracing_map contains a number of 99*4882a593Smuzhiyunbuckets, each bucket corresponding to a particular tracing_map_elt 100*4882a593Smuzhiyunobject hashed by a given histogram key. 101*4882a593Smuzhiyun 102*4882a593SmuzhiyunBelow is a diagram the first part of which describes the hist_data and 103*4882a593Smuzhiyunassociated key and value fields for the histogram described above. As 104*4882a593Smuzhiyunyou can see, there are two fields in the fields array, one val field 105*4882a593Smuzhiyunfor the hitcount and one key field for the pid key. 106*4882a593Smuzhiyun 107*4882a593SmuzhiyunBelow that is a diagram of a run-time snapshot of what the tracing_map 108*4882a593Smuzhiyunmight look like for a given run. It attempts to show the 109*4882a593Smuzhiyunrelationships between the hist_data fields and the tracing_map 110*4882a593Smuzhiyunelements for a couple hypothetical keys and values.:: 111*4882a593Smuzhiyun 112*4882a593Smuzhiyun +------------------+ 113*4882a593Smuzhiyun | hist_data | 114*4882a593Smuzhiyun +------------------+ +----------------+ 115*4882a593Smuzhiyun | .fields[] |---->| val = hitcount |----------------------------+ 116*4882a593Smuzhiyun +----------------+ +----------------+ | 117*4882a593Smuzhiyun | .map | | .size | | 118*4882a593Smuzhiyun +----------------+ +--------------+ | 119*4882a593Smuzhiyun | .offset | | 120*4882a593Smuzhiyun +--------------+ | 121*4882a593Smuzhiyun | .fn() | | 122*4882a593Smuzhiyun +--------------+ | 123*4882a593Smuzhiyun . | 124*4882a593Smuzhiyun . | 125*4882a593Smuzhiyun . | 126*4882a593Smuzhiyun +----------------+ <--- n_vals | 127*4882a593Smuzhiyun | key = pid |----------------------------|--+ 128*4882a593Smuzhiyun +----------------+ | | 129*4882a593Smuzhiyun | .size | | | 130*4882a593Smuzhiyun +--------------+ | | 131*4882a593Smuzhiyun | .offset | | | 132*4882a593Smuzhiyun +--------------+ | | 133*4882a593Smuzhiyun | .fn() | | | 134*4882a593Smuzhiyun +----------------+ <--- n_fields | | 135*4882a593Smuzhiyun | unused | | | 136*4882a593Smuzhiyun +----------------+ | | 137*4882a593Smuzhiyun | | | | 138*4882a593Smuzhiyun +--------------+ | | 139*4882a593Smuzhiyun | | | | 140*4882a593Smuzhiyun +--------------+ | | 141*4882a593Smuzhiyun | | | | 142*4882a593Smuzhiyun +--------------+ | | 143*4882a593Smuzhiyun n_keys = n_fields - n_vals | | 144*4882a593Smuzhiyun 145*4882a593SmuzhiyunThe hist_data n_vals and n_fields delineate the extent of the fields[] | | 146*4882a593Smuzhiyunarray and separate keys from values for the rest of the code. | | 147*4882a593Smuzhiyun 148*4882a593SmuzhiyunBelow is a run-time representation of the tracing_map part of the | | 149*4882a593Smuzhiyunhistogram, with pointers from various parts of the fields[] array | | 150*4882a593Smuzhiyunto corresponding parts of the tracing_map. | | 151*4882a593Smuzhiyun 152*4882a593SmuzhiyunThe tracing_map consists of an array of tracing_map_entrys and a set | | 153*4882a593Smuzhiyunof preallocated tracing_map_elts (abbreviated below as map_entry and | | 154*4882a593Smuzhiyunmap_elt). The total number of map_entrys in the hist_data.map array = | | 155*4882a593Smuzhiyunmap->max_elts (actually map->map_size but only max_elts of those are | | 156*4882a593Smuzhiyunused. This is a property required by the map_insert() algorithm). | | 157*4882a593Smuzhiyun 158*4882a593SmuzhiyunIf a map_entry is unused, meaning no key has yet hashed into it, its | | 159*4882a593Smuzhiyun.key value is 0 and its .val pointer is NULL. Once a map_entry has | | 160*4882a593Smuzhiyunbeen claimed, the .key value contains the key's hash value and the | | 161*4882a593Smuzhiyun.val member points to a map_elt containing the full key and an entry | | 162*4882a593Smuzhiyunfor each key or value in the map_elt.fields[] array. There is an | | 163*4882a593Smuzhiyunentry in the map_elt.fields[] array corresponding to each hist_field | | 164*4882a593Smuzhiyunin the histogram, and this is where the continually aggregated sums | | 165*4882a593Smuzhiyuncorresponding to each histogram value are kept. | | 166*4882a593Smuzhiyun 167*4882a593SmuzhiyunThe diagram attempts to show the relationship between the | | 168*4882a593Smuzhiyunhist_data.fields[] and the map_elt.fields[] with the links drawn | | 169*4882a593Smuzhiyunbetween diagrams:: 170*4882a593Smuzhiyun 171*4882a593Smuzhiyun +-----------+ | | 172*4882a593Smuzhiyun | hist_data | | | 173*4882a593Smuzhiyun +-----------+ | | 174*4882a593Smuzhiyun | .fields | | | 175*4882a593Smuzhiyun +---------+ +-----------+ | | 176*4882a593Smuzhiyun | .map |---->| map_entry | | | 177*4882a593Smuzhiyun +---------+ +-----------+ | | 178*4882a593Smuzhiyun | .key |---> 0 | | 179*4882a593Smuzhiyun +---------+ | | 180*4882a593Smuzhiyun | .val |---> NULL | | 181*4882a593Smuzhiyun +-----------+ | | 182*4882a593Smuzhiyun | map_entry | | | 183*4882a593Smuzhiyun +-----------+ | | 184*4882a593Smuzhiyun | .key |---> pid = 999 | | 185*4882a593Smuzhiyun +---------+ +-----------+ | | 186*4882a593Smuzhiyun | .val |--->| map_elt | | | 187*4882a593Smuzhiyun +---------+ +-----------+ | | 188*4882a593Smuzhiyun . | .key |---> full key * | | 189*4882a593Smuzhiyun . +---------+ +---------------+ | | 190*4882a593Smuzhiyun . | .fields |--->| .sum (val) |<-+ | 191*4882a593Smuzhiyun +-----------+ +---------+ | 2345 | | | 192*4882a593Smuzhiyun | map_entry | +---------------+ | | 193*4882a593Smuzhiyun +-----------+ | .offset (key) |<----+ 194*4882a593Smuzhiyun | .key |---> 0 | 0 | | | 195*4882a593Smuzhiyun +---------+ +---------------+ | | 196*4882a593Smuzhiyun | .val |---> NULL . | | 197*4882a593Smuzhiyun +-----------+ . | | 198*4882a593Smuzhiyun | map_entry | . | | 199*4882a593Smuzhiyun +-----------+ +---------------+ | | 200*4882a593Smuzhiyun | .key | | .sum (val) or | | | 201*4882a593Smuzhiyun +---------+ +---------+ | .offset (key) | | | 202*4882a593Smuzhiyun | .val |--->| map_elt | +---------------+ | | 203*4882a593Smuzhiyun +-----------+ +---------+ | .sum (val) or | | | 204*4882a593Smuzhiyun | map_entry | | .offset (key) | | | 205*4882a593Smuzhiyun +-----------+ +---------------+ | | 206*4882a593Smuzhiyun | .key |---> pid = 4444 | | 207*4882a593Smuzhiyun +---------+ +-----------+ | | 208*4882a593Smuzhiyun | .val | | map_elt | | | 209*4882a593Smuzhiyun +---------+ +-----------+ | | 210*4882a593Smuzhiyun | .key |---> full key * | | 211*4882a593Smuzhiyun +---------+ +---------------+ | | 212*4882a593Smuzhiyun | .fields |--->| .sum (val) |<-+ | 213*4882a593Smuzhiyun +---------+ | 65523 | | 214*4882a593Smuzhiyun +---------------+ | 215*4882a593Smuzhiyun | .offset (key) |<----+ 216*4882a593Smuzhiyun | 0 | 217*4882a593Smuzhiyun +---------------+ 218*4882a593Smuzhiyun . 219*4882a593Smuzhiyun . 220*4882a593Smuzhiyun . 221*4882a593Smuzhiyun +---------------+ 222*4882a593Smuzhiyun | .sum (val) or | 223*4882a593Smuzhiyun | .offset (key) | 224*4882a593Smuzhiyun +---------------+ 225*4882a593Smuzhiyun | .sum (val) or | 226*4882a593Smuzhiyun | .offset (key) | 227*4882a593Smuzhiyun +---------------+ 228*4882a593Smuzhiyun 229*4882a593SmuzhiyunAbbreviations used in the diagrams:: 230*4882a593Smuzhiyun 231*4882a593Smuzhiyun hist_data = struct hist_trigger_data 232*4882a593Smuzhiyun hist_data.fields = struct hist_field 233*4882a593Smuzhiyun fn = hist_field_fn_t 234*4882a593Smuzhiyun map_entry = struct tracing_map_entry 235*4882a593Smuzhiyun map_elt = struct tracing_map_elt 236*4882a593Smuzhiyun map_elt.fields = struct tracing_map_field 237*4882a593Smuzhiyun 238*4882a593SmuzhiyunWhenever a new event occurs and it has a hist trigger associated with 239*4882a593Smuzhiyunit, event_hist_trigger() is called. event_hist_trigger() first deals 240*4882a593Smuzhiyunwith the key: for each subkey in the key (in the above example, there 241*4882a593Smuzhiyunis just one subkey corresponding to pid), the hist_field that 242*4882a593Smuzhiyunrepresents that subkey is retrieved from hist_data.fields[] and the 243*4882a593Smuzhiyunhist_field_fn_t fn() associated with that field, along with the 244*4882a593Smuzhiyunfield's size and offset, is used to grab that subkey's data from the 245*4882a593Smuzhiyuncurrent trace record. 246*4882a593Smuzhiyun 247*4882a593SmuzhiyunOnce the complete key has been retrieved, it's used to look that key 248*4882a593Smuzhiyunup in the tracing_map. If there's no tracing_map_elt associated with 249*4882a593Smuzhiyunthat key, an empty one is claimed and inserted in the map for the new 250*4882a593Smuzhiyunkey. In either case, the tracing_map_elt associated with that key is 251*4882a593Smuzhiyunreturned. 252*4882a593Smuzhiyun 253*4882a593SmuzhiyunOnce a tracing_map_elt available, hist_trigger_elt_update() is called. 254*4882a593SmuzhiyunAs the name implies, this updates the element, which basically means 255*4882a593Smuzhiyunupdating the element's fields. There's a tracing_map_field associated 256*4882a593Smuzhiyunwith each key and value in the histogram, and each of these correspond 257*4882a593Smuzhiyunto the key and value hist_fields created when the histogram was 258*4882a593Smuzhiyuncreated. hist_trigger_elt_update() goes through each value hist_field 259*4882a593Smuzhiyunand, as for the keys, uses the hist_field's fn() and size and offset 260*4882a593Smuzhiyunto grab the field's value from the current trace record. Once it has 261*4882a593Smuzhiyunthat value, it simply adds that value to that field's 262*4882a593Smuzhiyuncontinually-updated tracing_map_field.sum member. Some hist_field 263*4882a593Smuzhiyunfn()s, such as for the hitcount, don't actually grab anything from the 264*4882a593Smuzhiyuntrace record (the hitcount fn() just increments the counter sum by 1), 265*4882a593Smuzhiyunbut the idea is the same. 266*4882a593Smuzhiyun 267*4882a593SmuzhiyunOnce all the values have been updated, hist_trigger_elt_update() is 268*4882a593Smuzhiyundone and returns. Note that there are also tracing_map_fields for 269*4882a593Smuzhiyuneach subkey in the key, but hist_trigger_elt_update() doesn't look at 270*4882a593Smuzhiyunthem or update anything - those exist only for sorting, which can 271*4882a593Smuzhiyunhappen later. 272*4882a593Smuzhiyun 273*4882a593SmuzhiyunBasic histogram test 274*4882a593Smuzhiyun-------------------- 275*4882a593Smuzhiyun 276*4882a593SmuzhiyunThis is a good example to try. It produces 3 value fields and 2 key 277*4882a593Smuzhiyunfields in the output:: 278*4882a593Smuzhiyun 279*4882a593Smuzhiyun # echo 'hist:keys=common_pid,call_site.sym:values=bytes_req,bytes_alloc,hitcount' >> events/kmem/kmalloc/trigger 280*4882a593Smuzhiyun 281*4882a593SmuzhiyunTo see the debug data, cat the kmem/kmalloc's 'hist_debug' file. It 282*4882a593Smuzhiyunwill show the trigger info of the histogram it corresponds to, along 283*4882a593Smuzhiyunwith the address of the hist_data associated with the histogram, which 284*4882a593Smuzhiyunwill become useful in later examples. It then displays the number of 285*4882a593Smuzhiyuntotal hist_fields associated with the histogram along with a count of 286*4882a593Smuzhiyunhow many of those correspond to keys and how many correspond to values. 287*4882a593Smuzhiyun 288*4882a593SmuzhiyunIt then goes on to display details for each field, including the 289*4882a593Smuzhiyunfield's flags and the position of each field in the hist_data's 290*4882a593Smuzhiyunfields[] array, which is useful information for verifying that things 291*4882a593Smuzhiyuninternally appear correct or not, and which again will become even 292*4882a593Smuzhiyunmore useful in further examples:: 293*4882a593Smuzhiyun 294*4882a593Smuzhiyun # cat events/kmem/kmalloc/hist_debug 295*4882a593Smuzhiyun 296*4882a593Smuzhiyun # event histogram 297*4882a593Smuzhiyun # 298*4882a593Smuzhiyun # trigger info: hist:keys=common_pid,call_site.sym:vals=hitcount,bytes_req,bytes_alloc:sort=hitcount:size=2048 [active] 299*4882a593Smuzhiyun # 300*4882a593Smuzhiyun 301*4882a593Smuzhiyun hist_data: 000000005e48c9a5 302*4882a593Smuzhiyun 303*4882a593Smuzhiyun n_vals: 3 304*4882a593Smuzhiyun n_keys: 2 305*4882a593Smuzhiyun n_fields: 5 306*4882a593Smuzhiyun 307*4882a593Smuzhiyun val fields: 308*4882a593Smuzhiyun 309*4882a593Smuzhiyun hist_data->fields[0]: 310*4882a593Smuzhiyun flags: 311*4882a593Smuzhiyun VAL: HIST_FIELD_FL_HITCOUNT 312*4882a593Smuzhiyun type: u64 313*4882a593Smuzhiyun size: 8 314*4882a593Smuzhiyun is_signed: 0 315*4882a593Smuzhiyun 316*4882a593Smuzhiyun hist_data->fields[1]: 317*4882a593Smuzhiyun flags: 318*4882a593Smuzhiyun VAL: normal u64 value 319*4882a593Smuzhiyun ftrace_event_field name: bytes_req 320*4882a593Smuzhiyun type: size_t 321*4882a593Smuzhiyun size: 8 322*4882a593Smuzhiyun is_signed: 0 323*4882a593Smuzhiyun 324*4882a593Smuzhiyun hist_data->fields[2]: 325*4882a593Smuzhiyun flags: 326*4882a593Smuzhiyun VAL: normal u64 value 327*4882a593Smuzhiyun ftrace_event_field name: bytes_alloc 328*4882a593Smuzhiyun type: size_t 329*4882a593Smuzhiyun size: 8 330*4882a593Smuzhiyun is_signed: 0 331*4882a593Smuzhiyun 332*4882a593Smuzhiyun key fields: 333*4882a593Smuzhiyun 334*4882a593Smuzhiyun hist_data->fields[3]: 335*4882a593Smuzhiyun flags: 336*4882a593Smuzhiyun HIST_FIELD_FL_KEY 337*4882a593Smuzhiyun ftrace_event_field name: common_pid 338*4882a593Smuzhiyun type: int 339*4882a593Smuzhiyun size: 8 340*4882a593Smuzhiyun is_signed: 1 341*4882a593Smuzhiyun 342*4882a593Smuzhiyun hist_data->fields[4]: 343*4882a593Smuzhiyun flags: 344*4882a593Smuzhiyun HIST_FIELD_FL_KEY 345*4882a593Smuzhiyun ftrace_event_field name: call_site 346*4882a593Smuzhiyun type: unsigned long 347*4882a593Smuzhiyun size: 8 348*4882a593Smuzhiyun is_signed: 0 349*4882a593Smuzhiyun 350*4882a593SmuzhiyunThe commands below can be used to clean things up for the next test:: 351*4882a593Smuzhiyun 352*4882a593Smuzhiyun # echo '!hist:keys=common_pid,call_site.sym:values=bytes_req,bytes_alloc,hitcount' >> events/kmem/kmalloc/trigger 353*4882a593Smuzhiyun 354*4882a593SmuzhiyunVariables 355*4882a593Smuzhiyun========= 356*4882a593Smuzhiyun 357*4882a593SmuzhiyunVariables allow data from one hist trigger to be saved by one hist 358*4882a593Smuzhiyuntrigger and retrieved by another hist trigger. For example, a trigger 359*4882a593Smuzhiyunon the sched_waking event can capture a timestamp for a particular 360*4882a593Smuzhiyunpid, and later a sched_switch event that switches to that pid event 361*4882a593Smuzhiyuncan grab the timestamp and use it to calculate a time delta between 362*4882a593Smuzhiyunthe two events:: 363*4882a593Smuzhiyun 364*4882a593Smuzhiyun # echo 'hist:keys=pid:ts0=common_timestamp.usecs' >> 365*4882a593Smuzhiyun events/sched/sched_waking/trigger 366*4882a593Smuzhiyun 367*4882a593Smuzhiyun # echo 'hist:keys=next_pid:wakeup_lat=common_timestamp.usecs-$ts0' >> 368*4882a593Smuzhiyun events/sched/sched_switch/trigger 369*4882a593Smuzhiyun 370*4882a593SmuzhiyunIn terms of the histogram data structures, variables are implemented 371*4882a593Smuzhiyunas another type of hist_field and for a given hist trigger are added 372*4882a593Smuzhiyunto the hist_data.fields[] array just after all the val fields. To 373*4882a593Smuzhiyundistinguish them from the existing key and val fields, they're given a 374*4882a593Smuzhiyunnew flag type, HIST_FIELD_FL_VAR (abbreviated FL_VAR) and they also 375*4882a593Smuzhiyunmake use of a new .var.idx field member in struct hist_field, which 376*4882a593Smuzhiyunmaps them to an index in a new map_elt.vars[] array added to the 377*4882a593Smuzhiyunmap_elt specifically designed to store and retrieve variable values. 378*4882a593SmuzhiyunThe diagram below shows those new elements and adds a new variable 379*4882a593Smuzhiyunentry, ts0, corresponding to the ts0 variable in the sched_waking 380*4882a593Smuzhiyuntrigger above. 381*4882a593Smuzhiyun 382*4882a593Smuzhiyunsched_waking histogram 383*4882a593Smuzhiyun----------------------:: 384*4882a593Smuzhiyun 385*4882a593Smuzhiyun +------------------+ 386*4882a593Smuzhiyun | hist_data |<-------------------------------------------------------+ 387*4882a593Smuzhiyun +------------------+ +-------------------+ | 388*4882a593Smuzhiyun | .fields[] |-->| val = hitcount | | 389*4882a593Smuzhiyun +----------------+ +-------------------+ | 390*4882a593Smuzhiyun | .map | | .size | | 391*4882a593Smuzhiyun +----------------+ +-----------------+ | 392*4882a593Smuzhiyun | .offset | | 393*4882a593Smuzhiyun +-----------------+ | 394*4882a593Smuzhiyun | .fn() | | 395*4882a593Smuzhiyun +-----------------+ | 396*4882a593Smuzhiyun | .flags | | 397*4882a593Smuzhiyun +-----------------+ | 398*4882a593Smuzhiyun | .var.idx | | 399*4882a593Smuzhiyun +-------------------+ | 400*4882a593Smuzhiyun | var = ts0 | | 401*4882a593Smuzhiyun +-------------------+ | 402*4882a593Smuzhiyun | .size | | 403*4882a593Smuzhiyun +-----------------+ | 404*4882a593Smuzhiyun | .offset | | 405*4882a593Smuzhiyun +-----------------+ | 406*4882a593Smuzhiyun | .fn() | | 407*4882a593Smuzhiyun +-----------------+ | 408*4882a593Smuzhiyun | .flags & FL_VAR | | 409*4882a593Smuzhiyun +-----------------+ | 410*4882a593Smuzhiyun | .var.idx |----------------------------+-+ | 411*4882a593Smuzhiyun +-----------------+ | | | 412*4882a593Smuzhiyun . | | | 413*4882a593Smuzhiyun . | | | 414*4882a593Smuzhiyun . | | | 415*4882a593Smuzhiyun +-------------------+ <--- n_vals | | | 416*4882a593Smuzhiyun | key = pid | | | | 417*4882a593Smuzhiyun +-------------------+ | | | 418*4882a593Smuzhiyun | .size | | | | 419*4882a593Smuzhiyun +-----------------+ | | | 420*4882a593Smuzhiyun | .offset | | | | 421*4882a593Smuzhiyun +-----------------+ | | | 422*4882a593Smuzhiyun | .fn() | | | | 423*4882a593Smuzhiyun +-----------------+ | | | 424*4882a593Smuzhiyun | .flags & FL_KEY | | | | 425*4882a593Smuzhiyun +-----------------+ | | | 426*4882a593Smuzhiyun | .var.idx | | | | 427*4882a593Smuzhiyun +-------------------+ <--- n_fields | | | 428*4882a593Smuzhiyun | unused | | | | 429*4882a593Smuzhiyun +-------------------+ | | | 430*4882a593Smuzhiyun | | | | | 431*4882a593Smuzhiyun +-----------------+ | | | 432*4882a593Smuzhiyun | | | | | 433*4882a593Smuzhiyun +-----------------+ | | | 434*4882a593Smuzhiyun | | | | | 435*4882a593Smuzhiyun +-----------------+ | | | 436*4882a593Smuzhiyun | | | | | 437*4882a593Smuzhiyun +-----------------+ | | | 438*4882a593Smuzhiyun | | | | | 439*4882a593Smuzhiyun +-----------------+ | | | 440*4882a593Smuzhiyun n_keys = n_fields - n_vals | | | 441*4882a593Smuzhiyun | | | 442*4882a593Smuzhiyun 443*4882a593SmuzhiyunThis is very similar to the basic case. In the above diagram, we can | | | 444*4882a593Smuzhiyunsee a new .flags member has been added to the struct hist_field | | | 445*4882a593Smuzhiyunstruct, and a new entry added to hist_data.fields representing the ts0 | | | 446*4882a593Smuzhiyunvariable. For a normal val hist_field, .flags is just 0 (modulo | | | 447*4882a593Smuzhiyunmodifier flags), but if the value is defined as a variable, the .flags | | | 448*4882a593Smuzhiyuncontains a set FL_VAR bit. | | | 449*4882a593Smuzhiyun 450*4882a593SmuzhiyunAs you can see, the ts0 entry's .var.idx member contains the index | | | 451*4882a593Smuzhiyuninto the tracing_map_elts' .vars[] array containing variable values. | | | 452*4882a593SmuzhiyunThis idx is used whenever the value of the variable is set or read. | | | 453*4882a593SmuzhiyunThe map_elt.vars idx assigned to the given variable is assigned and | | | 454*4882a593Smuzhiyunsaved in .var.idx by create_tracing_map_fields() after it calls | | | 455*4882a593Smuzhiyuntracing_map_add_var(). | | | 456*4882a593Smuzhiyun 457*4882a593SmuzhiyunBelow is a representation of the histogram at run-time, which | | | 458*4882a593Smuzhiyunpopulates the map, along with correspondence to the above hist_data and | | | 459*4882a593Smuzhiyunhist_field data structures. | | | 460*4882a593Smuzhiyun 461*4882a593SmuzhiyunThe diagram attempts to show the relationship between the | | | 462*4882a593Smuzhiyunhist_data.fields[] and the map_elt.fields[] and map_elt.vars[] with | | | 463*4882a593Smuzhiyunthe links drawn between diagrams. For each of the map_elts, you can | | | 464*4882a593Smuzhiyunsee that the .fields[] members point to the .sum or .offset of a key | | | 465*4882a593Smuzhiyunor val and the .vars[] members point to the value of a variable. The | | | 466*4882a593Smuzhiyunarrows between the two diagrams show the linkages between those | | | 467*4882a593Smuzhiyuntracing_map members and the field definitions in the corresponding | | | 468*4882a593Smuzhiyunhist_data fields[] members.:: 469*4882a593Smuzhiyun 470*4882a593Smuzhiyun +-----------+ | | | 471*4882a593Smuzhiyun | hist_data | | | | 472*4882a593Smuzhiyun +-----------+ | | | 473*4882a593Smuzhiyun | .fields | | | | 474*4882a593Smuzhiyun +---------+ +-----------+ | | | 475*4882a593Smuzhiyun | .map |---->| map_entry | | | | 476*4882a593Smuzhiyun +---------+ +-----------+ | | | 477*4882a593Smuzhiyun | .key |---> 0 | | | 478*4882a593Smuzhiyun +---------+ | | | 479*4882a593Smuzhiyun | .val |---> NULL | | | 480*4882a593Smuzhiyun +-----------+ | | | 481*4882a593Smuzhiyun | map_entry | | | | 482*4882a593Smuzhiyun +-----------+ | | | 483*4882a593Smuzhiyun | .key |---> pid = 999 | | | 484*4882a593Smuzhiyun +---------+ +-----------+ | | | 485*4882a593Smuzhiyun | .val |--->| map_elt | | | | 486*4882a593Smuzhiyun +---------+ +-----------+ | | | 487*4882a593Smuzhiyun . | .key |---> full key * | | | 488*4882a593Smuzhiyun . +---------+ +---------------+ | | | 489*4882a593Smuzhiyun . | .fields |--->| .sum (val) | | | | 490*4882a593Smuzhiyun . +---------+ | 2345 | | | | 491*4882a593Smuzhiyun . +--| .vars | +---------------+ | | | 492*4882a593Smuzhiyun . | +---------+ | .offset (key) | | | | 493*4882a593Smuzhiyun . | | 0 | | | | 494*4882a593Smuzhiyun . | +---------------+ | | | 495*4882a593Smuzhiyun . | . | | | 496*4882a593Smuzhiyun . | . | | | 497*4882a593Smuzhiyun . | . | | | 498*4882a593Smuzhiyun . | +---------------+ | | | 499*4882a593Smuzhiyun . | | .sum (val) or | | | | 500*4882a593Smuzhiyun . | | .offset (key) | | | | 501*4882a593Smuzhiyun . | +---------------+ | | | 502*4882a593Smuzhiyun . | | .sum (val) or | | | | 503*4882a593Smuzhiyun . | | .offset (key) | | | | 504*4882a593Smuzhiyun . | +---------------+ | | | 505*4882a593Smuzhiyun . | | | | 506*4882a593Smuzhiyun . +---------------->+---------------+ | | | 507*4882a593Smuzhiyun . | ts0 |<--+ | | 508*4882a593Smuzhiyun . | 113345679876 | | | | 509*4882a593Smuzhiyun . +---------------+ | | | 510*4882a593Smuzhiyun . | unused | | | | 511*4882a593Smuzhiyun . | | | | | 512*4882a593Smuzhiyun . +---------------+ | | | 513*4882a593Smuzhiyun . . | | | 514*4882a593Smuzhiyun . . | | | 515*4882a593Smuzhiyun . . | | | 516*4882a593Smuzhiyun . +---------------+ | | | 517*4882a593Smuzhiyun . | unused | | | | 518*4882a593Smuzhiyun . | | | | | 519*4882a593Smuzhiyun . +---------------+ | | | 520*4882a593Smuzhiyun . | unused | | | | 521*4882a593Smuzhiyun . | | | | | 522*4882a593Smuzhiyun . +---------------+ | | | 523*4882a593Smuzhiyun . | | | 524*4882a593Smuzhiyun +-----------+ | | | 525*4882a593Smuzhiyun | map_entry | | | | 526*4882a593Smuzhiyun +-----------+ | | | 527*4882a593Smuzhiyun | .key |---> pid = 4444 | | | 528*4882a593Smuzhiyun +---------+ +-----------+ | | | 529*4882a593Smuzhiyun | .val |--->| map_elt | | | | 530*4882a593Smuzhiyun +---------+ +-----------+ | | | 531*4882a593Smuzhiyun . | .key |---> full key * | | | 532*4882a593Smuzhiyun . +---------+ +---------------+ | | | 533*4882a593Smuzhiyun . | .fields |--->| .sum (val) | | | | 534*4882a593Smuzhiyun +---------+ | 2345 | | | | 535*4882a593Smuzhiyun +--| .vars | +---------------+ | | | 536*4882a593Smuzhiyun | +---------+ | .offset (key) | | | | 537*4882a593Smuzhiyun | | 0 | | | | 538*4882a593Smuzhiyun | +---------------+ | | | 539*4882a593Smuzhiyun | . | | | 540*4882a593Smuzhiyun | . | | | 541*4882a593Smuzhiyun | . | | | 542*4882a593Smuzhiyun | +---------------+ | | | 543*4882a593Smuzhiyun | | .sum (val) or | | | | 544*4882a593Smuzhiyun | | .offset (key) | | | | 545*4882a593Smuzhiyun | +---------------+ | | | 546*4882a593Smuzhiyun | | .sum (val) or | | | | 547*4882a593Smuzhiyun | | .offset (key) | | | | 548*4882a593Smuzhiyun | +---------------+ | | | 549*4882a593Smuzhiyun | | | | 550*4882a593Smuzhiyun | +---------------+ | | | 551*4882a593Smuzhiyun +---------------->| ts0 |<--+ | | 552*4882a593Smuzhiyun | 213499240729 | | | 553*4882a593Smuzhiyun +---------------+ | | 554*4882a593Smuzhiyun | unused | | | 555*4882a593Smuzhiyun | | | | 556*4882a593Smuzhiyun +---------------+ | | 557*4882a593Smuzhiyun . | | 558*4882a593Smuzhiyun . | | 559*4882a593Smuzhiyun . | | 560*4882a593Smuzhiyun +---------------+ | | 561*4882a593Smuzhiyun | unused | | | 562*4882a593Smuzhiyun | | | | 563*4882a593Smuzhiyun +---------------+ | | 564*4882a593Smuzhiyun | unused | | | 565*4882a593Smuzhiyun | | | | 566*4882a593Smuzhiyun +---------------+ | | 567*4882a593Smuzhiyun 568*4882a593SmuzhiyunFor each used map entry, there's a map_elt pointing to an array of | | 569*4882a593Smuzhiyun.vars containing the current value of the variables associated with | | 570*4882a593Smuzhiyunthat histogram entry. So in the above, the timestamp associated with | | 571*4882a593Smuzhiyunpid 999 is 113345679876, and the timestamp variable in the same | | 572*4882a593Smuzhiyun.var.idx for pid 4444 is 213499240729. | | 573*4882a593Smuzhiyun 574*4882a593Smuzhiyunsched_switch histogram | | 575*4882a593Smuzhiyun---------------------- | | 576*4882a593Smuzhiyun 577*4882a593SmuzhiyunThe sched_switch histogram paired with the above sched_waking | | 578*4882a593Smuzhiyunhistogram is shown below. The most important aspect of the | | 579*4882a593Smuzhiyunsched_switch histogram is that it references a variable on the | | 580*4882a593Smuzhiyunsched_waking histogram above. | | 581*4882a593Smuzhiyun 582*4882a593SmuzhiyunThe histogram diagram is very similar to the others so far displayed, | | 583*4882a593Smuzhiyunbut it adds variable references. You can see the normal hitcount and | | 584*4882a593Smuzhiyunkey fields along with a new wakeup_lat variable implemented in the | | 585*4882a593Smuzhiyunsame way as the sched_waking ts0 variable, but in addition there's an | | 586*4882a593Smuzhiyunentry with the new FL_VAR_REF (short for HIST_FIELD_FL_VAR_REF) flag. | | 587*4882a593Smuzhiyun 588*4882a593SmuzhiyunAssociated with the new var ref field are a couple of new hist_field | | 589*4882a593Smuzhiyunmembers, var.hist_data and var_ref_idx. For a variable reference, the | | 590*4882a593Smuzhiyunvar.hist_data goes with the var.idx, which together uniquely identify | | 591*4882a593Smuzhiyuna particular variable on a particular histogram. The var_ref_idx is | | 592*4882a593Smuzhiyunjust the index into the var_ref_vals[] array that caches the values of | | 593*4882a593Smuzhiyuneach variable whenever a hist trigger is updated. Those resulting | | 594*4882a593Smuzhiyunvalues are then finally accessed by other code such as trace action | | 595*4882a593Smuzhiyuncode that uses the var_ref_idx values to assign param values. | | 596*4882a593Smuzhiyun 597*4882a593SmuzhiyunThe diagram below describes the situation for the sched_switch | | 598*4882a593Smuzhiyunhistogram referred to before:: 599*4882a593Smuzhiyun 600*4882a593Smuzhiyun # echo 'hist:keys=next_pid:wakeup_lat=common_timestamp.usecs-$ts0' >> | | 601*4882a593Smuzhiyun events/sched/sched_switch/trigger | | 602*4882a593Smuzhiyun | | 603*4882a593Smuzhiyun +------------------+ | | 604*4882a593Smuzhiyun | hist_data | | | 605*4882a593Smuzhiyun +------------------+ +-----------------------+ | | 606*4882a593Smuzhiyun | .fields[] |-->| val = hitcount | | | 607*4882a593Smuzhiyun +----------------+ +-----------------------+ | | 608*4882a593Smuzhiyun | .map | | .size | | | 609*4882a593Smuzhiyun +----------------+ +---------------------+ | | 610*4882a593Smuzhiyun +--| .var_refs[] | | .offset | | | 611*4882a593Smuzhiyun | +----------------+ +---------------------+ | | 612*4882a593Smuzhiyun | | .fn() | | | 613*4882a593Smuzhiyun | var_ref_vals[] +---------------------+ | | 614*4882a593Smuzhiyun | +-------------+ | .flags | | | 615*4882a593Smuzhiyun | | $ts0 |<---+ +---------------------+ | | 616*4882a593Smuzhiyun | +-------------+ | | .var.idx | | | 617*4882a593Smuzhiyun | | | | +---------------------+ | | 618*4882a593Smuzhiyun | +-------------+ | | .var.hist_data | | | 619*4882a593Smuzhiyun | | | | +---------------------+ | | 620*4882a593Smuzhiyun | +-------------+ | | .var_ref_idx | | | 621*4882a593Smuzhiyun | | | | +-----------------------+ | | 622*4882a593Smuzhiyun | +-------------+ | | var = wakeup_lat | | | 623*4882a593Smuzhiyun | . | +-----------------------+ | | 624*4882a593Smuzhiyun | . | | .size | | | 625*4882a593Smuzhiyun | . | +---------------------+ | | 626*4882a593Smuzhiyun | +-------------+ | | .offset | | | 627*4882a593Smuzhiyun | | | | +---------------------+ | | 628*4882a593Smuzhiyun | +-------------+ | | .fn() | | | 629*4882a593Smuzhiyun | | | | +---------------------+ | | 630*4882a593Smuzhiyun | +-------------+ | | .flags & FL_VAR | | | 631*4882a593Smuzhiyun | | +---------------------+ | | 632*4882a593Smuzhiyun | | | .var.idx | | | 633*4882a593Smuzhiyun | | +---------------------+ | | 634*4882a593Smuzhiyun | | | .var.hist_data | | | 635*4882a593Smuzhiyun | | +---------------------+ | | 636*4882a593Smuzhiyun | | | .var_ref_idx | | | 637*4882a593Smuzhiyun | | +---------------------+ | | 638*4882a593Smuzhiyun | | . | | 639*4882a593Smuzhiyun | | . | | 640*4882a593Smuzhiyun | | . | | 641*4882a593Smuzhiyun | | +-----------------------+ <--- n_vals | | 642*4882a593Smuzhiyun | | | key = pid | | | 643*4882a593Smuzhiyun | | +-----------------------+ | | 644*4882a593Smuzhiyun | | | .size | | | 645*4882a593Smuzhiyun | | +---------------------+ | | 646*4882a593Smuzhiyun | | | .offset | | | 647*4882a593Smuzhiyun | | +---------------------+ | | 648*4882a593Smuzhiyun | | | .fn() | | | 649*4882a593Smuzhiyun | | +---------------------+ | | 650*4882a593Smuzhiyun | | | .flags | | | 651*4882a593Smuzhiyun | | +---------------------+ | | 652*4882a593Smuzhiyun | | | .var.idx | | | 653*4882a593Smuzhiyun | | +-----------------------+ <--- n_fields | | 654*4882a593Smuzhiyun | | | unused | | | 655*4882a593Smuzhiyun | | +-----------------------+ | | 656*4882a593Smuzhiyun | | | | | | 657*4882a593Smuzhiyun | | +---------------------+ | | 658*4882a593Smuzhiyun | | | | | | 659*4882a593Smuzhiyun | | +---------------------+ | | 660*4882a593Smuzhiyun | | | | | | 661*4882a593Smuzhiyun | | +---------------------+ | | 662*4882a593Smuzhiyun | | | | | | 663*4882a593Smuzhiyun | | +---------------------+ | | 664*4882a593Smuzhiyun | | | | | | 665*4882a593Smuzhiyun | | +---------------------+ | | 666*4882a593Smuzhiyun | | n_keys = n_fields - n_vals | | 667*4882a593Smuzhiyun | | | | 668*4882a593Smuzhiyun | | | | 669*4882a593Smuzhiyun | | +-----------------------+ | | 670*4882a593Smuzhiyun +---------------------->| var_ref = $ts0 | | | 671*4882a593Smuzhiyun | +-----------------------+ | | 672*4882a593Smuzhiyun | | .size | | | 673*4882a593Smuzhiyun | +---------------------+ | | 674*4882a593Smuzhiyun | | .offset | | | 675*4882a593Smuzhiyun | +---------------------+ | | 676*4882a593Smuzhiyun | | .fn() | | | 677*4882a593Smuzhiyun | +---------------------+ | | 678*4882a593Smuzhiyun | | .flags & FL_VAR_REF | | | 679*4882a593Smuzhiyun | +---------------------+ | | 680*4882a593Smuzhiyun | | .var.idx |--------------------------+ | 681*4882a593Smuzhiyun | +---------------------+ | 682*4882a593Smuzhiyun | | .var.hist_data |----------------------------+ 683*4882a593Smuzhiyun | +---------------------+ 684*4882a593Smuzhiyun +---| .var_ref_idx | 685*4882a593Smuzhiyun +---------------------+ 686*4882a593Smuzhiyun 687*4882a593SmuzhiyunAbbreviations used in the diagrams:: 688*4882a593Smuzhiyun 689*4882a593Smuzhiyun hist_data = struct hist_trigger_data 690*4882a593Smuzhiyun hist_data.fields = struct hist_field 691*4882a593Smuzhiyun fn = hist_field_fn_t 692*4882a593Smuzhiyun FL_KEY = HIST_FIELD_FL_KEY 693*4882a593Smuzhiyun FL_VAR = HIST_FIELD_FL_VAR 694*4882a593Smuzhiyun FL_VAR_REF = HIST_FIELD_FL_VAR_REF 695*4882a593Smuzhiyun 696*4882a593SmuzhiyunWhen a hist trigger makes use of a variable, a new hist_field is 697*4882a593Smuzhiyuncreated with flag HIST_FIELD_FL_VAR_REF. For a VAR_REF field, the 698*4882a593Smuzhiyunvar.idx and var.hist_data take the same values as the referenced 699*4882a593Smuzhiyunvariable, as well as the referenced variable's size, type, and 700*4882a593Smuzhiyunis_signed values. The VAR_REF field's .name is set to the name of the 701*4882a593Smuzhiyunvariable it references. If a variable reference was created using the 702*4882a593Smuzhiyunexplicit system.event.$var_ref notation, the hist_field's system and 703*4882a593Smuzhiyunevent_name variables are also set. 704*4882a593Smuzhiyun 705*4882a593SmuzhiyunSo, in order to handle an event for the sched_switch histogram, 706*4882a593Smuzhiyunbecause we have a reference to a variable on another histogram, we 707*4882a593Smuzhiyunneed to resolve all variable references first. This is done via the 708*4882a593Smuzhiyunresolve_var_refs() calls made from event_hist_trigger(). What this 709*4882a593Smuzhiyundoes is grabs the var_refs[] array from the hist_data representing the 710*4882a593Smuzhiyunsched_switch histogram. For each one of those, the referenced 711*4882a593Smuzhiyunvariable's var.hist_data along with the current key is used to look up 712*4882a593Smuzhiyunthe corresponding tracing_map_elt in that histogram. Once found, the 713*4882a593Smuzhiyunreferenced variable's var.idx is used to look up the variable's value 714*4882a593Smuzhiyunusing tracing_map_read_var(elt, var.idx), which yields the value of 715*4882a593Smuzhiyunthe variable for that element, ts0 in the case above. Note that both 716*4882a593Smuzhiyunthe hist_fields representing both the variable and the variable 717*4882a593Smuzhiyunreference have the same var.idx, so this is straightforward. 718*4882a593Smuzhiyun 719*4882a593SmuzhiyunVariable and variable reference test 720*4882a593Smuzhiyun------------------------------------ 721*4882a593Smuzhiyun 722*4882a593SmuzhiyunThis example creates a variable on the sched_waking event, ts0, and 723*4882a593Smuzhiyunuses it in the sched_switch trigger. The sched_switch trigger also 724*4882a593Smuzhiyuncreates its own variable, wakeup_lat, but nothing yet uses it:: 725*4882a593Smuzhiyun 726*4882a593Smuzhiyun # echo 'hist:keys=pid:ts0=common_timestamp.usecs' >> events/sched/sched_waking/trigger 727*4882a593Smuzhiyun 728*4882a593Smuzhiyun # echo 'hist:keys=next_pid:wakeup_lat=common_timestamp.usecs-$ts0' >> events/sched/sched_switch/trigger 729*4882a593Smuzhiyun 730*4882a593SmuzhiyunLooking at the sched_waking 'hist_debug' output, in addition to the 731*4882a593Smuzhiyunnormal key and value hist_fields, in the val fields section we see a 732*4882a593Smuzhiyunfield with the HIST_FIELD_FL_VAR flag, which indicates that that field 733*4882a593Smuzhiyunrepresents a variable. Note that in addition to the variable name, 734*4882a593Smuzhiyuncontained in the var.name field, it includes the var.idx, which is the 735*4882a593Smuzhiyunindex into the tracing_map_elt.vars[] array of the actual variable 736*4882a593Smuzhiyunlocation. Note also that the output shows that variables live in the 737*4882a593Smuzhiyunsame part of the hist_data->fields[] array as normal values:: 738*4882a593Smuzhiyun 739*4882a593Smuzhiyun # cat events/sched/sched_waking/hist_debug 740*4882a593Smuzhiyun 741*4882a593Smuzhiyun # event histogram 742*4882a593Smuzhiyun # 743*4882a593Smuzhiyun # trigger info: hist:keys=pid:vals=hitcount:ts0=common_timestamp.usecs:sort=hitcount:size=2048:clock=global [active] 744*4882a593Smuzhiyun # 745*4882a593Smuzhiyun 746*4882a593Smuzhiyun hist_data: 000000009536f554 747*4882a593Smuzhiyun 748*4882a593Smuzhiyun n_vals: 2 749*4882a593Smuzhiyun n_keys: 1 750*4882a593Smuzhiyun n_fields: 3 751*4882a593Smuzhiyun 752*4882a593Smuzhiyun val fields: 753*4882a593Smuzhiyun 754*4882a593Smuzhiyun hist_data->fields[0]: 755*4882a593Smuzhiyun flags: 756*4882a593Smuzhiyun VAL: HIST_FIELD_FL_HITCOUNT 757*4882a593Smuzhiyun type: u64 758*4882a593Smuzhiyun size: 8 759*4882a593Smuzhiyun is_signed: 0 760*4882a593Smuzhiyun 761*4882a593Smuzhiyun hist_data->fields[1]: 762*4882a593Smuzhiyun flags: 763*4882a593Smuzhiyun HIST_FIELD_FL_VAR 764*4882a593Smuzhiyun var.name: ts0 765*4882a593Smuzhiyun var.idx (into tracing_map_elt.vars[]): 0 766*4882a593Smuzhiyun type: u64 767*4882a593Smuzhiyun size: 8 768*4882a593Smuzhiyun is_signed: 0 769*4882a593Smuzhiyun 770*4882a593Smuzhiyun key fields: 771*4882a593Smuzhiyun 772*4882a593Smuzhiyun hist_data->fields[2]: 773*4882a593Smuzhiyun flags: 774*4882a593Smuzhiyun HIST_FIELD_FL_KEY 775*4882a593Smuzhiyun ftrace_event_field name: pid 776*4882a593Smuzhiyun type: pid_t 777*4882a593Smuzhiyun size: 8 778*4882a593Smuzhiyun is_signed: 1 779*4882a593Smuzhiyun 780*4882a593SmuzhiyunMoving on to the sched_switch trigger hist_debug output, in addition 781*4882a593Smuzhiyunto the unused wakeup_lat variable, we see a new section displaying 782*4882a593Smuzhiyunvariable references. Variable references are displayed in a separate 783*4882a593Smuzhiyunsection because in addition to being logically separate from 784*4882a593Smuzhiyunvariables and values, they actually live in a separate hist_data 785*4882a593Smuzhiyunarray, var_refs[]. 786*4882a593Smuzhiyun 787*4882a593SmuzhiyunIn this example, the sched_switch trigger has a reference to a 788*4882a593Smuzhiyunvariable on the sched_waking trigger, $ts0. Looking at the details, 789*4882a593Smuzhiyunwe can see that the var.hist_data value of the referenced variable 790*4882a593Smuzhiyunmatches the previously displayed sched_waking trigger, and the var.idx 791*4882a593Smuzhiyunvalue matches the previously displayed var.idx value for that 792*4882a593Smuzhiyunvariable. Also displayed is the var_ref_idx value for that variable 793*4882a593Smuzhiyunreference, which is where the value for that variable is cached for 794*4882a593Smuzhiyunuse when the trigger is invoked:: 795*4882a593Smuzhiyun 796*4882a593Smuzhiyun # cat events/sched/sched_switch/hist_debug 797*4882a593Smuzhiyun 798*4882a593Smuzhiyun # event histogram 799*4882a593Smuzhiyun # 800*4882a593Smuzhiyun # trigger info: hist:keys=next_pid:vals=hitcount:wakeup_lat=common_timestamp.usecs-$ts0:sort=hitcount:size=2048:clock=global [active] 801*4882a593Smuzhiyun # 802*4882a593Smuzhiyun 803*4882a593Smuzhiyun hist_data: 00000000f4ee8006 804*4882a593Smuzhiyun 805*4882a593Smuzhiyun n_vals: 2 806*4882a593Smuzhiyun n_keys: 1 807*4882a593Smuzhiyun n_fields: 3 808*4882a593Smuzhiyun 809*4882a593Smuzhiyun val fields: 810*4882a593Smuzhiyun 811*4882a593Smuzhiyun hist_data->fields[0]: 812*4882a593Smuzhiyun flags: 813*4882a593Smuzhiyun VAL: HIST_FIELD_FL_HITCOUNT 814*4882a593Smuzhiyun type: u64 815*4882a593Smuzhiyun size: 8 816*4882a593Smuzhiyun is_signed: 0 817*4882a593Smuzhiyun 818*4882a593Smuzhiyun hist_data->fields[1]: 819*4882a593Smuzhiyun flags: 820*4882a593Smuzhiyun HIST_FIELD_FL_VAR 821*4882a593Smuzhiyun var.name: wakeup_lat 822*4882a593Smuzhiyun var.idx (into tracing_map_elt.vars[]): 0 823*4882a593Smuzhiyun type: u64 824*4882a593Smuzhiyun size: 0 825*4882a593Smuzhiyun is_signed: 0 826*4882a593Smuzhiyun 827*4882a593Smuzhiyun key fields: 828*4882a593Smuzhiyun 829*4882a593Smuzhiyun hist_data->fields[2]: 830*4882a593Smuzhiyun flags: 831*4882a593Smuzhiyun HIST_FIELD_FL_KEY 832*4882a593Smuzhiyun ftrace_event_field name: next_pid 833*4882a593Smuzhiyun type: pid_t 834*4882a593Smuzhiyun size: 8 835*4882a593Smuzhiyun is_signed: 1 836*4882a593Smuzhiyun 837*4882a593Smuzhiyun variable reference fields: 838*4882a593Smuzhiyun 839*4882a593Smuzhiyun hist_data->var_refs[0]: 840*4882a593Smuzhiyun flags: 841*4882a593Smuzhiyun HIST_FIELD_FL_VAR_REF 842*4882a593Smuzhiyun name: ts0 843*4882a593Smuzhiyun var.idx (into tracing_map_elt.vars[]): 0 844*4882a593Smuzhiyun var.hist_data: 000000009536f554 845*4882a593Smuzhiyun var_ref_idx (into hist_data->var_refs[]): 0 846*4882a593Smuzhiyun type: u64 847*4882a593Smuzhiyun size: 8 848*4882a593Smuzhiyun is_signed: 0 849*4882a593Smuzhiyun 850*4882a593SmuzhiyunThe commands below can be used to clean things up for the next test:: 851*4882a593Smuzhiyun 852*4882a593Smuzhiyun # echo '!hist:keys=next_pid:wakeup_lat=common_timestamp.usecs-$ts0' >> events/sched/sched_switch/trigger 853*4882a593Smuzhiyun 854*4882a593Smuzhiyun # echo '!hist:keys=pid:ts0=common_timestamp.usecs' >> events/sched/sched_waking/trigger 855*4882a593Smuzhiyun 856*4882a593SmuzhiyunActions and Handlers 857*4882a593Smuzhiyun==================== 858*4882a593Smuzhiyun 859*4882a593SmuzhiyunAdding onto the previous example, we will now do something with that 860*4882a593Smuzhiyunwakeup_lat variable, namely send it and another field as a synthetic 861*4882a593Smuzhiyunevent. 862*4882a593Smuzhiyun 863*4882a593SmuzhiyunThe onmatch() action below basically says that whenever we have a 864*4882a593Smuzhiyunsched_switch event, if we have a matching sched_waking event, in this 865*4882a593Smuzhiyuncase if we have a pid in the sched_waking histogram that matches the 866*4882a593Smuzhiyunnext_pid field on this sched_switch event, we retrieve the 867*4882a593Smuzhiyunvariables specified in the wakeup_latency() trace action, and use 868*4882a593Smuzhiyunthem to generate a new wakeup_latency event into the trace stream. 869*4882a593Smuzhiyun 870*4882a593SmuzhiyunNote that the way the trace handlers such as wakeup_latency() (which 871*4882a593Smuzhiyuncould equivalently be written trace(wakeup_latency,$wakeup_lat,next_pid) 872*4882a593Smuzhiyunare implemented, the parameters specified to the trace handler must be 873*4882a593Smuzhiyunvariables. In this case, $wakeup_lat is obviously a variable, but 874*4882a593Smuzhiyunnext_pid isn't, since it's just naming a field in the sched_switch 875*4882a593Smuzhiyuntrace event. Since this is something that almost every trace() and 876*4882a593Smuzhiyunsave() action does, a special shortcut is implemented to allow field 877*4882a593Smuzhiyunnames to be used directly in those cases. How it works is that under 878*4882a593Smuzhiyunthe covers, a temporary variable is created for the named field, and 879*4882a593Smuzhiyunthis variable is what is actually passed to the trace handler. In the 880*4882a593Smuzhiyuncode and documentation, this type of variable is called a 'field 881*4882a593Smuzhiyunvariable'. 882*4882a593Smuzhiyun 883*4882a593SmuzhiyunFields on other trace event's histograms can be used as well. In that 884*4882a593Smuzhiyuncase we have to generate a new histogram and an unfortunately named 885*4882a593Smuzhiyun'synthetic_field' (the use of synthetic here has nothing to do with 886*4882a593Smuzhiyunsynthetic events) and use that special histogram field as a variable. 887*4882a593Smuzhiyun 888*4882a593SmuzhiyunThe diagram below illustrates the new elements described above in the 889*4882a593Smuzhiyuncontext of the sched_switch histogram using the onmatch() handler and 890*4882a593Smuzhiyunthe trace() action. 891*4882a593Smuzhiyun 892*4882a593SmuzhiyunFirst, we define the wakeup_latency synthetic event:: 893*4882a593Smuzhiyun 894*4882a593Smuzhiyun # echo 'wakeup_latency u64 lat; pid_t pid' >> synthetic_events 895*4882a593Smuzhiyun 896*4882a593SmuzhiyunNext, the sched_waking hist trigger as before:: 897*4882a593Smuzhiyun 898*4882a593Smuzhiyun # echo 'hist:keys=pid:ts0=common_timestamp.usecs' >> 899*4882a593Smuzhiyun events/sched/sched_waking/trigger 900*4882a593Smuzhiyun 901*4882a593SmuzhiyunFinally, we create a hist trigger on the sched_switch event that 902*4882a593Smuzhiyungenerates a wakeup_latency() trace event. In this case we pass 903*4882a593Smuzhiyunnext_pid into the wakeup_latency synthetic event invocation, which 904*4882a593Smuzhiyunmeans it will be automatically converted into a field variable:: 905*4882a593Smuzhiyun 906*4882a593Smuzhiyun # echo 'hist:keys=next_pid:wakeup_lat=common_timestamp.usecs-$ts0: \ 907*4882a593Smuzhiyun onmatch(sched.sched_waking).wakeup_latency($wakeup_lat,next_pid)' >> 908*4882a593Smuzhiyun /sys/kernel/debug/tracing/events/sched/sched_switch/trigger 909*4882a593Smuzhiyun 910*4882a593SmuzhiyunThe diagram for the sched_switch event is similar to previous examples 911*4882a593Smuzhiyunbut shows the additional field_vars[] array for hist_data and shows 912*4882a593Smuzhiyunthe linkages between the field_vars and the variables and references 913*4882a593Smuzhiyuncreated to implement the field variables. The details are discussed 914*4882a593Smuzhiyunbelow:: 915*4882a593Smuzhiyun 916*4882a593Smuzhiyun +------------------+ 917*4882a593Smuzhiyun | hist_data | 918*4882a593Smuzhiyun +------------------+ +-----------------------+ 919*4882a593Smuzhiyun | .fields[] |-->| val = hitcount | 920*4882a593Smuzhiyun +----------------+ +-----------------------+ 921*4882a593Smuzhiyun | .map | | .size | 922*4882a593Smuzhiyun +----------------+ +---------------------+ 923*4882a593Smuzhiyun +---| .field_vars[] | | .offset | 924*4882a593Smuzhiyun | +----------------+ +---------------------+ 925*4882a593Smuzhiyun |+--| .var_refs[] | | .offset | 926*4882a593Smuzhiyun || +----------------+ +---------------------+ 927*4882a593Smuzhiyun || | .fn() | 928*4882a593Smuzhiyun || var_ref_vals[] +---------------------+ 929*4882a593Smuzhiyun || +-------------+ | .flags | 930*4882a593Smuzhiyun || | $ts0 |<---+ +---------------------+ 931*4882a593Smuzhiyun || +-------------+ | | .var.idx | 932*4882a593Smuzhiyun || | $next_pid |<-+ | +---------------------+ 933*4882a593Smuzhiyun || +-------------+ | | | .var.hist_data | 934*4882a593Smuzhiyun ||+>| $wakeup_lat | | | +---------------------+ 935*4882a593Smuzhiyun ||| +-------------+ | | | .var_ref_idx | 936*4882a593Smuzhiyun ||| | | | | +-----------------------+ 937*4882a593Smuzhiyun ||| +-------------+ | | | var = wakeup_lat | 938*4882a593Smuzhiyun ||| . | | +-----------------------+ 939*4882a593Smuzhiyun ||| . | | | .size | 940*4882a593Smuzhiyun ||| . | | +---------------------+ 941*4882a593Smuzhiyun ||| +-------------+ | | | .offset | 942*4882a593Smuzhiyun ||| | | | | +---------------------+ 943*4882a593Smuzhiyun ||| +-------------+ | | | .fn() | 944*4882a593Smuzhiyun ||| | | | | +---------------------+ 945*4882a593Smuzhiyun ||| +-------------+ | | | .flags & FL_VAR | 946*4882a593Smuzhiyun ||| | | +---------------------+ 947*4882a593Smuzhiyun ||| | | | .var.idx | 948*4882a593Smuzhiyun ||| | | +---------------------+ 949*4882a593Smuzhiyun ||| | | | .var.hist_data | 950*4882a593Smuzhiyun ||| | | +---------------------+ 951*4882a593Smuzhiyun ||| | | | .var_ref_idx | 952*4882a593Smuzhiyun ||| | | +---------------------+ 953*4882a593Smuzhiyun ||| | | . 954*4882a593Smuzhiyun ||| | | . 955*4882a593Smuzhiyun ||| | | . 956*4882a593Smuzhiyun ||| | | . 957*4882a593Smuzhiyun ||| +--------------+ | | . 958*4882a593Smuzhiyun +-->| field_var | | | . 959*4882a593Smuzhiyun || +--------------+ | | . 960*4882a593Smuzhiyun || | var | | | . 961*4882a593Smuzhiyun || +------------+ | | . 962*4882a593Smuzhiyun || | val | | | . 963*4882a593Smuzhiyun || +--------------+ | | . 964*4882a593Smuzhiyun || | field_var | | | . 965*4882a593Smuzhiyun || +--------------+ | | . 966*4882a593Smuzhiyun || | var | | | . 967*4882a593Smuzhiyun || +------------+ | | . 968*4882a593Smuzhiyun || | val | | | . 969*4882a593Smuzhiyun || +------------+ | | . 970*4882a593Smuzhiyun || . | | . 971*4882a593Smuzhiyun || . | | . 972*4882a593Smuzhiyun || . | | +-----------------------+ <--- n_vals 973*4882a593Smuzhiyun || +--------------+ | | | key = pid | 974*4882a593Smuzhiyun || | field_var | | | +-----------------------+ 975*4882a593Smuzhiyun || +--------------+ | | | .size | 976*4882a593Smuzhiyun || | var |--+| +---------------------+ 977*4882a593Smuzhiyun || +------------+ ||| | .offset | 978*4882a593Smuzhiyun || | val |-+|| +---------------------+ 979*4882a593Smuzhiyun || +------------+ ||| | .fn() | 980*4882a593Smuzhiyun || ||| +---------------------+ 981*4882a593Smuzhiyun || ||| | .flags | 982*4882a593Smuzhiyun || ||| +---------------------+ 983*4882a593Smuzhiyun || ||| | .var.idx | 984*4882a593Smuzhiyun || ||| +---------------------+ <--- n_fields 985*4882a593Smuzhiyun || ||| 986*4882a593Smuzhiyun || ||| n_keys = n_fields - n_vals 987*4882a593Smuzhiyun || ||| +-----------------------+ 988*4882a593Smuzhiyun || |+->| var = next_pid | 989*4882a593Smuzhiyun || | | +-----------------------+ 990*4882a593Smuzhiyun || | | | .size | 991*4882a593Smuzhiyun || | | +---------------------+ 992*4882a593Smuzhiyun || | | | .offset | 993*4882a593Smuzhiyun || | | +---------------------+ 994*4882a593Smuzhiyun || | | | .flags & FL_VAR | 995*4882a593Smuzhiyun || | | +---------------------+ 996*4882a593Smuzhiyun || | | | .var.idx | 997*4882a593Smuzhiyun || | | +---------------------+ 998*4882a593Smuzhiyun || | | | .var.hist_data | 999*4882a593Smuzhiyun || | | +-----------------------+ 1000*4882a593Smuzhiyun || +-->| val for next_pid | 1001*4882a593Smuzhiyun || | | +-----------------------+ 1002*4882a593Smuzhiyun || | | | .size | 1003*4882a593Smuzhiyun || | | +---------------------+ 1004*4882a593Smuzhiyun || | | | .offset | 1005*4882a593Smuzhiyun || | | +---------------------+ 1006*4882a593Smuzhiyun || | | | .fn() | 1007*4882a593Smuzhiyun || | | +---------------------+ 1008*4882a593Smuzhiyun || | | | .flags | 1009*4882a593Smuzhiyun || | | +---------------------+ 1010*4882a593Smuzhiyun || | | | | 1011*4882a593Smuzhiyun || | | +---------------------+ 1012*4882a593Smuzhiyun || | | 1013*4882a593Smuzhiyun || | | 1014*4882a593Smuzhiyun || | | +-----------------------+ 1015*4882a593Smuzhiyun +|------------------|-|>| var_ref = $ts0 | 1016*4882a593Smuzhiyun | | | +-----------------------+ 1017*4882a593Smuzhiyun | | | | .size | 1018*4882a593Smuzhiyun | | | +---------------------+ 1019*4882a593Smuzhiyun | | | | .offset | 1020*4882a593Smuzhiyun | | | +---------------------+ 1021*4882a593Smuzhiyun | | | | .fn() | 1022*4882a593Smuzhiyun | | | +---------------------+ 1023*4882a593Smuzhiyun | | | | .flags & FL_VAR_REF | 1024*4882a593Smuzhiyun | | | +---------------------+ 1025*4882a593Smuzhiyun | | +---| .var_ref_idx | 1026*4882a593Smuzhiyun | | +-----------------------+ 1027*4882a593Smuzhiyun | | | var_ref = $next_pid | 1028*4882a593Smuzhiyun | | +-----------------------+ 1029*4882a593Smuzhiyun | | | .size | 1030*4882a593Smuzhiyun | | +---------------------+ 1031*4882a593Smuzhiyun | | | .offset | 1032*4882a593Smuzhiyun | | +---------------------+ 1033*4882a593Smuzhiyun | | | .fn() | 1034*4882a593Smuzhiyun | | +---------------------+ 1035*4882a593Smuzhiyun | | | .flags & FL_VAR_REF | 1036*4882a593Smuzhiyun | | +---------------------+ 1037*4882a593Smuzhiyun | +-----| .var_ref_idx | 1038*4882a593Smuzhiyun | +-----------------------+ 1039*4882a593Smuzhiyun | | var_ref = $wakeup_lat | 1040*4882a593Smuzhiyun | +-----------------------+ 1041*4882a593Smuzhiyun | | .size | 1042*4882a593Smuzhiyun | +---------------------+ 1043*4882a593Smuzhiyun | | .offset | 1044*4882a593Smuzhiyun | +---------------------+ 1045*4882a593Smuzhiyun | | .fn() | 1046*4882a593Smuzhiyun | +---------------------+ 1047*4882a593Smuzhiyun | | .flags & FL_VAR_REF | 1048*4882a593Smuzhiyun | +---------------------+ 1049*4882a593Smuzhiyun +------------------------| .var_ref_idx | 1050*4882a593Smuzhiyun +---------------------+ 1051*4882a593Smuzhiyun 1052*4882a593SmuzhiyunAs you can see, for a field variable, two hist_fields are created: one 1053*4882a593Smuzhiyunrepresenting the variable, in this case next_pid, and one to actually 1054*4882a593Smuzhiyunget the value of the field from the trace stream, like a normal val 1055*4882a593Smuzhiyunfield does. These are created separately from normal variable 1056*4882a593Smuzhiyuncreation and are saved in the hist_data->field_vars[] array. See 1057*4882a593Smuzhiyunbelow for how these are used. In addition, a reference hist_field is 1058*4882a593Smuzhiyunalso created, which is needed to reference the field variables such as 1059*4882a593Smuzhiyun$next_pid variable in the trace() action. 1060*4882a593Smuzhiyun 1061*4882a593SmuzhiyunNote that $wakeup_lat is also a variable reference, referencing the 1062*4882a593Smuzhiyunvalue of the expression common_timestamp-$ts0, and so also needs to 1063*4882a593Smuzhiyunhave a hist field entry representing that reference created. 1064*4882a593Smuzhiyun 1065*4882a593SmuzhiyunWhen hist_trigger_elt_update() is called to get the normal key and 1066*4882a593Smuzhiyunvalue fields, it also calls update_field_vars(), which goes through 1067*4882a593Smuzhiyuneach field_var created for the histogram, and available from 1068*4882a593Smuzhiyunhist_data->field_vars and calls val->fn() to get the data from the 1069*4882a593Smuzhiyuncurrent trace record, and then uses the var's var.idx to set the 1070*4882a593Smuzhiyunvariable at the var.idx offset in the appropriate tracing_map_elt's 1071*4882a593Smuzhiyunvariable at elt->vars[var.idx]. 1072*4882a593Smuzhiyun 1073*4882a593SmuzhiyunOnce all the variables have been updated, resolve_var_refs() can be 1074*4882a593Smuzhiyuncalled from event_hist_trigger(), and not only can our $ts0 and 1075*4882a593Smuzhiyun$next_pid references be resolved but the $wakeup_lat reference as 1076*4882a593Smuzhiyunwell. At this point, the trace() action can simply access the values 1077*4882a593Smuzhiyunassembled in the var_ref_vals[] array and generate the trace event. 1078*4882a593Smuzhiyun 1079*4882a593SmuzhiyunThe same process occurs for the field variables associated with the 1080*4882a593Smuzhiyunsave() action. 1081*4882a593Smuzhiyun 1082*4882a593SmuzhiyunAbbreviations used in the diagram:: 1083*4882a593Smuzhiyun 1084*4882a593Smuzhiyun hist_data = struct hist_trigger_data 1085*4882a593Smuzhiyun hist_data.fields = struct hist_field 1086*4882a593Smuzhiyun field_var = struct field_var 1087*4882a593Smuzhiyun fn = hist_field_fn_t 1088*4882a593Smuzhiyun FL_KEY = HIST_FIELD_FL_KEY 1089*4882a593Smuzhiyun FL_VAR = HIST_FIELD_FL_VAR 1090*4882a593Smuzhiyun FL_VAR_REF = HIST_FIELD_FL_VAR_REF 1091*4882a593Smuzhiyun 1092*4882a593Smuzhiyuntrace() action field variable test 1093*4882a593Smuzhiyun---------------------------------- 1094*4882a593Smuzhiyun 1095*4882a593SmuzhiyunThis example adds to the previous test example by finally making use 1096*4882a593Smuzhiyunof the wakeup_lat variable, but in addition also creates a couple of 1097*4882a593Smuzhiyunfield variables that then are all passed to the wakeup_latency() trace 1098*4882a593Smuzhiyunaction via the onmatch() handler. 1099*4882a593Smuzhiyun 1100*4882a593SmuzhiyunFirst, we create the wakeup_latency synthetic event:: 1101*4882a593Smuzhiyun 1102*4882a593Smuzhiyun # echo 'wakeup_latency u64 lat; pid_t pid; char comm[16]' >> synthetic_events 1103*4882a593Smuzhiyun 1104*4882a593SmuzhiyunNext, the sched_waking trigger from previous examples:: 1105*4882a593Smuzhiyun 1106*4882a593Smuzhiyun # echo 'hist:keys=pid:ts0=common_timestamp.usecs' >> events/sched/sched_waking/trigger 1107*4882a593Smuzhiyun 1108*4882a593SmuzhiyunFinally, as in the previous test example, we calculate and assign the 1109*4882a593Smuzhiyunwakeup latency using the $ts0 reference from the sched_waking trigger 1110*4882a593Smuzhiyunto the wakeup_lat variable, and finally use it along with a couple 1111*4882a593Smuzhiyunsched_switch event fields, next_pid and next_comm, to generate a 1112*4882a593Smuzhiyunwakeup_latency trace event. The next_pid and next_comm event fields 1113*4882a593Smuzhiyunare automatically converted into field variables for this purpose:: 1114*4882a593Smuzhiyun 1115*4882a593Smuzhiyun # echo 'hist:keys=next_pid:wakeup_lat=common_timestamp.usecs-$ts0:onmatch(sched.sched_waking).wakeup_latency($wakeup_lat,next_pid,next_comm)' >> /sys/kernel/debug/tracing/events/sched/sched_switch/trigger 1116*4882a593Smuzhiyun 1117*4882a593SmuzhiyunThe sched_waking hist_debug output shows the same data as in the 1118*4882a593Smuzhiyunprevious test example:: 1119*4882a593Smuzhiyun 1120*4882a593Smuzhiyun # cat events/sched/sched_waking/hist_debug 1121*4882a593Smuzhiyun 1122*4882a593Smuzhiyun # event histogram 1123*4882a593Smuzhiyun # 1124*4882a593Smuzhiyun # trigger info: hist:keys=pid:vals=hitcount:ts0=common_timestamp.usecs:sort=hitcount:size=2048:clock=global [active] 1125*4882a593Smuzhiyun # 1126*4882a593Smuzhiyun 1127*4882a593Smuzhiyun hist_data: 00000000d60ff61f 1128*4882a593Smuzhiyun 1129*4882a593Smuzhiyun n_vals: 2 1130*4882a593Smuzhiyun n_keys: 1 1131*4882a593Smuzhiyun n_fields: 3 1132*4882a593Smuzhiyun 1133*4882a593Smuzhiyun val fields: 1134*4882a593Smuzhiyun 1135*4882a593Smuzhiyun hist_data->fields[0]: 1136*4882a593Smuzhiyun flags: 1137*4882a593Smuzhiyun VAL: HIST_FIELD_FL_HITCOUNT 1138*4882a593Smuzhiyun type: u64 1139*4882a593Smuzhiyun size: 8 1140*4882a593Smuzhiyun is_signed: 0 1141*4882a593Smuzhiyun 1142*4882a593Smuzhiyun hist_data->fields[1]: 1143*4882a593Smuzhiyun flags: 1144*4882a593Smuzhiyun HIST_FIELD_FL_VAR 1145*4882a593Smuzhiyun var.name: ts0 1146*4882a593Smuzhiyun var.idx (into tracing_map_elt.vars[]): 0 1147*4882a593Smuzhiyun type: u64 1148*4882a593Smuzhiyun size: 8 1149*4882a593Smuzhiyun is_signed: 0 1150*4882a593Smuzhiyun 1151*4882a593Smuzhiyun key fields: 1152*4882a593Smuzhiyun 1153*4882a593Smuzhiyun hist_data->fields[2]: 1154*4882a593Smuzhiyun flags: 1155*4882a593Smuzhiyun HIST_FIELD_FL_KEY 1156*4882a593Smuzhiyun ftrace_event_field name: pid 1157*4882a593Smuzhiyun type: pid_t 1158*4882a593Smuzhiyun size: 8 1159*4882a593Smuzhiyun is_signed: 1 1160*4882a593Smuzhiyun 1161*4882a593SmuzhiyunThe sched_switch hist_debug output shows the same key and value fields 1162*4882a593Smuzhiyunas in the previous test example - note that wakeup_lat is still in the 1163*4882a593Smuzhiyunval fields section, but that the new field variables are not there - 1164*4882a593Smuzhiyunalthough the field variables are variables, they're held separately in 1165*4882a593Smuzhiyunthe hist_data's field_vars[] array. Although the field variables and 1166*4882a593Smuzhiyunthe normal variables are located in separate places, you can see that 1167*4882a593Smuzhiyunthe actual variable locations for those variables in the 1168*4882a593Smuzhiyuntracing_map_elt.vars[] do have increasing indices as expected: 1169*4882a593Smuzhiyunwakeup_lat takes the var.idx = 0 slot, while the field variables for 1170*4882a593Smuzhiyunnext_pid and next_comm have values var.idx = 1, and var.idx = 2. Note 1171*4882a593Smuzhiyunalso that those are the same values displayed for the variable 1172*4882a593Smuzhiyunreferences corresponding to those variables in the variable reference 1173*4882a593Smuzhiyunfields section. Since there are two triggers and thus two hist_data 1174*4882a593Smuzhiyunaddresses, those addresses also need to be accounted for when doing 1175*4882a593Smuzhiyunthe matching - you can see that the first variable refers to the 0 1176*4882a593Smuzhiyunvar.idx on the previous hist trigger (see the hist_data address 1177*4882a593Smuzhiyunassociated with that trigger), while the second variable refers to the 1178*4882a593Smuzhiyun0 var.idx on the sched_switch hist trigger, as do all the remaining 1179*4882a593Smuzhiyunvariable references. 1180*4882a593Smuzhiyun 1181*4882a593SmuzhiyunFinally, the action tracking variables section just shows the system 1182*4882a593Smuzhiyunand event name for the onmatch() handler:: 1183*4882a593Smuzhiyun 1184*4882a593Smuzhiyun # cat events/sched/sched_switch/hist_debug 1185*4882a593Smuzhiyun 1186*4882a593Smuzhiyun # event histogram 1187*4882a593Smuzhiyun # 1188*4882a593Smuzhiyun # trigger info: hist:keys=next_pid:vals=hitcount:wakeup_lat=common_timestamp.usecs-$ts0:sort=hitcount:size=2048:clock=global:onmatch(sched.sched_waking).wakeup_latency($wakeup_lat,next_pid,next_comm) [active] 1189*4882a593Smuzhiyun # 1190*4882a593Smuzhiyun 1191*4882a593Smuzhiyun hist_data: 0000000008f551b7 1192*4882a593Smuzhiyun 1193*4882a593Smuzhiyun n_vals: 2 1194*4882a593Smuzhiyun n_keys: 1 1195*4882a593Smuzhiyun n_fields: 3 1196*4882a593Smuzhiyun 1197*4882a593Smuzhiyun val fields: 1198*4882a593Smuzhiyun 1199*4882a593Smuzhiyun hist_data->fields[0]: 1200*4882a593Smuzhiyun flags: 1201*4882a593Smuzhiyun VAL: HIST_FIELD_FL_HITCOUNT 1202*4882a593Smuzhiyun type: u64 1203*4882a593Smuzhiyun size: 8 1204*4882a593Smuzhiyun is_signed: 0 1205*4882a593Smuzhiyun 1206*4882a593Smuzhiyun hist_data->fields[1]: 1207*4882a593Smuzhiyun flags: 1208*4882a593Smuzhiyun HIST_FIELD_FL_VAR 1209*4882a593Smuzhiyun var.name: wakeup_lat 1210*4882a593Smuzhiyun var.idx (into tracing_map_elt.vars[]): 0 1211*4882a593Smuzhiyun type: u64 1212*4882a593Smuzhiyun size: 0 1213*4882a593Smuzhiyun is_signed: 0 1214*4882a593Smuzhiyun 1215*4882a593Smuzhiyun key fields: 1216*4882a593Smuzhiyun 1217*4882a593Smuzhiyun hist_data->fields[2]: 1218*4882a593Smuzhiyun flags: 1219*4882a593Smuzhiyun HIST_FIELD_FL_KEY 1220*4882a593Smuzhiyun ftrace_event_field name: next_pid 1221*4882a593Smuzhiyun type: pid_t 1222*4882a593Smuzhiyun size: 8 1223*4882a593Smuzhiyun is_signed: 1 1224*4882a593Smuzhiyun 1225*4882a593Smuzhiyun variable reference fields: 1226*4882a593Smuzhiyun 1227*4882a593Smuzhiyun hist_data->var_refs[0]: 1228*4882a593Smuzhiyun flags: 1229*4882a593Smuzhiyun HIST_FIELD_FL_VAR_REF 1230*4882a593Smuzhiyun name: ts0 1231*4882a593Smuzhiyun var.idx (into tracing_map_elt.vars[]): 0 1232*4882a593Smuzhiyun var.hist_data: 00000000d60ff61f 1233*4882a593Smuzhiyun var_ref_idx (into hist_data->var_refs[]): 0 1234*4882a593Smuzhiyun type: u64 1235*4882a593Smuzhiyun size: 8 1236*4882a593Smuzhiyun is_signed: 0 1237*4882a593Smuzhiyun 1238*4882a593Smuzhiyun hist_data->var_refs[1]: 1239*4882a593Smuzhiyun flags: 1240*4882a593Smuzhiyun HIST_FIELD_FL_VAR_REF 1241*4882a593Smuzhiyun name: wakeup_lat 1242*4882a593Smuzhiyun var.idx (into tracing_map_elt.vars[]): 0 1243*4882a593Smuzhiyun var.hist_data: 0000000008f551b7 1244*4882a593Smuzhiyun var_ref_idx (into hist_data->var_refs[]): 1 1245*4882a593Smuzhiyun type: u64 1246*4882a593Smuzhiyun size: 0 1247*4882a593Smuzhiyun is_signed: 0 1248*4882a593Smuzhiyun 1249*4882a593Smuzhiyun hist_data->var_refs[2]: 1250*4882a593Smuzhiyun flags: 1251*4882a593Smuzhiyun HIST_FIELD_FL_VAR_REF 1252*4882a593Smuzhiyun name: next_pid 1253*4882a593Smuzhiyun var.idx (into tracing_map_elt.vars[]): 1 1254*4882a593Smuzhiyun var.hist_data: 0000000008f551b7 1255*4882a593Smuzhiyun var_ref_idx (into hist_data->var_refs[]): 2 1256*4882a593Smuzhiyun type: pid_t 1257*4882a593Smuzhiyun size: 4 1258*4882a593Smuzhiyun is_signed: 0 1259*4882a593Smuzhiyun 1260*4882a593Smuzhiyun hist_data->var_refs[3]: 1261*4882a593Smuzhiyun flags: 1262*4882a593Smuzhiyun HIST_FIELD_FL_VAR_REF 1263*4882a593Smuzhiyun name: next_comm 1264*4882a593Smuzhiyun var.idx (into tracing_map_elt.vars[]): 2 1265*4882a593Smuzhiyun var.hist_data: 0000000008f551b7 1266*4882a593Smuzhiyun var_ref_idx (into hist_data->var_refs[]): 3 1267*4882a593Smuzhiyun type: char[16] 1268*4882a593Smuzhiyun size: 256 1269*4882a593Smuzhiyun is_signed: 0 1270*4882a593Smuzhiyun 1271*4882a593Smuzhiyun field variables: 1272*4882a593Smuzhiyun 1273*4882a593Smuzhiyun hist_data->field_vars[0]: 1274*4882a593Smuzhiyun 1275*4882a593Smuzhiyun field_vars[0].var: 1276*4882a593Smuzhiyun flags: 1277*4882a593Smuzhiyun HIST_FIELD_FL_VAR 1278*4882a593Smuzhiyun var.name: next_pid 1279*4882a593Smuzhiyun var.idx (into tracing_map_elt.vars[]): 1 1280*4882a593Smuzhiyun 1281*4882a593Smuzhiyun field_vars[0].val: 1282*4882a593Smuzhiyun ftrace_event_field name: next_pid 1283*4882a593Smuzhiyun type: pid_t 1284*4882a593Smuzhiyun size: 4 1285*4882a593Smuzhiyun is_signed: 1 1286*4882a593Smuzhiyun 1287*4882a593Smuzhiyun hist_data->field_vars[1]: 1288*4882a593Smuzhiyun 1289*4882a593Smuzhiyun field_vars[1].var: 1290*4882a593Smuzhiyun flags: 1291*4882a593Smuzhiyun HIST_FIELD_FL_VAR 1292*4882a593Smuzhiyun var.name: next_comm 1293*4882a593Smuzhiyun var.idx (into tracing_map_elt.vars[]): 2 1294*4882a593Smuzhiyun 1295*4882a593Smuzhiyun field_vars[1].val: 1296*4882a593Smuzhiyun ftrace_event_field name: next_comm 1297*4882a593Smuzhiyun type: char[16] 1298*4882a593Smuzhiyun size: 256 1299*4882a593Smuzhiyun is_signed: 0 1300*4882a593Smuzhiyun 1301*4882a593Smuzhiyun action tracking variables (for onmax()/onchange()/onmatch()): 1302*4882a593Smuzhiyun 1303*4882a593Smuzhiyun hist_data->actions[0].match_data.event_system: sched 1304*4882a593Smuzhiyun hist_data->actions[0].match_data.event: sched_waking 1305*4882a593Smuzhiyun 1306*4882a593SmuzhiyunThe commands below can be used to clean things up for the next test:: 1307*4882a593Smuzhiyun 1308*4882a593Smuzhiyun # echo '!hist:keys=next_pid:wakeup_lat=common_timestamp.usecs-$ts0:onmatch(sched.sched_waking).wakeup_latency($wakeup_lat,next_pid,next_comm)' >> /sys/kernel/debug/tracing/events/sched/sched_switch/trigger 1309*4882a593Smuzhiyun 1310*4882a593Smuzhiyun # echo '!hist:keys=pid:ts0=common_timestamp.usecs' >> events/sched/sched_waking/trigger 1311*4882a593Smuzhiyun 1312*4882a593Smuzhiyun # echo '!wakeup_latency u64 lat; pid_t pid; char comm[16]' >> synthetic_events 1313*4882a593Smuzhiyun 1314*4882a593Smuzhiyunaction_data and the trace() action 1315*4882a593Smuzhiyun---------------------------------- 1316*4882a593Smuzhiyun 1317*4882a593SmuzhiyunAs mentioned above, when the trace() action generates a synthetic 1318*4882a593Smuzhiyunevent, all the parameters to the synthetic event either already are 1319*4882a593Smuzhiyunvariables or are converted into variables (via field variables), and 1320*4882a593Smuzhiyunfinally all those variable values are collected via references to them 1321*4882a593Smuzhiyuninto a var_ref_vals[] array. 1322*4882a593Smuzhiyun 1323*4882a593SmuzhiyunThe values in the var_ref_vals[] array, however, don't necessarily 1324*4882a593Smuzhiyunfollow the same ordering as the synthetic event params. To address 1325*4882a593Smuzhiyunthat, struct action_data contains another array, var_ref_idx[] that 1326*4882a593Smuzhiyunmaps the trace action params to the var_ref_vals[] values. Below is a 1327*4882a593Smuzhiyundiagram illustrating that for the wakeup_latency() synthetic event:: 1328*4882a593Smuzhiyun 1329*4882a593Smuzhiyun +------------------+ wakeup_latency() 1330*4882a593Smuzhiyun | action_data | event params var_ref_vals[] 1331*4882a593Smuzhiyun +------------------+ +-----------------+ +-----------------+ 1332*4882a593Smuzhiyun | .var_ref_idx[] |--->| $wakeup_lat idx |---+ | | 1333*4882a593Smuzhiyun +----------------+ +-----------------+ | +-----------------+ 1334*4882a593Smuzhiyun | .synth_event | | $next_pid idx |---|-+ | $wakeup_lat val | 1335*4882a593Smuzhiyun +----------------+ +-----------------+ | | +-----------------+ 1336*4882a593Smuzhiyun . | +->| $next_pid val | 1337*4882a593Smuzhiyun . | +-----------------+ 1338*4882a593Smuzhiyun . | . 1339*4882a593Smuzhiyun +-----------------+ | . 1340*4882a593Smuzhiyun | | | . 1341*4882a593Smuzhiyun +-----------------+ | +-----------------+ 1342*4882a593Smuzhiyun +--->| $wakeup_lat val | 1343*4882a593Smuzhiyun +-----------------+ 1344*4882a593Smuzhiyun 1345*4882a593SmuzhiyunBasically, how this ends up getting used in the synthetic event probe 1346*4882a593Smuzhiyunfunction, trace_event_raw_event_synth(), is as follows:: 1347*4882a593Smuzhiyun 1348*4882a593Smuzhiyun for each field i in .synth_event 1349*4882a593Smuzhiyun val_idx = .var_ref_idx[i] 1350*4882a593Smuzhiyun val = var_ref_vals[val_idx] 1351*4882a593Smuzhiyun 1352*4882a593Smuzhiyunaction_data and the onXXX() handlers 1353*4882a593Smuzhiyun------------------------------------ 1354*4882a593Smuzhiyun 1355*4882a593SmuzhiyunThe hist trigger onXXX() actions other than onmatch(), such as onmax() 1356*4882a593Smuzhiyunand onchange(), also make use of and internally create hidden 1357*4882a593Smuzhiyunvariables. This information is contained in the 1358*4882a593Smuzhiyunaction_data.track_data struct, and is also visible in the hist_debug 1359*4882a593Smuzhiyunoutput as will be described in the example below. 1360*4882a593Smuzhiyun 1361*4882a593SmuzhiyunTypically, the onmax() or onchange() handlers are used in conjunction 1362*4882a593Smuzhiyunwith the save() and snapshot() actions. For example:: 1363*4882a593Smuzhiyun 1364*4882a593Smuzhiyun # echo 'hist:keys=next_pid:wakeup_lat=common_timestamp.usecs-$ts0: \ 1365*4882a593Smuzhiyun onmax($wakeup_lat).save(next_comm,prev_pid,prev_prio,prev_comm)' >> 1366*4882a593Smuzhiyun /sys/kernel/debug/tracing/events/sched/sched_switch/trigger 1367*4882a593Smuzhiyun 1368*4882a593Smuzhiyunor:: 1369*4882a593Smuzhiyun 1370*4882a593Smuzhiyun # echo 'hist:keys=next_pid:wakeup_lat=common_timestamp.usecs-$ts0: \ 1371*4882a593Smuzhiyun onmax($wakeup_lat).snapshot()' >> 1372*4882a593Smuzhiyun /sys/kernel/debug/tracing/events/sched/sched_switch/trigger 1373*4882a593Smuzhiyun 1374*4882a593Smuzhiyunsave() action field variable test 1375*4882a593Smuzhiyun--------------------------------- 1376*4882a593Smuzhiyun 1377*4882a593SmuzhiyunFor this example, instead of generating a synthetic event, the save() 1378*4882a593Smuzhiyunaction is used to save field values whenever an onmax() handler 1379*4882a593Smuzhiyundetects that a new max latency has been hit. As in the previous 1380*4882a593Smuzhiyunexample, the values being saved are also field values, but in this 1381*4882a593Smuzhiyuncase, are kept in a separate hist_data array named save_vars[]. 1382*4882a593Smuzhiyun 1383*4882a593SmuzhiyunAs in previous test examples, we set up the sched_waking trigger:: 1384*4882a593Smuzhiyun 1385*4882a593Smuzhiyun # echo 'hist:keys=pid:ts0=common_timestamp.usecs' >> events/sched/sched_waking/trigger 1386*4882a593Smuzhiyun 1387*4882a593SmuzhiyunIn this case, however, we set up the sched_switch trigger to save some 1388*4882a593Smuzhiyunsched_switch field values whenever we hit a new maximum latency. For 1389*4882a593Smuzhiyunboth the onmax() handler and save() action, variables will be created, 1390*4882a593Smuzhiyunwhich we can use the hist_debug files to examine:: 1391*4882a593Smuzhiyun 1392*4882a593Smuzhiyun # echo 'hist:keys=next_pid:wakeup_lat=common_timestamp.usecs-$ts0:onmax($wakeup_lat).save(next_comm,prev_pid,prev_prio,prev_comm)' >> events/sched/sched_switch/trigger 1393*4882a593Smuzhiyun 1394*4882a593SmuzhiyunThe sched_waking hist_debug output shows the same data as in the 1395*4882a593Smuzhiyunprevious test examples:: 1396*4882a593Smuzhiyun 1397*4882a593Smuzhiyun # cat events/sched/sched_waking/hist_debug 1398*4882a593Smuzhiyun 1399*4882a593Smuzhiyun # 1400*4882a593Smuzhiyun # trigger info: hist:keys=pid:vals=hitcount:ts0=common_timestamp.usecs:sort=hitcount:size=2048:clock=global [active] 1401*4882a593Smuzhiyun # 1402*4882a593Smuzhiyun 1403*4882a593Smuzhiyun hist_data: 00000000e6290f48 1404*4882a593Smuzhiyun 1405*4882a593Smuzhiyun n_vals: 2 1406*4882a593Smuzhiyun n_keys: 1 1407*4882a593Smuzhiyun n_fields: 3 1408*4882a593Smuzhiyun 1409*4882a593Smuzhiyun val fields: 1410*4882a593Smuzhiyun 1411*4882a593Smuzhiyun hist_data->fields[0]: 1412*4882a593Smuzhiyun flags: 1413*4882a593Smuzhiyun VAL: HIST_FIELD_FL_HITCOUNT 1414*4882a593Smuzhiyun type: u64 1415*4882a593Smuzhiyun size: 8 1416*4882a593Smuzhiyun is_signed: 0 1417*4882a593Smuzhiyun 1418*4882a593Smuzhiyun hist_data->fields[1]: 1419*4882a593Smuzhiyun flags: 1420*4882a593Smuzhiyun HIST_FIELD_FL_VAR 1421*4882a593Smuzhiyun var.name: ts0 1422*4882a593Smuzhiyun var.idx (into tracing_map_elt.vars[]): 0 1423*4882a593Smuzhiyun type: u64 1424*4882a593Smuzhiyun size: 8 1425*4882a593Smuzhiyun is_signed: 0 1426*4882a593Smuzhiyun 1427*4882a593Smuzhiyun key fields: 1428*4882a593Smuzhiyun 1429*4882a593Smuzhiyun hist_data->fields[2]: 1430*4882a593Smuzhiyun flags: 1431*4882a593Smuzhiyun HIST_FIELD_FL_KEY 1432*4882a593Smuzhiyun ftrace_event_field name: pid 1433*4882a593Smuzhiyun type: pid_t 1434*4882a593Smuzhiyun size: 8 1435*4882a593Smuzhiyun is_signed: 1 1436*4882a593Smuzhiyun 1437*4882a593SmuzhiyunThe output of the sched_switch trigger shows the same val and key 1438*4882a593Smuzhiyunvalues as before, but also shows a couple new sections. 1439*4882a593Smuzhiyun 1440*4882a593SmuzhiyunFirst, the action tracking variables section now shows the 1441*4882a593Smuzhiyunactions[].track_data information describing the special tracking 1442*4882a593Smuzhiyunvariables and references used to track, in this case, the running 1443*4882a593Smuzhiyunmaximum value. The actions[].track_data.var_ref member contains the 1444*4882a593Smuzhiyunreference to the variable being tracked, in this case the $wakeup_lat 1445*4882a593Smuzhiyunvariable. In order to perform the onmax() handler function, there 1446*4882a593Smuzhiyunalso needs to be a variable that tracks the current maximum by getting 1447*4882a593Smuzhiyunupdated whenever a new maximum is hit. In this case, we can see that 1448*4882a593Smuzhiyunan auto-generated variable named ' __max' has been created and is 1449*4882a593Smuzhiyunvisible in the actions[].track_data.track_var variable. 1450*4882a593Smuzhiyun 1451*4882a593SmuzhiyunFinally, in the new 'save action variables' section, we can see that 1452*4882a593Smuzhiyunthe 4 params to the save() function have resulted in 4 field variables 1453*4882a593Smuzhiyunbeing created for the purposes of saving the values of the named 1454*4882a593Smuzhiyunfields when the max is hit. These variables are kept in a separate 1455*4882a593Smuzhiyunsave_vars[] array off of hist_data, so are displayed in a separate 1456*4882a593Smuzhiyunsection:: 1457*4882a593Smuzhiyun 1458*4882a593Smuzhiyun # cat events/sched/sched_switch/hist_debug 1459*4882a593Smuzhiyun 1460*4882a593Smuzhiyun # event histogram 1461*4882a593Smuzhiyun # 1462*4882a593Smuzhiyun # trigger info: hist:keys=next_pid:vals=hitcount:wakeup_lat=common_timestamp.usecs-$ts0:sort=hitcount:size=2048:clock=global:onmax($wakeup_lat).save(next_comm,prev_pid,prev_prio,prev_comm) [active] 1463*4882a593Smuzhiyun # 1464*4882a593Smuzhiyun 1465*4882a593Smuzhiyun hist_data: 0000000057bcd28d 1466*4882a593Smuzhiyun 1467*4882a593Smuzhiyun n_vals: 2 1468*4882a593Smuzhiyun n_keys: 1 1469*4882a593Smuzhiyun n_fields: 3 1470*4882a593Smuzhiyun 1471*4882a593Smuzhiyun val fields: 1472*4882a593Smuzhiyun 1473*4882a593Smuzhiyun hist_data->fields[0]: 1474*4882a593Smuzhiyun flags: 1475*4882a593Smuzhiyun VAL: HIST_FIELD_FL_HITCOUNT 1476*4882a593Smuzhiyun type: u64 1477*4882a593Smuzhiyun size: 8 1478*4882a593Smuzhiyun is_signed: 0 1479*4882a593Smuzhiyun 1480*4882a593Smuzhiyun hist_data->fields[1]: 1481*4882a593Smuzhiyun flags: 1482*4882a593Smuzhiyun HIST_FIELD_FL_VAR 1483*4882a593Smuzhiyun var.name: wakeup_lat 1484*4882a593Smuzhiyun var.idx (into tracing_map_elt.vars[]): 0 1485*4882a593Smuzhiyun type: u64 1486*4882a593Smuzhiyun size: 0 1487*4882a593Smuzhiyun is_signed: 0 1488*4882a593Smuzhiyun 1489*4882a593Smuzhiyun key fields: 1490*4882a593Smuzhiyun 1491*4882a593Smuzhiyun hist_data->fields[2]: 1492*4882a593Smuzhiyun flags: 1493*4882a593Smuzhiyun HIST_FIELD_FL_KEY 1494*4882a593Smuzhiyun ftrace_event_field name: next_pid 1495*4882a593Smuzhiyun type: pid_t 1496*4882a593Smuzhiyun size: 8 1497*4882a593Smuzhiyun is_signed: 1 1498*4882a593Smuzhiyun 1499*4882a593Smuzhiyun variable reference fields: 1500*4882a593Smuzhiyun 1501*4882a593Smuzhiyun hist_data->var_refs[0]: 1502*4882a593Smuzhiyun flags: 1503*4882a593Smuzhiyun HIST_FIELD_FL_VAR_REF 1504*4882a593Smuzhiyun name: ts0 1505*4882a593Smuzhiyun var.idx (into tracing_map_elt.vars[]): 0 1506*4882a593Smuzhiyun var.hist_data: 00000000e6290f48 1507*4882a593Smuzhiyun var_ref_idx (into hist_data->var_refs[]): 0 1508*4882a593Smuzhiyun type: u64 1509*4882a593Smuzhiyun size: 8 1510*4882a593Smuzhiyun is_signed: 0 1511*4882a593Smuzhiyun 1512*4882a593Smuzhiyun hist_data->var_refs[1]: 1513*4882a593Smuzhiyun flags: 1514*4882a593Smuzhiyun HIST_FIELD_FL_VAR_REF 1515*4882a593Smuzhiyun name: wakeup_lat 1516*4882a593Smuzhiyun var.idx (into tracing_map_elt.vars[]): 0 1517*4882a593Smuzhiyun var.hist_data: 0000000057bcd28d 1518*4882a593Smuzhiyun var_ref_idx (into hist_data->var_refs[]): 1 1519*4882a593Smuzhiyun type: u64 1520*4882a593Smuzhiyun size: 0 1521*4882a593Smuzhiyun is_signed: 0 1522*4882a593Smuzhiyun 1523*4882a593Smuzhiyun action tracking variables (for onmax()/onchange()/onmatch()): 1524*4882a593Smuzhiyun 1525*4882a593Smuzhiyun hist_data->actions[0].track_data.var_ref: 1526*4882a593Smuzhiyun flags: 1527*4882a593Smuzhiyun HIST_FIELD_FL_VAR_REF 1528*4882a593Smuzhiyun name: wakeup_lat 1529*4882a593Smuzhiyun var.idx (into tracing_map_elt.vars[]): 0 1530*4882a593Smuzhiyun var.hist_data: 0000000057bcd28d 1531*4882a593Smuzhiyun var_ref_idx (into hist_data->var_refs[]): 1 1532*4882a593Smuzhiyun type: u64 1533*4882a593Smuzhiyun size: 0 1534*4882a593Smuzhiyun is_signed: 0 1535*4882a593Smuzhiyun 1536*4882a593Smuzhiyun hist_data->actions[0].track_data.track_var: 1537*4882a593Smuzhiyun flags: 1538*4882a593Smuzhiyun HIST_FIELD_FL_VAR 1539*4882a593Smuzhiyun var.name: __max 1540*4882a593Smuzhiyun var.idx (into tracing_map_elt.vars[]): 1 1541*4882a593Smuzhiyun type: u64 1542*4882a593Smuzhiyun size: 8 1543*4882a593Smuzhiyun is_signed: 0 1544*4882a593Smuzhiyun 1545*4882a593Smuzhiyun save action variables (save() params): 1546*4882a593Smuzhiyun 1547*4882a593Smuzhiyun hist_data->save_vars[0]: 1548*4882a593Smuzhiyun 1549*4882a593Smuzhiyun save_vars[0].var: 1550*4882a593Smuzhiyun flags: 1551*4882a593Smuzhiyun HIST_FIELD_FL_VAR 1552*4882a593Smuzhiyun var.name: next_comm 1553*4882a593Smuzhiyun var.idx (into tracing_map_elt.vars[]): 2 1554*4882a593Smuzhiyun 1555*4882a593Smuzhiyun save_vars[0].val: 1556*4882a593Smuzhiyun ftrace_event_field name: next_comm 1557*4882a593Smuzhiyun type: char[16] 1558*4882a593Smuzhiyun size: 256 1559*4882a593Smuzhiyun is_signed: 0 1560*4882a593Smuzhiyun 1561*4882a593Smuzhiyun hist_data->save_vars[1]: 1562*4882a593Smuzhiyun 1563*4882a593Smuzhiyun save_vars[1].var: 1564*4882a593Smuzhiyun flags: 1565*4882a593Smuzhiyun HIST_FIELD_FL_VAR 1566*4882a593Smuzhiyun var.name: prev_pid 1567*4882a593Smuzhiyun var.idx (into tracing_map_elt.vars[]): 3 1568*4882a593Smuzhiyun 1569*4882a593Smuzhiyun save_vars[1].val: 1570*4882a593Smuzhiyun ftrace_event_field name: prev_pid 1571*4882a593Smuzhiyun type: pid_t 1572*4882a593Smuzhiyun size: 4 1573*4882a593Smuzhiyun is_signed: 1 1574*4882a593Smuzhiyun 1575*4882a593Smuzhiyun hist_data->save_vars[2]: 1576*4882a593Smuzhiyun 1577*4882a593Smuzhiyun save_vars[2].var: 1578*4882a593Smuzhiyun flags: 1579*4882a593Smuzhiyun HIST_FIELD_FL_VAR 1580*4882a593Smuzhiyun var.name: prev_prio 1581*4882a593Smuzhiyun var.idx (into tracing_map_elt.vars[]): 4 1582*4882a593Smuzhiyun 1583*4882a593Smuzhiyun save_vars[2].val: 1584*4882a593Smuzhiyun ftrace_event_field name: prev_prio 1585*4882a593Smuzhiyun type: int 1586*4882a593Smuzhiyun size: 4 1587*4882a593Smuzhiyun is_signed: 1 1588*4882a593Smuzhiyun 1589*4882a593Smuzhiyun hist_data->save_vars[3]: 1590*4882a593Smuzhiyun 1591*4882a593Smuzhiyun save_vars[3].var: 1592*4882a593Smuzhiyun flags: 1593*4882a593Smuzhiyun HIST_FIELD_FL_VAR 1594*4882a593Smuzhiyun var.name: prev_comm 1595*4882a593Smuzhiyun var.idx (into tracing_map_elt.vars[]): 5 1596*4882a593Smuzhiyun 1597*4882a593Smuzhiyun save_vars[3].val: 1598*4882a593Smuzhiyun ftrace_event_field name: prev_comm 1599*4882a593Smuzhiyun type: char[16] 1600*4882a593Smuzhiyun size: 256 1601*4882a593Smuzhiyun is_signed: 0 1602*4882a593Smuzhiyun 1603*4882a593SmuzhiyunThe commands below can be used to clean things up for the next test:: 1604*4882a593Smuzhiyun 1605*4882a593Smuzhiyun # echo '!hist:keys=next_pid:wakeup_lat=common_timestamp.usecs-$ts0:onmax($wakeup_lat).save(next_comm,prev_pid,prev_prio,prev_comm)' >> events/sched/sched_switch/trigger 1606*4882a593Smuzhiyun 1607*4882a593Smuzhiyun # echo '!hist:keys=pid:ts0=common_timestamp.usecs' >> events/sched/sched_waking/trigger 1608*4882a593Smuzhiyun 1609*4882a593SmuzhiyunA couple special cases 1610*4882a593Smuzhiyun====================== 1611*4882a593Smuzhiyun 1612*4882a593SmuzhiyunWhile the above covers the basics of the histogram internals, there 1613*4882a593Smuzhiyunare a couple of special cases that should be discussed, since they 1614*4882a593Smuzhiyuntend to create even more confusion. Those are field variables on other 1615*4882a593Smuzhiyunhistograms, and aliases, both described below through example tests 1616*4882a593Smuzhiyunusing the hist_debug files. 1617*4882a593Smuzhiyun 1618*4882a593SmuzhiyunTest of field variables on other histograms 1619*4882a593Smuzhiyun------------------------------------------- 1620*4882a593Smuzhiyun 1621*4882a593SmuzhiyunThis example is similar to the previous examples, but in this case, 1622*4882a593Smuzhiyunthe sched_switch trigger references a hist trigger field on another 1623*4882a593Smuzhiyunevent, namely the sched_waking event. In order to accomplish this, a 1624*4882a593Smuzhiyunfield variable is created for the other event, but since an existing 1625*4882a593Smuzhiyunhistogram can't be used, as existing histograms are immutable, a new 1626*4882a593Smuzhiyunhistogram with a matching variable is created and used, and we'll see 1627*4882a593Smuzhiyunthat reflected in the hist_debug output shown below. 1628*4882a593Smuzhiyun 1629*4882a593SmuzhiyunFirst, we create the wakeup_latency synthetic event. Note the 1630*4882a593Smuzhiyunaddition of the prio field:: 1631*4882a593Smuzhiyun 1632*4882a593Smuzhiyun # echo 'wakeup_latency u64 lat; pid_t pid; int prio' >> synthetic_events 1633*4882a593Smuzhiyun 1634*4882a593SmuzhiyunAs in previous test examples, we set up the sched_waking trigger:: 1635*4882a593Smuzhiyun 1636*4882a593Smuzhiyun # echo 'hist:keys=pid:ts0=common_timestamp.usecs' >> events/sched/sched_waking/trigger 1637*4882a593Smuzhiyun 1638*4882a593SmuzhiyunHere we set up a hist trigger on sched_switch to send a wakeup_latency 1639*4882a593Smuzhiyunevent using an onmatch handler naming the sched_waking event. Note 1640*4882a593Smuzhiyunthat the third param being passed to the wakeup_latency() is prio, 1641*4882a593Smuzhiyunwhich is a field name that needs to have a field variable created for 1642*4882a593Smuzhiyunit. There isn't however any prio field on the sched_switch event so 1643*4882a593Smuzhiyunit would seem that it wouldn't be possible to create a field variable 1644*4882a593Smuzhiyunfor it. The matching sched_waking event does have a prio field, so it 1645*4882a593Smuzhiyunshould be possible to make use of it for this purpose. The problem 1646*4882a593Smuzhiyunwith that is that it's not currently possible to define a new variable 1647*4882a593Smuzhiyunon an existing histogram, so it's not possible to add a new prio field 1648*4882a593Smuzhiyunvariable to the existing sched_waking histogram. It is however 1649*4882a593Smuzhiyunpossible to create an additional new 'matching' sched_waking histogram 1650*4882a593Smuzhiyunfor the same event, meaning that it uses the same key and filters, and 1651*4882a593Smuzhiyundefine the new prio field variable on that. 1652*4882a593Smuzhiyun 1653*4882a593SmuzhiyunHere's the sched_switch trigger:: 1654*4882a593Smuzhiyun 1655*4882a593Smuzhiyun # echo 'hist:keys=next_pid:wakeup_lat=common_timestamp.usecs-$ts0:onmatch(sched.sched_waking).wakeup_latency($wakeup_lat,next_pid,prio)' >> events/sched/sched_switch/trigger 1656*4882a593Smuzhiyun 1657*4882a593SmuzhiyunAnd here's the output of the hist_debug information for the 1658*4882a593Smuzhiyunsched_waking hist trigger. Note that there are two histograms 1659*4882a593Smuzhiyundisplayed in the output: the first is the normal sched_waking 1660*4882a593Smuzhiyunhistogram we've seen in the previous examples, and the second is the 1661*4882a593Smuzhiyunspecial histogram we created to provide the prio field variable. 1662*4882a593Smuzhiyun 1663*4882a593SmuzhiyunLooking at the second histogram below, we see a variable with the name 1664*4882a593Smuzhiyunsynthetic_prio. This is the field variable created for the prio field 1665*4882a593Smuzhiyunon that sched_waking histogram:: 1666*4882a593Smuzhiyun 1667*4882a593Smuzhiyun # cat events/sched/sched_waking/hist_debug 1668*4882a593Smuzhiyun 1669*4882a593Smuzhiyun # event histogram 1670*4882a593Smuzhiyun # 1671*4882a593Smuzhiyun # trigger info: hist:keys=pid:vals=hitcount:ts0=common_timestamp.usecs:sort=hitcount:size=2048:clock=global [active] 1672*4882a593Smuzhiyun # 1673*4882a593Smuzhiyun 1674*4882a593Smuzhiyun hist_data: 00000000349570e4 1675*4882a593Smuzhiyun 1676*4882a593Smuzhiyun n_vals: 2 1677*4882a593Smuzhiyun n_keys: 1 1678*4882a593Smuzhiyun n_fields: 3 1679*4882a593Smuzhiyun 1680*4882a593Smuzhiyun val fields: 1681*4882a593Smuzhiyun 1682*4882a593Smuzhiyun hist_data->fields[0]: 1683*4882a593Smuzhiyun flags: 1684*4882a593Smuzhiyun VAL: HIST_FIELD_FL_HITCOUNT 1685*4882a593Smuzhiyun type: u64 1686*4882a593Smuzhiyun size: 8 1687*4882a593Smuzhiyun is_signed: 0 1688*4882a593Smuzhiyun 1689*4882a593Smuzhiyun hist_data->fields[1]: 1690*4882a593Smuzhiyun flags: 1691*4882a593Smuzhiyun HIST_FIELD_FL_VAR 1692*4882a593Smuzhiyun var.name: ts0 1693*4882a593Smuzhiyun var.idx (into tracing_map_elt.vars[]): 0 1694*4882a593Smuzhiyun type: u64 1695*4882a593Smuzhiyun size: 8 1696*4882a593Smuzhiyun is_signed: 0 1697*4882a593Smuzhiyun 1698*4882a593Smuzhiyun key fields: 1699*4882a593Smuzhiyun 1700*4882a593Smuzhiyun hist_data->fields[2]: 1701*4882a593Smuzhiyun flags: 1702*4882a593Smuzhiyun HIST_FIELD_FL_KEY 1703*4882a593Smuzhiyun ftrace_event_field name: pid 1704*4882a593Smuzhiyun type: pid_t 1705*4882a593Smuzhiyun size: 8 1706*4882a593Smuzhiyun is_signed: 1 1707*4882a593Smuzhiyun 1708*4882a593Smuzhiyun 1709*4882a593Smuzhiyun # event histogram 1710*4882a593Smuzhiyun # 1711*4882a593Smuzhiyun # trigger info: hist:keys=pid:vals=hitcount:synthetic_prio=prio:sort=hitcount:size=2048 [active] 1712*4882a593Smuzhiyun # 1713*4882a593Smuzhiyun 1714*4882a593Smuzhiyun hist_data: 000000006920cf38 1715*4882a593Smuzhiyun 1716*4882a593Smuzhiyun n_vals: 2 1717*4882a593Smuzhiyun n_keys: 1 1718*4882a593Smuzhiyun n_fields: 3 1719*4882a593Smuzhiyun 1720*4882a593Smuzhiyun val fields: 1721*4882a593Smuzhiyun 1722*4882a593Smuzhiyun hist_data->fields[0]: 1723*4882a593Smuzhiyun flags: 1724*4882a593Smuzhiyun VAL: HIST_FIELD_FL_HITCOUNT 1725*4882a593Smuzhiyun type: u64 1726*4882a593Smuzhiyun size: 8 1727*4882a593Smuzhiyun is_signed: 0 1728*4882a593Smuzhiyun 1729*4882a593Smuzhiyun hist_data->fields[1]: 1730*4882a593Smuzhiyun flags: 1731*4882a593Smuzhiyun HIST_FIELD_FL_VAR 1732*4882a593Smuzhiyun ftrace_event_field name: prio 1733*4882a593Smuzhiyun var.name: synthetic_prio 1734*4882a593Smuzhiyun var.idx (into tracing_map_elt.vars[]): 0 1735*4882a593Smuzhiyun type: int 1736*4882a593Smuzhiyun size: 4 1737*4882a593Smuzhiyun is_signed: 1 1738*4882a593Smuzhiyun 1739*4882a593Smuzhiyun key fields: 1740*4882a593Smuzhiyun 1741*4882a593Smuzhiyun hist_data->fields[2]: 1742*4882a593Smuzhiyun flags: 1743*4882a593Smuzhiyun HIST_FIELD_FL_KEY 1744*4882a593Smuzhiyun ftrace_event_field name: pid 1745*4882a593Smuzhiyun type: pid_t 1746*4882a593Smuzhiyun size: 8 1747*4882a593Smuzhiyun is_signed: 1 1748*4882a593Smuzhiyun 1749*4882a593SmuzhiyunLooking at the sched_switch histogram below, we can see a reference to 1750*4882a593Smuzhiyunthe synthetic_prio variable on sched_waking, and looking at the 1751*4882a593Smuzhiyunassociated hist_data address we see that it is indeed associated with 1752*4882a593Smuzhiyunthe new histogram. Note also that the other references are to a 1753*4882a593Smuzhiyunnormal variable, wakeup_lat, and to a normal field variable, next_pid, 1754*4882a593Smuzhiyunthe details of which are in the field variables section:: 1755*4882a593Smuzhiyun 1756*4882a593Smuzhiyun # cat events/sched/sched_switch/hist_debug 1757*4882a593Smuzhiyun 1758*4882a593Smuzhiyun # event histogram 1759*4882a593Smuzhiyun # 1760*4882a593Smuzhiyun # trigger info: hist:keys=next_pid:vals=hitcount:wakeup_lat=common_timestamp.usecs-$ts0:sort=hitcount:size=2048:clock=global:onmatch(sched.sched_waking).wakeup_latency($wakeup_lat,next_pid,prio) [active] 1761*4882a593Smuzhiyun # 1762*4882a593Smuzhiyun 1763*4882a593Smuzhiyun hist_data: 00000000a73b67df 1764*4882a593Smuzhiyun 1765*4882a593Smuzhiyun n_vals: 2 1766*4882a593Smuzhiyun n_keys: 1 1767*4882a593Smuzhiyun n_fields: 3 1768*4882a593Smuzhiyun 1769*4882a593Smuzhiyun val fields: 1770*4882a593Smuzhiyun 1771*4882a593Smuzhiyun hist_data->fields[0]: 1772*4882a593Smuzhiyun flags: 1773*4882a593Smuzhiyun VAL: HIST_FIELD_FL_HITCOUNT 1774*4882a593Smuzhiyun type: u64 1775*4882a593Smuzhiyun size: 8 1776*4882a593Smuzhiyun is_signed: 0 1777*4882a593Smuzhiyun 1778*4882a593Smuzhiyun hist_data->fields[1]: 1779*4882a593Smuzhiyun flags: 1780*4882a593Smuzhiyun HIST_FIELD_FL_VAR 1781*4882a593Smuzhiyun var.name: wakeup_lat 1782*4882a593Smuzhiyun var.idx (into tracing_map_elt.vars[]): 0 1783*4882a593Smuzhiyun type: u64 1784*4882a593Smuzhiyun size: 0 1785*4882a593Smuzhiyun is_signed: 0 1786*4882a593Smuzhiyun 1787*4882a593Smuzhiyun key fields: 1788*4882a593Smuzhiyun 1789*4882a593Smuzhiyun hist_data->fields[2]: 1790*4882a593Smuzhiyun flags: 1791*4882a593Smuzhiyun HIST_FIELD_FL_KEY 1792*4882a593Smuzhiyun ftrace_event_field name: next_pid 1793*4882a593Smuzhiyun type: pid_t 1794*4882a593Smuzhiyun size: 8 1795*4882a593Smuzhiyun is_signed: 1 1796*4882a593Smuzhiyun 1797*4882a593Smuzhiyun variable reference fields: 1798*4882a593Smuzhiyun 1799*4882a593Smuzhiyun hist_data->var_refs[0]: 1800*4882a593Smuzhiyun flags: 1801*4882a593Smuzhiyun HIST_FIELD_FL_VAR_REF 1802*4882a593Smuzhiyun name: ts0 1803*4882a593Smuzhiyun var.idx (into tracing_map_elt.vars[]): 0 1804*4882a593Smuzhiyun var.hist_data: 00000000349570e4 1805*4882a593Smuzhiyun var_ref_idx (into hist_data->var_refs[]): 0 1806*4882a593Smuzhiyun type: u64 1807*4882a593Smuzhiyun size: 8 1808*4882a593Smuzhiyun is_signed: 0 1809*4882a593Smuzhiyun 1810*4882a593Smuzhiyun hist_data->var_refs[1]: 1811*4882a593Smuzhiyun flags: 1812*4882a593Smuzhiyun HIST_FIELD_FL_VAR_REF 1813*4882a593Smuzhiyun name: wakeup_lat 1814*4882a593Smuzhiyun var.idx (into tracing_map_elt.vars[]): 0 1815*4882a593Smuzhiyun var.hist_data: 00000000a73b67df 1816*4882a593Smuzhiyun var_ref_idx (into hist_data->var_refs[]): 1 1817*4882a593Smuzhiyun type: u64 1818*4882a593Smuzhiyun size: 0 1819*4882a593Smuzhiyun is_signed: 0 1820*4882a593Smuzhiyun 1821*4882a593Smuzhiyun hist_data->var_refs[2]: 1822*4882a593Smuzhiyun flags: 1823*4882a593Smuzhiyun HIST_FIELD_FL_VAR_REF 1824*4882a593Smuzhiyun name: next_pid 1825*4882a593Smuzhiyun var.idx (into tracing_map_elt.vars[]): 1 1826*4882a593Smuzhiyun var.hist_data: 00000000a73b67df 1827*4882a593Smuzhiyun var_ref_idx (into hist_data->var_refs[]): 2 1828*4882a593Smuzhiyun type: pid_t 1829*4882a593Smuzhiyun size: 4 1830*4882a593Smuzhiyun is_signed: 0 1831*4882a593Smuzhiyun 1832*4882a593Smuzhiyun hist_data->var_refs[3]: 1833*4882a593Smuzhiyun flags: 1834*4882a593Smuzhiyun HIST_FIELD_FL_VAR_REF 1835*4882a593Smuzhiyun name: synthetic_prio 1836*4882a593Smuzhiyun var.idx (into tracing_map_elt.vars[]): 0 1837*4882a593Smuzhiyun var.hist_data: 000000006920cf38 1838*4882a593Smuzhiyun var_ref_idx (into hist_data->var_refs[]): 3 1839*4882a593Smuzhiyun type: int 1840*4882a593Smuzhiyun size: 4 1841*4882a593Smuzhiyun is_signed: 1 1842*4882a593Smuzhiyun 1843*4882a593Smuzhiyun field variables: 1844*4882a593Smuzhiyun 1845*4882a593Smuzhiyun hist_data->field_vars[0]: 1846*4882a593Smuzhiyun 1847*4882a593Smuzhiyun field_vars[0].var: 1848*4882a593Smuzhiyun flags: 1849*4882a593Smuzhiyun HIST_FIELD_FL_VAR 1850*4882a593Smuzhiyun var.name: next_pid 1851*4882a593Smuzhiyun var.idx (into tracing_map_elt.vars[]): 1 1852*4882a593Smuzhiyun 1853*4882a593Smuzhiyun field_vars[0].val: 1854*4882a593Smuzhiyun ftrace_event_field name: next_pid 1855*4882a593Smuzhiyun type: pid_t 1856*4882a593Smuzhiyun size: 4 1857*4882a593Smuzhiyun is_signed: 1 1858*4882a593Smuzhiyun 1859*4882a593Smuzhiyun action tracking variables (for onmax()/onchange()/onmatch()): 1860*4882a593Smuzhiyun 1861*4882a593Smuzhiyun hist_data->actions[0].match_data.event_system: sched 1862*4882a593Smuzhiyun hist_data->actions[0].match_data.event: sched_waking 1863*4882a593Smuzhiyun 1864*4882a593SmuzhiyunThe commands below can be used to clean things up for the next test:: 1865*4882a593Smuzhiyun 1866*4882a593Smuzhiyun # echo '!hist:keys=next_pid:wakeup_lat=common_timestamp.usecs-$ts0:onmatch(sched.sched_waking).wakeup_latency($wakeup_lat,next_pid,prio)' >> events/sched/sched_switch/trigger 1867*4882a593Smuzhiyun 1868*4882a593Smuzhiyun # echo '!hist:keys=pid:ts0=common_timestamp.usecs' >> events/sched/sched_waking/trigger 1869*4882a593Smuzhiyun 1870*4882a593Smuzhiyun # echo '!wakeup_latency u64 lat; pid_t pid; int prio' >> synthetic_events 1871*4882a593Smuzhiyun 1872*4882a593SmuzhiyunAlias test 1873*4882a593Smuzhiyun---------- 1874*4882a593Smuzhiyun 1875*4882a593SmuzhiyunThis example is very similar to previous examples, but demonstrates 1876*4882a593Smuzhiyunthe alias flag. 1877*4882a593Smuzhiyun 1878*4882a593SmuzhiyunFirst, we create the wakeup_latency synthetic event:: 1879*4882a593Smuzhiyun 1880*4882a593Smuzhiyun # echo 'wakeup_latency u64 lat; pid_t pid; char comm[16]' >> synthetic_events 1881*4882a593Smuzhiyun 1882*4882a593SmuzhiyunNext, we create a sched_waking trigger similar to previous examples, 1883*4882a593Smuzhiyunbut in this case we save the pid in the waking_pid variable:: 1884*4882a593Smuzhiyun 1885*4882a593Smuzhiyun # echo 'hist:keys=pid:waking_pid=pid:ts0=common_timestamp.usecs' >> events/sched/sched_waking/trigger 1886*4882a593Smuzhiyun 1887*4882a593SmuzhiyunFor the sched_switch trigger, instead of using $waking_pid directly in 1888*4882a593Smuzhiyunthe wakeup_latency synthetic event invocation, we create an alias of 1889*4882a593Smuzhiyun$waking_pid named $woken_pid, and use that in the synthetic event 1890*4882a593Smuzhiyuninvocation instead:: 1891*4882a593Smuzhiyun 1892*4882a593Smuzhiyun # echo 'hist:keys=next_pid:woken_pid=$waking_pid:wakeup_lat=common_timestamp.usecs-$ts0:onmatch(sched.sched_waking).wakeup_latency($wakeup_lat,$woken_pid,next_comm)' >> events/sched/sched_switch/trigger 1893*4882a593Smuzhiyun 1894*4882a593SmuzhiyunLooking at the sched_waking hist_debug output, in addition to the 1895*4882a593Smuzhiyunnormal fields, we can see the waking_pid variable:: 1896*4882a593Smuzhiyun 1897*4882a593Smuzhiyun # cat events/sched/sched_waking/hist_debug 1898*4882a593Smuzhiyun 1899*4882a593Smuzhiyun # event histogram 1900*4882a593Smuzhiyun # 1901*4882a593Smuzhiyun # trigger info: hist:keys=pid:vals=hitcount:waking_pid=pid,ts0=common_timestamp.usecs:sort=hitcount:size=2048:clock=global [active] 1902*4882a593Smuzhiyun # 1903*4882a593Smuzhiyun 1904*4882a593Smuzhiyun hist_data: 00000000a250528c 1905*4882a593Smuzhiyun 1906*4882a593Smuzhiyun n_vals: 3 1907*4882a593Smuzhiyun n_keys: 1 1908*4882a593Smuzhiyun n_fields: 4 1909*4882a593Smuzhiyun 1910*4882a593Smuzhiyun val fields: 1911*4882a593Smuzhiyun 1912*4882a593Smuzhiyun hist_data->fields[0]: 1913*4882a593Smuzhiyun flags: 1914*4882a593Smuzhiyun VAL: HIST_FIELD_FL_HITCOUNT 1915*4882a593Smuzhiyun type: u64 1916*4882a593Smuzhiyun size: 8 1917*4882a593Smuzhiyun is_signed: 0 1918*4882a593Smuzhiyun 1919*4882a593Smuzhiyun hist_data->fields[1]: 1920*4882a593Smuzhiyun flags: 1921*4882a593Smuzhiyun HIST_FIELD_FL_VAR 1922*4882a593Smuzhiyun ftrace_event_field name: pid 1923*4882a593Smuzhiyun var.name: waking_pid 1924*4882a593Smuzhiyun var.idx (into tracing_map_elt.vars[]): 0 1925*4882a593Smuzhiyun type: pid_t 1926*4882a593Smuzhiyun size: 4 1927*4882a593Smuzhiyun is_signed: 1 1928*4882a593Smuzhiyun 1929*4882a593Smuzhiyun hist_data->fields[2]: 1930*4882a593Smuzhiyun flags: 1931*4882a593Smuzhiyun HIST_FIELD_FL_VAR 1932*4882a593Smuzhiyun var.name: ts0 1933*4882a593Smuzhiyun var.idx (into tracing_map_elt.vars[]): 1 1934*4882a593Smuzhiyun type: u64 1935*4882a593Smuzhiyun size: 8 1936*4882a593Smuzhiyun is_signed: 0 1937*4882a593Smuzhiyun 1938*4882a593Smuzhiyun key fields: 1939*4882a593Smuzhiyun 1940*4882a593Smuzhiyun hist_data->fields[3]: 1941*4882a593Smuzhiyun flags: 1942*4882a593Smuzhiyun HIST_FIELD_FL_KEY 1943*4882a593Smuzhiyun ftrace_event_field name: pid 1944*4882a593Smuzhiyun type: pid_t 1945*4882a593Smuzhiyun size: 8 1946*4882a593Smuzhiyun is_signed: 1 1947*4882a593Smuzhiyun 1948*4882a593SmuzhiyunThe sched_switch hist_debug output shows that a variable named 1949*4882a593Smuzhiyunwoken_pid has been created but that it also has the 1950*4882a593SmuzhiyunHIST_FIELD_FL_ALIAS flag set. It also has the HIST_FIELD_FL_VAR flag 1951*4882a593Smuzhiyunset, which is why it appears in the val field section. 1952*4882a593Smuzhiyun 1953*4882a593SmuzhiyunDespite that implementation detail, an alias variable is actually more 1954*4882a593Smuzhiyunlike a variable reference; in fact it can be thought of as a reference 1955*4882a593Smuzhiyunto a reference. The implementation copies the var_ref->fn() from the 1956*4882a593Smuzhiyunvariable reference being referenced, in this case, the waking_pid 1957*4882a593Smuzhiyunfn(), which is hist_field_var_ref() and makes that the fn() of the 1958*4882a593Smuzhiyunalias. The hist_field_var_ref() fn() requires the var_ref_idx of the 1959*4882a593Smuzhiyunvariable reference it's using, so waking_pid's var_ref_idx is also 1960*4882a593Smuzhiyuncopied to the alias. The end result is that when the value of alias 1961*4882a593Smuzhiyunis retrieved, in the end it just does the same thing the original 1962*4882a593Smuzhiyunreference would have done and retrieves the same value from the 1963*4882a593Smuzhiyunvar_ref_vals[] array. You can verify this in the output by noting 1964*4882a593Smuzhiyunthat the var_ref_idx of the alias, in this case woken_pid, is the same 1965*4882a593Smuzhiyunas the var_ref_idx of the reference, waking_pid, in the variable 1966*4882a593Smuzhiyunreference fields section. 1967*4882a593Smuzhiyun 1968*4882a593SmuzhiyunAdditionally, once it gets that value, since it is also a variable, it 1969*4882a593Smuzhiyunthen saves that value into its var.idx. So the var.idx of the 1970*4882a593Smuzhiyunwoken_pid alias is 0, which it fills with the value from var_ref_idx 0 1971*4882a593Smuzhiyunwhen its fn() is called to update itself. You'll also notice that 1972*4882a593Smuzhiyunthere's a woken_pid var_ref in the variable refs section. That is the 1973*4882a593Smuzhiyunreference to the woken_pid alias variable, and you can see that it 1974*4882a593Smuzhiyunretrieves the value from the same var.idx as the woken_pid alias, 0, 1975*4882a593Smuzhiyunand then in turn saves that value in its own var_ref_idx slot, 3, and 1976*4882a593Smuzhiyunthe value at this position is finally what gets assigned to the 1977*4882a593Smuzhiyun$woken_pid slot in the trace event invocation:: 1978*4882a593Smuzhiyun 1979*4882a593Smuzhiyun # cat events/sched/sched_switch/hist_debug 1980*4882a593Smuzhiyun 1981*4882a593Smuzhiyun # event histogram 1982*4882a593Smuzhiyun # 1983*4882a593Smuzhiyun # trigger info: hist:keys=next_pid:vals=hitcount:woken_pid=$waking_pid,wakeup_lat=common_timestamp.usecs-$ts0:sort=hitcount:size=2048:clock=global:onmatch(sched.sched_waking).wakeup_latency($wakeup_lat,$woken_pid,next_comm) [active] 1984*4882a593Smuzhiyun # 1985*4882a593Smuzhiyun 1986*4882a593Smuzhiyun hist_data: 0000000055d65ed0 1987*4882a593Smuzhiyun 1988*4882a593Smuzhiyun n_vals: 3 1989*4882a593Smuzhiyun n_keys: 1 1990*4882a593Smuzhiyun n_fields: 4 1991*4882a593Smuzhiyun 1992*4882a593Smuzhiyun val fields: 1993*4882a593Smuzhiyun 1994*4882a593Smuzhiyun hist_data->fields[0]: 1995*4882a593Smuzhiyun flags: 1996*4882a593Smuzhiyun VAL: HIST_FIELD_FL_HITCOUNT 1997*4882a593Smuzhiyun type: u64 1998*4882a593Smuzhiyun size: 8 1999*4882a593Smuzhiyun is_signed: 0 2000*4882a593Smuzhiyun 2001*4882a593Smuzhiyun hist_data->fields[1]: 2002*4882a593Smuzhiyun flags: 2003*4882a593Smuzhiyun HIST_FIELD_FL_VAR 2004*4882a593Smuzhiyun HIST_FIELD_FL_ALIAS 2005*4882a593Smuzhiyun var.name: woken_pid 2006*4882a593Smuzhiyun var.idx (into tracing_map_elt.vars[]): 0 2007*4882a593Smuzhiyun var_ref_idx (into hist_data->var_refs[]): 0 2008*4882a593Smuzhiyun type: pid_t 2009*4882a593Smuzhiyun size: 4 2010*4882a593Smuzhiyun is_signed: 1 2011*4882a593Smuzhiyun 2012*4882a593Smuzhiyun hist_data->fields[2]: 2013*4882a593Smuzhiyun flags: 2014*4882a593Smuzhiyun HIST_FIELD_FL_VAR 2015*4882a593Smuzhiyun var.name: wakeup_lat 2016*4882a593Smuzhiyun var.idx (into tracing_map_elt.vars[]): 1 2017*4882a593Smuzhiyun type: u64 2018*4882a593Smuzhiyun size: 0 2019*4882a593Smuzhiyun is_signed: 0 2020*4882a593Smuzhiyun 2021*4882a593Smuzhiyun key fields: 2022*4882a593Smuzhiyun 2023*4882a593Smuzhiyun hist_data->fields[3]: 2024*4882a593Smuzhiyun flags: 2025*4882a593Smuzhiyun HIST_FIELD_FL_KEY 2026*4882a593Smuzhiyun ftrace_event_field name: next_pid 2027*4882a593Smuzhiyun type: pid_t 2028*4882a593Smuzhiyun size: 8 2029*4882a593Smuzhiyun is_signed: 1 2030*4882a593Smuzhiyun 2031*4882a593Smuzhiyun variable reference fields: 2032*4882a593Smuzhiyun 2033*4882a593Smuzhiyun hist_data->var_refs[0]: 2034*4882a593Smuzhiyun flags: 2035*4882a593Smuzhiyun HIST_FIELD_FL_VAR_REF 2036*4882a593Smuzhiyun name: waking_pid 2037*4882a593Smuzhiyun var.idx (into tracing_map_elt.vars[]): 0 2038*4882a593Smuzhiyun var.hist_data: 00000000a250528c 2039*4882a593Smuzhiyun var_ref_idx (into hist_data->var_refs[]): 0 2040*4882a593Smuzhiyun type: pid_t 2041*4882a593Smuzhiyun size: 4 2042*4882a593Smuzhiyun is_signed: 1 2043*4882a593Smuzhiyun 2044*4882a593Smuzhiyun hist_data->var_refs[1]: 2045*4882a593Smuzhiyun flags: 2046*4882a593Smuzhiyun HIST_FIELD_FL_VAR_REF 2047*4882a593Smuzhiyun name: ts0 2048*4882a593Smuzhiyun var.idx (into tracing_map_elt.vars[]): 1 2049*4882a593Smuzhiyun var.hist_data: 00000000a250528c 2050*4882a593Smuzhiyun var_ref_idx (into hist_data->var_refs[]): 1 2051*4882a593Smuzhiyun type: u64 2052*4882a593Smuzhiyun size: 8 2053*4882a593Smuzhiyun is_signed: 0 2054*4882a593Smuzhiyun 2055*4882a593Smuzhiyun hist_data->var_refs[2]: 2056*4882a593Smuzhiyun flags: 2057*4882a593Smuzhiyun HIST_FIELD_FL_VAR_REF 2058*4882a593Smuzhiyun name: wakeup_lat 2059*4882a593Smuzhiyun var.idx (into tracing_map_elt.vars[]): 1 2060*4882a593Smuzhiyun var.hist_data: 0000000055d65ed0 2061*4882a593Smuzhiyun var_ref_idx (into hist_data->var_refs[]): 2 2062*4882a593Smuzhiyun type: u64 2063*4882a593Smuzhiyun size: 0 2064*4882a593Smuzhiyun is_signed: 0 2065*4882a593Smuzhiyun 2066*4882a593Smuzhiyun hist_data->var_refs[3]: 2067*4882a593Smuzhiyun flags: 2068*4882a593Smuzhiyun HIST_FIELD_FL_VAR_REF 2069*4882a593Smuzhiyun name: woken_pid 2070*4882a593Smuzhiyun var.idx (into tracing_map_elt.vars[]): 0 2071*4882a593Smuzhiyun var.hist_data: 0000000055d65ed0 2072*4882a593Smuzhiyun var_ref_idx (into hist_data->var_refs[]): 3 2073*4882a593Smuzhiyun type: pid_t 2074*4882a593Smuzhiyun size: 4 2075*4882a593Smuzhiyun is_signed: 1 2076*4882a593Smuzhiyun 2077*4882a593Smuzhiyun hist_data->var_refs[4]: 2078*4882a593Smuzhiyun flags: 2079*4882a593Smuzhiyun HIST_FIELD_FL_VAR_REF 2080*4882a593Smuzhiyun name: next_comm 2081*4882a593Smuzhiyun var.idx (into tracing_map_elt.vars[]): 2 2082*4882a593Smuzhiyun var.hist_data: 0000000055d65ed0 2083*4882a593Smuzhiyun var_ref_idx (into hist_data->var_refs[]): 4 2084*4882a593Smuzhiyun type: char[16] 2085*4882a593Smuzhiyun size: 256 2086*4882a593Smuzhiyun is_signed: 0 2087*4882a593Smuzhiyun 2088*4882a593Smuzhiyun field variables: 2089*4882a593Smuzhiyun 2090*4882a593Smuzhiyun hist_data->field_vars[0]: 2091*4882a593Smuzhiyun 2092*4882a593Smuzhiyun field_vars[0].var: 2093*4882a593Smuzhiyun flags: 2094*4882a593Smuzhiyun HIST_FIELD_FL_VAR 2095*4882a593Smuzhiyun var.name: next_comm 2096*4882a593Smuzhiyun var.idx (into tracing_map_elt.vars[]): 2 2097*4882a593Smuzhiyun 2098*4882a593Smuzhiyun field_vars[0].val: 2099*4882a593Smuzhiyun ftrace_event_field name: next_comm 2100*4882a593Smuzhiyun type: char[16] 2101*4882a593Smuzhiyun size: 256 2102*4882a593Smuzhiyun is_signed: 0 2103*4882a593Smuzhiyun 2104*4882a593Smuzhiyun action tracking variables (for onmax()/onchange()/onmatch()): 2105*4882a593Smuzhiyun 2106*4882a593Smuzhiyun hist_data->actions[0].match_data.event_system: sched 2107*4882a593Smuzhiyun hist_data->actions[0].match_data.event: sched_waking 2108*4882a593Smuzhiyun 2109*4882a593SmuzhiyunThe commands below can be used to clean things up for the next test:: 2110*4882a593Smuzhiyun 2111*4882a593Smuzhiyun # echo '!hist:keys=next_pid:woken_pid=$waking_pid:wakeup_lat=common_timestamp.usecs-$ts0:onmatch(sched.sched_waking).wakeup_latency($wakeup_lat,$woken_pid,next_comm)' >> events/sched/sched_switch/trigger 2112*4882a593Smuzhiyun 2113*4882a593Smuzhiyun # echo '!hist:keys=pid:ts0=common_timestamp.usecs' >> events/sched/sched_waking/trigger 2114*4882a593Smuzhiyun 2115*4882a593Smuzhiyun # echo '!wakeup_latency u64 lat; pid_t pid; char comm[16]' >> synthetic_events 2116