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