0001 .. SPDX-License-Identifier: GPL-2.0
0002
0003 ======================
0004 Histogram Design Notes
0005 ======================
0006
0007 :Author: Tom Zanussi <zanussi@kernel.org>
0008
0009 This document attempts to provide a description of how the ftrace
0010 histograms work and how the individual pieces map to the data
0011 structures used to implement them in trace_events_hist.c and
0012 tracing_map.c.
0013
0014 Note: All the ftrace histogram command examples assume the working
0015 directory is the ftrace /tracing directory. For example::
0016
0017 # cd /sys/kernel/debug/tracing
0018
0019 Also, the histogram output displayed for those commands will be
0020 generally be truncated - only enough to make the point is displayed.
0021
0022 'hist_debug' trace event files
0023 ==============================
0024
0025 If the kernel is compiled with CONFIG_HIST_TRIGGERS_DEBUG set, an
0026 event file named 'hist_debug' will appear in each event's
0027 subdirectory. This file can be read at any time and will display some
0028 of the hist trigger internals described in this document. Specific
0029 examples and output will be described in test cases below.
0030
0031 Basic histograms
0032 ================
0033
0034 First, basic histograms. Below is pretty much the simplest thing you
0035 can do with histograms - create one with a single key on a single
0036 event and cat the output::
0037
0038 # echo 'hist:keys=pid' >> events/sched/sched_waking/trigger
0039
0040 # cat events/sched/sched_waking/hist
0041
0042 { pid: 18249 } hitcount: 1
0043 { pid: 13399 } hitcount: 1
0044 { pid: 17973 } hitcount: 1
0045 { pid: 12572 } hitcount: 1
0046 ...
0047 { pid: 10 } hitcount: 921
0048 { pid: 18255 } hitcount: 1444
0049 { pid: 25526 } hitcount: 2055
0050 { pid: 5257 } hitcount: 2055
0051 { pid: 27367 } hitcount: 2055
0052 { pid: 1728 } hitcount: 2161
0053
0054 Totals:
0055 Hits: 21305
0056 Entries: 183
0057 Dropped: 0
0058
0059 What this does is create a histogram on the sched_waking event using
0060 pid as a key and with a single value, hitcount, which even if not
0061 explicitly specified, exists for every histogram regardless.
0062
0063 The hitcount value is a per-bucket value that's automatically
0064 incremented on every hit for the given key, which in this case is the
0065 pid.
0066
0067 So in this histogram, there's a separate bucket for each pid, and each
0068 bucket contains a value for that bucket, counting the number of times
0069 sched_waking was called for that pid.
0070
0071 Each histogram is represented by a hist_data struct.
0072
0073 To keep track of each key and value field in the histogram, hist_data
0074 keeps an array of these fields named fields[]. The fields[] array is
0075 an array containing struct hist_field representations of each
0076 histogram val and key in the histogram (variables are also included
0077 here, but are discussed later). So for the above histogram we have one
0078 key and one value; in this case the one value is the hitcount value,
0079 which all histograms have, regardless of whether they define that
0080 value or not, which the above histogram does not.
0081
0082 Each struct hist_field contains a pointer to the ftrace_event_field
0083 from the event's trace_event_file along with various bits related to
0084 that such as the size, offset, type, and a hist_field_fn_t function,
0085 which is used to grab the field's data from the ftrace event buffer
0086 (in most cases - some hist_fields such as hitcount don't directly map
0087 to an event field in the trace buffer - in these cases the function
0088 implementation gets its value from somewhere else). The flags field
0089 indicates which type of field it is - key, value, variable, variable
0090 reference, etc., with value being the default.
0091
0092 The other important hist_data data structure in addition to the
0093 fields[] array is the tracing_map instance created for the histogram,
0094 which is held in the .map member. The tracing_map implements the
0095 lock-free hash table used to implement histograms (see
0096 kernel/trace/tracing_map.h for much more discussion about the
0097 low-level data structures implementing the tracing_map). For the
0098 purposes of this discussion, the tracing_map contains a number of
0099 buckets, each bucket corresponding to a particular tracing_map_elt
0100 object hashed by a given histogram key.
0101
0102 Below is a diagram the first part of which describes the hist_data and
0103 associated key and value fields for the histogram described above. As
0104 you can see, there are two fields in the fields array, one val field
0105 for the hitcount and one key field for the pid key.
0106
0107 Below that is a diagram of a run-time snapshot of what the tracing_map
0108 might look like for a given run. It attempts to show the
0109 relationships between the hist_data fields and the tracing_map
0110 elements for a couple hypothetical keys and values.::
0111
0112 +------------------+
0113 | hist_data |
0114 +------------------+ +----------------+
0115 | .fields[] |---->| val = hitcount |----------------------------+
0116 +----------------+ +----------------+ |
0117 | .map | | .size | |
0118 +----------------+ +--------------+ |
0119 | .offset | |
0120 +--------------+ |
0121 | .fn() | |
0122 +--------------+ |
0123 . |
0124 . |
0125 . |
0126 +----------------+ <--- n_vals |
0127 | key = pid |----------------------------|--+
0128 +----------------+ | |
0129 | .size | | |
0130 +--------------+ | |
0131 | .offset | | |
0132 +--------------+ | |
0133 | .fn() | | |
0134 +----------------+ <--- n_fields | |
0135 | unused | | |
0136 +----------------+ | |
0137 | | | |
0138 +--------------+ | |
0139 | | | |
0140 +--------------+ | |
0141 | | | |
0142 +--------------+ | |
0143 n_keys = n_fields - n_vals | |
0144
0145 The hist_data n_vals and n_fields delineate the extent of the fields[] | |
0146 array and separate keys from values for the rest of the code. | |
0147
0148 Below is a run-time representation of the tracing_map part of the | |
0149 histogram, with pointers from various parts of the fields[] array | |
0150 to corresponding parts of the tracing_map. | |
0151
0152 The tracing_map consists of an array of tracing_map_entrys and a set | |
0153 of preallocated tracing_map_elts (abbreviated below as map_entry and | |
0154 map_elt). The total number of map_entrys in the hist_data.map array = | |
0155 map->max_elts (actually map->map_size but only max_elts of those are | |
0156 used. This is a property required by the map_insert() algorithm). | |
0157
0158 If a map_entry is unused, meaning no key has yet hashed into it, its | |
0159 .key value is 0 and its .val pointer is NULL. Once a map_entry has | |
0160 been claimed, the .key value contains the key's hash value and the | |
0161 .val member points to a map_elt containing the full key and an entry | |
0162 for each key or value in the map_elt.fields[] array. There is an | |
0163 entry in the map_elt.fields[] array corresponding to each hist_field | |
0164 in the histogram, and this is where the continually aggregated sums | |
0165 corresponding to each histogram value are kept. | |
0166
0167 The diagram attempts to show the relationship between the | |
0168 hist_data.fields[] and the map_elt.fields[] with the links drawn | |
0169 between diagrams::
0170
0171 +-----------+ | |
0172 | hist_data | | |
0173 +-----------+ | |
0174 | .fields | | |
0175 +---------+ +-----------+ | |
0176 | .map |---->| map_entry | | |
0177 +---------+ +-----------+ | |
0178 | .key |---> 0 | |
0179 +---------+ | |
0180 | .val |---> NULL | |
0181 +-----------+ | |
0182 | map_entry | | |
0183 +-----------+ | |
0184 | .key |---> pid = 999 | |
0185 +---------+ +-----------+ | |
0186 | .val |--->| map_elt | | |
0187 +---------+ +-----------+ | |
0188 . | .key |---> full key * | |
0189 . +---------+ +---------------+ | |
0190 . | .fields |--->| .sum (val) |<-+ |
0191 +-----------+ +---------+ | 2345 | | |
0192 | map_entry | +---------------+ | |
0193 +-----------+ | .offset (key) |<----+
0194 | .key |---> 0 | 0 | | |
0195 +---------+ +---------------+ | |
0196 | .val |---> NULL . | |
0197 +-----------+ . | |
0198 | map_entry | . | |
0199 +-----------+ +---------------+ | |
0200 | .key | | .sum (val) or | | |
0201 +---------+ +---------+ | .offset (key) | | |
0202 | .val |--->| map_elt | +---------------+ | |
0203 +-----------+ +---------+ | .sum (val) or | | |
0204 | map_entry | | .offset (key) | | |
0205 +-----------+ +---------------+ | |
0206 | .key |---> pid = 4444 | |
0207 +---------+ +-----------+ | |
0208 | .val | | map_elt | | |
0209 +---------+ +-----------+ | |
0210 | .key |---> full key * | |
0211 +---------+ +---------------+ | |
0212 | .fields |--->| .sum (val) |<-+ |
0213 +---------+ | 65523 | |
0214 +---------------+ |
0215 | .offset (key) |<----+
0216 | 0 |
0217 +---------------+
0218 .
0219 .
0220 .
0221 +---------------+
0222 | .sum (val) or |
0223 | .offset (key) |
0224 +---------------+
0225 | .sum (val) or |
0226 | .offset (key) |
0227 +---------------+
0228
0229 Abbreviations used in the diagrams::
0230
0231 hist_data = struct hist_trigger_data
0232 hist_data.fields = struct hist_field
0233 fn = hist_field_fn_t
0234 map_entry = struct tracing_map_entry
0235 map_elt = struct tracing_map_elt
0236 map_elt.fields = struct tracing_map_field
0237
0238 Whenever a new event occurs and it has a hist trigger associated with
0239 it, event_hist_trigger() is called. event_hist_trigger() first deals
0240 with the key: for each subkey in the key (in the above example, there
0241 is just one subkey corresponding to pid), the hist_field that
0242 represents that subkey is retrieved from hist_data.fields[] and the
0243 hist_field_fn_t fn() associated with that field, along with the
0244 field's size and offset, is used to grab that subkey's data from the
0245 current trace record.
0246
0247 Once the complete key has been retrieved, it's used to look that key
0248 up in the tracing_map. If there's no tracing_map_elt associated with
0249 that key, an empty one is claimed and inserted in the map for the new
0250 key. In either case, the tracing_map_elt associated with that key is
0251 returned.
0252
0253 Once a tracing_map_elt available, hist_trigger_elt_update() is called.
0254 As the name implies, this updates the element, which basically means
0255 updating the element's fields. There's a tracing_map_field associated
0256 with each key and value in the histogram, and each of these correspond
0257 to the key and value hist_fields created when the histogram was
0258 created. hist_trigger_elt_update() goes through each value hist_field
0259 and, as for the keys, uses the hist_field's fn() and size and offset
0260 to grab the field's value from the current trace record. Once it has
0261 that value, it simply adds that value to that field's
0262 continually-updated tracing_map_field.sum member. Some hist_field
0263 fn()s, such as for the hitcount, don't actually grab anything from the
0264 trace record (the hitcount fn() just increments the counter sum by 1),
0265 but the idea is the same.
0266
0267 Once all the values have been updated, hist_trigger_elt_update() is
0268 done and returns. Note that there are also tracing_map_fields for
0269 each subkey in the key, but hist_trigger_elt_update() doesn't look at
0270 them or update anything - those exist only for sorting, which can
0271 happen later.
0272
0273 Basic histogram test
0274 --------------------
0275
0276 This is a good example to try. It produces 3 value fields and 2 key
0277 fields in the output::
0278
0279 # echo 'hist:keys=common_pid,call_site.sym:values=bytes_req,bytes_alloc,hitcount' >> events/kmem/kmalloc/trigger
0280
0281 To see the debug data, cat the kmem/kmalloc's 'hist_debug' file. It
0282 will show the trigger info of the histogram it corresponds to, along
0283 with the address of the hist_data associated with the histogram, which
0284 will become useful in later examples. It then displays the number of
0285 total hist_fields associated with the histogram along with a count of
0286 how many of those correspond to keys and how many correspond to values.
0287
0288 It then goes on to display details for each field, including the
0289 field's flags and the position of each field in the hist_data's
0290 fields[] array, which is useful information for verifying that things
0291 internally appear correct or not, and which again will become even
0292 more useful in further examples::
0293
0294 # cat events/kmem/kmalloc/hist_debug
0295
0296 # event histogram
0297 #
0298 # trigger info: hist:keys=common_pid,call_site.sym:vals=hitcount,bytes_req,bytes_alloc:sort=hitcount:size=2048 [active]
0299 #
0300
0301 hist_data: 000000005e48c9a5
0302
0303 n_vals: 3
0304 n_keys: 2
0305 n_fields: 5
0306
0307 val fields:
0308
0309 hist_data->fields[0]:
0310 flags:
0311 VAL: HIST_FIELD_FL_HITCOUNT
0312 type: u64
0313 size: 8
0314 is_signed: 0
0315
0316 hist_data->fields[1]:
0317 flags:
0318 VAL: normal u64 value
0319 ftrace_event_field name: bytes_req
0320 type: size_t
0321 size: 8
0322 is_signed: 0
0323
0324 hist_data->fields[2]:
0325 flags:
0326 VAL: normal u64 value
0327 ftrace_event_field name: bytes_alloc
0328 type: size_t
0329 size: 8
0330 is_signed: 0
0331
0332 key fields:
0333
0334 hist_data->fields[3]:
0335 flags:
0336 HIST_FIELD_FL_KEY
0337 ftrace_event_field name: common_pid
0338 type: int
0339 size: 8
0340 is_signed: 1
0341
0342 hist_data->fields[4]:
0343 flags:
0344 HIST_FIELD_FL_KEY
0345 ftrace_event_field name: call_site
0346 type: unsigned long
0347 size: 8
0348 is_signed: 0
0349
0350 The commands below can be used to clean things up for the next test::
0351
0352 # echo '!hist:keys=common_pid,call_site.sym:values=bytes_req,bytes_alloc,hitcount' >> events/kmem/kmalloc/trigger
0353
0354 Variables
0355 =========
0356
0357 Variables allow data from one hist trigger to be saved by one hist
0358 trigger and retrieved by another hist trigger. For example, a trigger
0359 on the sched_waking event can capture a timestamp for a particular
0360 pid, and later a sched_switch event that switches to that pid event
0361 can grab the timestamp and use it to calculate a time delta between
0362 the two events::
0363
0364 # echo 'hist:keys=pid:ts0=common_timestamp.usecs' >>
0365 events/sched/sched_waking/trigger
0366
0367 # echo 'hist:keys=next_pid:wakeup_lat=common_timestamp.usecs-$ts0' >>
0368 events/sched/sched_switch/trigger
0369
0370 In terms of the histogram data structures, variables are implemented
0371 as another type of hist_field and for a given hist trigger are added
0372 to the hist_data.fields[] array just after all the val fields. To
0373 distinguish them from the existing key and val fields, they're given a
0374 new flag type, HIST_FIELD_FL_VAR (abbreviated FL_VAR) and they also
0375 make use of a new .var.idx field member in struct hist_field, which
0376 maps them to an index in a new map_elt.vars[] array added to the
0377 map_elt specifically designed to store and retrieve variable values.
0378 The diagram below shows those new elements and adds a new variable
0379 entry, ts0, corresponding to the ts0 variable in the sched_waking
0380 trigger above.
0381
0382 sched_waking histogram
0383 ----------------------::
0384
0385 +------------------+
0386 | hist_data |<-------------------------------------------------------+
0387 +------------------+ +-------------------+ |
0388 | .fields[] |-->| val = hitcount | |
0389 +----------------+ +-------------------+ |
0390 | .map | | .size | |
0391 +----------------+ +-----------------+ |
0392 | .offset | |
0393 +-----------------+ |
0394 | .fn() | |
0395 +-----------------+ |
0396 | .flags | |
0397 +-----------------+ |
0398 | .var.idx | |
0399 +-------------------+ |
0400 | var = ts0 | |
0401 +-------------------+ |
0402 | .size | |
0403 +-----------------+ |
0404 | .offset | |
0405 +-----------------+ |
0406 | .fn() | |
0407 +-----------------+ |
0408 | .flags & FL_VAR | |
0409 +-----------------+ |
0410 | .var.idx |----------------------------+-+ |
0411 +-----------------+ | | |
0412 . | | |
0413 . | | |
0414 . | | |
0415 +-------------------+ <--- n_vals | | |
0416 | key = pid | | | |
0417 +-------------------+ | | |
0418 | .size | | | |
0419 +-----------------+ | | |
0420 | .offset | | | |
0421 +-----------------+ | | |
0422 | .fn() | | | |
0423 +-----------------+ | | |
0424 | .flags & FL_KEY | | | |
0425 +-----------------+ | | |
0426 | .var.idx | | | |
0427 +-------------------+ <--- n_fields | | |
0428 | unused | | | |
0429 +-------------------+ | | |
0430 | | | | |
0431 +-----------------+ | | |
0432 | | | | |
0433 +-----------------+ | | |
0434 | | | | |
0435 +-----------------+ | | |
0436 | | | | |
0437 +-----------------+ | | |
0438 | | | | |
0439 +-----------------+ | | |
0440 n_keys = n_fields - n_vals | | |
0441 | | |
0442
0443 This is very similar to the basic case. In the above diagram, we can | | |
0444 see a new .flags member has been added to the struct hist_field | | |
0445 struct, and a new entry added to hist_data.fields representing the ts0 | | |
0446 variable. For a normal val hist_field, .flags is just 0 (modulo | | |
0447 modifier flags), but if the value is defined as a variable, the .flags | | |
0448 contains a set FL_VAR bit. | | |
0449
0450 As you can see, the ts0 entry's .var.idx member contains the index | | |
0451 into the tracing_map_elts' .vars[] array containing variable values. | | |
0452 This idx is used whenever the value of the variable is set or read. | | |
0453 The map_elt.vars idx assigned to the given variable is assigned and | | |
0454 saved in .var.idx by create_tracing_map_fields() after it calls | | |
0455 tracing_map_add_var(). | | |
0456
0457 Below is a representation of the histogram at run-time, which | | |
0458 populates the map, along with correspondence to the above hist_data and | | |
0459 hist_field data structures. | | |
0460
0461 The diagram attempts to show the relationship between the | | |
0462 hist_data.fields[] and the map_elt.fields[] and map_elt.vars[] with | | |
0463 the links drawn between diagrams. For each of the map_elts, you can | | |
0464 see that the .fields[] members point to the .sum or .offset of a key | | |
0465 or val and the .vars[] members point to the value of a variable. The | | |
0466 arrows between the two diagrams show the linkages between those | | |
0467 tracing_map members and the field definitions in the corresponding | | |
0468 hist_data fields[] members.::
0469
0470 +-----------+ | | |
0471 | hist_data | | | |
0472 +-----------+ | | |
0473 | .fields | | | |
0474 +---------+ +-----------+ | | |
0475 | .map |---->| map_entry | | | |
0476 +---------+ +-----------+ | | |
0477 | .key |---> 0 | | |
0478 +---------+ | | |
0479 | .val |---> NULL | | |
0480 +-----------+ | | |
0481 | map_entry | | | |
0482 +-----------+ | | |
0483 | .key |---> pid = 999 | | |
0484 +---------+ +-----------+ | | |
0485 | .val |--->| map_elt | | | |
0486 +---------+ +-----------+ | | |
0487 . | .key |---> full key * | | |
0488 . +---------+ +---------------+ | | |
0489 . | .fields |--->| .sum (val) | | | |
0490 . +---------+ | 2345 | | | |
0491 . +--| .vars | +---------------+ | | |
0492 . | +---------+ | .offset (key) | | | |
0493 . | | 0 | | | |
0494 . | +---------------+ | | |
0495 . | . | | |
0496 . | . | | |
0497 . | . | | |
0498 . | +---------------+ | | |
0499 . | | .sum (val) or | | | |
0500 . | | .offset (key) | | | |
0501 . | +---------------+ | | |
0502 . | | .sum (val) or | | | |
0503 . | | .offset (key) | | | |
0504 . | +---------------+ | | |
0505 . | | | |
0506 . +---------------->+---------------+ | | |
0507 . | ts0 |<--+ | |
0508 . | 113345679876 | | | |
0509 . +---------------+ | | |
0510 . | unused | | | |
0511 . | | | | |
0512 . +---------------+ | | |
0513 . . | | |
0514 . . | | |
0515 . . | | |
0516 . +---------------+ | | |
0517 . | unused | | | |
0518 . | | | | |
0519 . +---------------+ | | |
0520 . | unused | | | |
0521 . | | | | |
0522 . +---------------+ | | |
0523 . | | |
0524 +-----------+ | | |
0525 | map_entry | | | |
0526 +-----------+ | | |
0527 | .key |---> pid = 4444 | | |
0528 +---------+ +-----------+ | | |
0529 | .val |--->| map_elt | | | |
0530 +---------+ +-----------+ | | |
0531 . | .key |---> full key * | | |
0532 . +---------+ +---------------+ | | |
0533 . | .fields |--->| .sum (val) | | | |
0534 +---------+ | 2345 | | | |
0535 +--| .vars | +---------------+ | | |
0536 | +---------+ | .offset (key) | | | |
0537 | | 0 | | | |
0538 | +---------------+ | | |
0539 | . | | |
0540 | . | | |
0541 | . | | |
0542 | +---------------+ | | |
0543 | | .sum (val) or | | | |
0544 | | .offset (key) | | | |
0545 | +---------------+ | | |
0546 | | .sum (val) or | | | |
0547 | | .offset (key) | | | |
0548 | +---------------+ | | |
0549 | | | |
0550 | +---------------+ | | |
0551 +---------------->| ts0 |<--+ | |
0552 | 213499240729 | | |
0553 +---------------+ | |
0554 | unused | | |
0555 | | | |
0556 +---------------+ | |
0557 . | |
0558 . | |
0559 . | |
0560 +---------------+ | |
0561 | unused | | |
0562 | | | |
0563 +---------------+ | |
0564 | unused | | |
0565 | | | |
0566 +---------------+ | |
0567
0568 For each used map entry, there's a map_elt pointing to an array of | |
0569 .vars containing the current value of the variables associated with | |
0570 that histogram entry. So in the above, the timestamp associated with | |
0571 pid 999 is 113345679876, and the timestamp variable in the same | |
0572 .var.idx for pid 4444 is 213499240729. | |
0573
0574 sched_switch histogram | |
0575 ---------------------- | |
0576
0577 The sched_switch histogram paired with the above sched_waking | |
0578 histogram is shown below. The most important aspect of the | |
0579 sched_switch histogram is that it references a variable on the | |
0580 sched_waking histogram above. | |
0581
0582 The histogram diagram is very similar to the others so far displayed, | |
0583 but it adds variable references. You can see the normal hitcount and | |
0584 key fields along with a new wakeup_lat variable implemented in the | |
0585 same way as the sched_waking ts0 variable, but in addition there's an | |
0586 entry with the new FL_VAR_REF (short for HIST_FIELD_FL_VAR_REF) flag. | |
0587
0588 Associated with the new var ref field are a couple of new hist_field | |
0589 members, var.hist_data and var_ref_idx. For a variable reference, the | |
0590 var.hist_data goes with the var.idx, which together uniquely identify | |
0591 a particular variable on a particular histogram. The var_ref_idx is | |
0592 just the index into the var_ref_vals[] array that caches the values of | |
0593 each variable whenever a hist trigger is updated. Those resulting | |
0594 values are then finally accessed by other code such as trace action | |
0595 code that uses the var_ref_idx values to assign param values. | |
0596
0597 The diagram below describes the situation for the sched_switch | |
0598 histogram referred to before::
0599
0600 # echo 'hist:keys=next_pid:wakeup_lat=common_timestamp.usecs-$ts0' >> | |
0601 events/sched/sched_switch/trigger | |
0602 | |
0603 +------------------+ | |
0604 | hist_data | | |
0605 +------------------+ +-----------------------+ | |
0606 | .fields[] |-->| val = hitcount | | |
0607 +----------------+ +-----------------------+ | |
0608 | .map | | .size | | |
0609 +----------------+ +---------------------+ | |
0610 +--| .var_refs[] | | .offset | | |
0611 | +----------------+ +---------------------+ | |
0612 | | .fn() | | |
0613 | var_ref_vals[] +---------------------+ | |
0614 | +-------------+ | .flags | | |
0615 | | $ts0 |<---+ +---------------------+ | |
0616 | +-------------+ | | .var.idx | | |
0617 | | | | +---------------------+ | |
0618 | +-------------+ | | .var.hist_data | | |
0619 | | | | +---------------------+ | |
0620 | +-------------+ | | .var_ref_idx | | |
0621 | | | | +-----------------------+ | |
0622 | +-------------+ | | var = wakeup_lat | | |
0623 | . | +-----------------------+ | |
0624 | . | | .size | | |
0625 | . | +---------------------+ | |
0626 | +-------------+ | | .offset | | |
0627 | | | | +---------------------+ | |
0628 | +-------------+ | | .fn() | | |
0629 | | | | +---------------------+ | |
0630 | +-------------+ | | .flags & FL_VAR | | |
0631 | | +---------------------+ | |
0632 | | | .var.idx | | |
0633 | | +---------------------+ | |
0634 | | | .var.hist_data | | |
0635 | | +---------------------+ | |
0636 | | | .var_ref_idx | | |
0637 | | +---------------------+ | |
0638 | | . | |
0639 | | . | |
0640 | | . | |
0641 | | +-----------------------+ <--- n_vals | |
0642 | | | key = pid | | |
0643 | | +-----------------------+ | |
0644 | | | .size | | |
0645 | | +---------------------+ | |
0646 | | | .offset | | |
0647 | | +---------------------+ | |
0648 | | | .fn() | | |
0649 | | +---------------------+ | |
0650 | | | .flags | | |
0651 | | +---------------------+ | |
0652 | | | .var.idx | | |
0653 | | +-----------------------+ <--- n_fields | |
0654 | | | unused | | |
0655 | | +-----------------------+ | |
0656 | | | | | |
0657 | | +---------------------+ | |
0658 | | | | | |
0659 | | +---------------------+ | |
0660 | | | | | |
0661 | | +---------------------+ | |
0662 | | | | | |
0663 | | +---------------------+ | |
0664 | | | | | |
0665 | | +---------------------+ | |
0666 | | n_keys = n_fields - n_vals | |
0667 | | | |
0668 | | | |
0669 | | +-----------------------+ | |
0670 +---------------------->| var_ref = $ts0 | | |
0671 | +-----------------------+ | |
0672 | | .size | | |
0673 | +---------------------+ | |
0674 | | .offset | | |
0675 | +---------------------+ | |
0676 | | .fn() | | |
0677 | +---------------------+ | |
0678 | | .flags & FL_VAR_REF | | |
0679 | +---------------------+ | |
0680 | | .var.idx |--------------------------+ |
0681 | +---------------------+ |
0682 | | .var.hist_data |----------------------------+
0683 | +---------------------+
0684 +---| .var_ref_idx |
0685 +---------------------+
0686
0687 Abbreviations used in the diagrams::
0688
0689 hist_data = struct hist_trigger_data
0690 hist_data.fields = struct hist_field
0691 fn = hist_field_fn_t
0692 FL_KEY = HIST_FIELD_FL_KEY
0693 FL_VAR = HIST_FIELD_FL_VAR
0694 FL_VAR_REF = HIST_FIELD_FL_VAR_REF
0695
0696 When a hist trigger makes use of a variable, a new hist_field is
0697 created with flag HIST_FIELD_FL_VAR_REF. For a VAR_REF field, the
0698 var.idx and var.hist_data take the same values as the referenced
0699 variable, as well as the referenced variable's size, type, and
0700 is_signed values. The VAR_REF field's .name is set to the name of the
0701 variable it references. If a variable reference was created using the
0702 explicit system.event.$var_ref notation, the hist_field's system and
0703 event_name variables are also set.
0704
0705 So, in order to handle an event for the sched_switch histogram,
0706 because we have a reference to a variable on another histogram, we
0707 need to resolve all variable references first. This is done via the
0708 resolve_var_refs() calls made from event_hist_trigger(). What this
0709 does is grabs the var_refs[] array from the hist_data representing the
0710 sched_switch histogram. For each one of those, the referenced
0711 variable's var.hist_data along with the current key is used to look up
0712 the corresponding tracing_map_elt in that histogram. Once found, the
0713 referenced variable's var.idx is used to look up the variable's value
0714 using tracing_map_read_var(elt, var.idx), which yields the value of
0715 the variable for that element, ts0 in the case above. Note that both
0716 the hist_fields representing both the variable and the variable
0717 reference have the same var.idx, so this is straightforward.
0718
0719 Variable and variable reference test
0720 ------------------------------------
0721
0722 This example creates a variable on the sched_waking event, ts0, and
0723 uses it in the sched_switch trigger. The sched_switch trigger also
0724 creates its own variable, wakeup_lat, but nothing yet uses it::
0725
0726 # echo 'hist:keys=pid:ts0=common_timestamp.usecs' >> events/sched/sched_waking/trigger
0727
0728 # echo 'hist:keys=next_pid:wakeup_lat=common_timestamp.usecs-$ts0' >> events/sched/sched_switch/trigger
0729
0730 Looking at the sched_waking 'hist_debug' output, in addition to the
0731 normal key and value hist_fields, in the val fields section we see a
0732 field with the HIST_FIELD_FL_VAR flag, which indicates that that field
0733 represents a variable. Note that in addition to the variable name,
0734 contained in the var.name field, it includes the var.idx, which is the
0735 index into the tracing_map_elt.vars[] array of the actual variable
0736 location. Note also that the output shows that variables live in the
0737 same part of the hist_data->fields[] array as normal values::
0738
0739 # cat events/sched/sched_waking/hist_debug
0740
0741 # event histogram
0742 #
0743 # trigger info: hist:keys=pid:vals=hitcount:ts0=common_timestamp.usecs:sort=hitcount:size=2048:clock=global [active]
0744 #
0745
0746 hist_data: 000000009536f554
0747
0748 n_vals: 2
0749 n_keys: 1
0750 n_fields: 3
0751
0752 val fields:
0753
0754 hist_data->fields[0]:
0755 flags:
0756 VAL: HIST_FIELD_FL_HITCOUNT
0757 type: u64
0758 size: 8
0759 is_signed: 0
0760
0761 hist_data->fields[1]:
0762 flags:
0763 HIST_FIELD_FL_VAR
0764 var.name: ts0
0765 var.idx (into tracing_map_elt.vars[]): 0
0766 type: u64
0767 size: 8
0768 is_signed: 0
0769
0770 key fields:
0771
0772 hist_data->fields[2]:
0773 flags:
0774 HIST_FIELD_FL_KEY
0775 ftrace_event_field name: pid
0776 type: pid_t
0777 size: 8
0778 is_signed: 1
0779
0780 Moving on to the sched_switch trigger hist_debug output, in addition
0781 to the unused wakeup_lat variable, we see a new section displaying
0782 variable references. Variable references are displayed in a separate
0783 section because in addition to being logically separate from
0784 variables and values, they actually live in a separate hist_data
0785 array, var_refs[].
0786
0787 In this example, the sched_switch trigger has a reference to a
0788 variable on the sched_waking trigger, $ts0. Looking at the details,
0789 we can see that the var.hist_data value of the referenced variable
0790 matches the previously displayed sched_waking trigger, and the var.idx
0791 value matches the previously displayed var.idx value for that
0792 variable. Also displayed is the var_ref_idx value for that variable
0793 reference, which is where the value for that variable is cached for
0794 use when the trigger is invoked::
0795
0796 # cat events/sched/sched_switch/hist_debug
0797
0798 # event histogram
0799 #
0800 # trigger info: hist:keys=next_pid:vals=hitcount:wakeup_lat=common_timestamp.usecs-$ts0:sort=hitcount:size=2048:clock=global [active]
0801 #
0802
0803 hist_data: 00000000f4ee8006
0804
0805 n_vals: 2
0806 n_keys: 1
0807 n_fields: 3
0808
0809 val fields:
0810
0811 hist_data->fields[0]:
0812 flags:
0813 VAL: HIST_FIELD_FL_HITCOUNT
0814 type: u64
0815 size: 8
0816 is_signed: 0
0817
0818 hist_data->fields[1]:
0819 flags:
0820 HIST_FIELD_FL_VAR
0821 var.name: wakeup_lat
0822 var.idx (into tracing_map_elt.vars[]): 0
0823 type: u64
0824 size: 0
0825 is_signed: 0
0826
0827 key fields:
0828
0829 hist_data->fields[2]:
0830 flags:
0831 HIST_FIELD_FL_KEY
0832 ftrace_event_field name: next_pid
0833 type: pid_t
0834 size: 8
0835 is_signed: 1
0836
0837 variable reference fields:
0838
0839 hist_data->var_refs[0]:
0840 flags:
0841 HIST_FIELD_FL_VAR_REF
0842 name: ts0
0843 var.idx (into tracing_map_elt.vars[]): 0
0844 var.hist_data: 000000009536f554
0845 var_ref_idx (into hist_data->var_refs[]): 0
0846 type: u64
0847 size: 8
0848 is_signed: 0
0849
0850 The commands below can be used to clean things up for the next test::
0851
0852 # echo '!hist:keys=next_pid:wakeup_lat=common_timestamp.usecs-$ts0' >> events/sched/sched_switch/trigger
0853
0854 # echo '!hist:keys=pid:ts0=common_timestamp.usecs' >> events/sched/sched_waking/trigger
0855
0856 Actions and Handlers
0857 ====================
0858
0859 Adding onto the previous example, we will now do something with that
0860 wakeup_lat variable, namely send it and another field as a synthetic
0861 event.
0862
0863 The onmatch() action below basically says that whenever we have a
0864 sched_switch event, if we have a matching sched_waking event, in this
0865 case if we have a pid in the sched_waking histogram that matches the
0866 next_pid field on this sched_switch event, we retrieve the
0867 variables specified in the wakeup_latency() trace action, and use
0868 them to generate a new wakeup_latency event into the trace stream.
0869
0870 Note that the way the trace handlers such as wakeup_latency() (which
0871 could equivalently be written trace(wakeup_latency,$wakeup_lat,next_pid)
0872 are implemented, the parameters specified to the trace handler must be
0873 variables. In this case, $wakeup_lat is obviously a variable, but
0874 next_pid isn't, since it's just naming a field in the sched_switch
0875 trace event. Since this is something that almost every trace() and
0876 save() action does, a special shortcut is implemented to allow field
0877 names to be used directly in those cases. How it works is that under
0878 the covers, a temporary variable is created for the named field, and
0879 this variable is what is actually passed to the trace handler. In the
0880 code and documentation, this type of variable is called a 'field
0881 variable'.
0882
0883 Fields on other trace event's histograms can be used as well. In that
0884 case we have to generate a new histogram and an unfortunately named
0885 'synthetic_field' (the use of synthetic here has nothing to do with
0886 synthetic events) and use that special histogram field as a variable.
0887
0888 The diagram below illustrates the new elements described above in the
0889 context of the sched_switch histogram using the onmatch() handler and
0890 the trace() action.
0891
0892 First, we define the wakeup_latency synthetic event::
0893
0894 # echo 'wakeup_latency u64 lat; pid_t pid' >> synthetic_events
0895
0896 Next, the sched_waking hist trigger as before::
0897
0898 # echo 'hist:keys=pid:ts0=common_timestamp.usecs' >>
0899 events/sched/sched_waking/trigger
0900
0901 Finally, we create a hist trigger on the sched_switch event that
0902 generates a wakeup_latency() trace event. In this case we pass
0903 next_pid into the wakeup_latency synthetic event invocation, which
0904 means it will be automatically converted into a field variable::
0905
0906 # echo 'hist:keys=next_pid:wakeup_lat=common_timestamp.usecs-$ts0: \
0907 onmatch(sched.sched_waking).wakeup_latency($wakeup_lat,next_pid)' >>
0908 /sys/kernel/debug/tracing/events/sched/sched_switch/trigger
0909
0910 The diagram for the sched_switch event is similar to previous examples
0911 but shows the additional field_vars[] array for hist_data and shows
0912 the linkages between the field_vars and the variables and references
0913 created to implement the field variables. The details are discussed
0914 below::
0915
0916 +------------------+
0917 | hist_data |
0918 +------------------+ +-----------------------+
0919 | .fields[] |-->| val = hitcount |
0920 +----------------+ +-----------------------+
0921 | .map | | .size |
0922 +----------------+ +---------------------+
0923 +---| .field_vars[] | | .offset |
0924 | +----------------+ +---------------------+
0925 |+--| .var_refs[] | | .offset |
0926 || +----------------+ +---------------------+
0927 || | .fn() |
0928 || var_ref_vals[] +---------------------+
0929 || +-------------+ | .flags |
0930 || | $ts0 |<---+ +---------------------+
0931 || +-------------+ | | .var.idx |
0932 || | $next_pid |<-+ | +---------------------+
0933 || +-------------+ | | | .var.hist_data |
0934 ||+>| $wakeup_lat | | | +---------------------+
0935 ||| +-------------+ | | | .var_ref_idx |
0936 ||| | | | | +-----------------------+
0937 ||| +-------------+ | | | var = wakeup_lat |
0938 ||| . | | +-----------------------+
0939 ||| . | | | .size |
0940 ||| . | | +---------------------+
0941 ||| +-------------+ | | | .offset |
0942 ||| | | | | +---------------------+
0943 ||| +-------------+ | | | .fn() |
0944 ||| | | | | +---------------------+
0945 ||| +-------------+ | | | .flags & FL_VAR |
0946 ||| | | +---------------------+
0947 ||| | | | .var.idx |
0948 ||| | | +---------------------+
0949 ||| | | | .var.hist_data |
0950 ||| | | +---------------------+
0951 ||| | | | .var_ref_idx |
0952 ||| | | +---------------------+
0953 ||| | | .
0954 ||| | | .
0955 ||| | | .
0956 ||| | | .
0957 ||| +--------------+ | | .
0958 +-->| field_var | | | .
0959 || +--------------+ | | .
0960 || | var | | | .
0961 || +------------+ | | .
0962 || | val | | | .
0963 || +--------------+ | | .
0964 || | field_var | | | .
0965 || +--------------+ | | .
0966 || | var | | | .
0967 || +------------+ | | .
0968 || | val | | | .
0969 || +------------+ | | .
0970 || . | | .
0971 || . | | .
0972 || . | | +-----------------------+ <--- n_vals
0973 || +--------------+ | | | key = pid |
0974 || | field_var | | | +-----------------------+
0975 || +--------------+ | | | .size |
0976 || | var |--+| +---------------------+
0977 || +------------+ ||| | .offset |
0978 || | val |-+|| +---------------------+
0979 || +------------+ ||| | .fn() |
0980 || ||| +---------------------+
0981 || ||| | .flags |
0982 || ||| +---------------------+
0983 || ||| | .var.idx |
0984 || ||| +---------------------+ <--- n_fields
0985 || |||
0986 || ||| n_keys = n_fields - n_vals
0987 || ||| +-----------------------+
0988 || |+->| var = next_pid |
0989 || | | +-----------------------+
0990 || | | | .size |
0991 || | | +---------------------+
0992 || | | | .offset |
0993 || | | +---------------------+
0994 || | | | .flags & FL_VAR |
0995 || | | +---------------------+
0996 || | | | .var.idx |
0997 || | | +---------------------+
0998 || | | | .var.hist_data |
0999 || | | +-----------------------+
1000 || +-->| val for next_pid |
1001 || | | +-----------------------+
1002 || | | | .size |
1003 || | | +---------------------+
1004 || | | | .offset |
1005 || | | +---------------------+
1006 || | | | .fn() |
1007 || | | +---------------------+
1008 || | | | .flags |
1009 || | | +---------------------+
1010 || | | | |
1011 || | | +---------------------+
1012 || | |
1013 || | |
1014 || | | +-----------------------+
1015 +|------------------|-|>| var_ref = $ts0 |
1016 | | | +-----------------------+
1017 | | | | .size |
1018 | | | +---------------------+
1019 | | | | .offset |
1020 | | | +---------------------+
1021 | | | | .fn() |
1022 | | | +---------------------+
1023 | | | | .flags & FL_VAR_REF |
1024 | | | +---------------------+
1025 | | +---| .var_ref_idx |
1026 | | +-----------------------+
1027 | | | var_ref = $next_pid |
1028 | | +-----------------------+
1029 | | | .size |
1030 | | +---------------------+
1031 | | | .offset |
1032 | | +---------------------+
1033 | | | .fn() |
1034 | | +---------------------+
1035 | | | .flags & FL_VAR_REF |
1036 | | +---------------------+
1037 | +-----| .var_ref_idx |
1038 | +-----------------------+
1039 | | var_ref = $wakeup_lat |
1040 | +-----------------------+
1041 | | .size |
1042 | +---------------------+
1043 | | .offset |
1044 | +---------------------+
1045 | | .fn() |
1046 | +---------------------+
1047 | | .flags & FL_VAR_REF |
1048 | +---------------------+
1049 +------------------------| .var_ref_idx |
1050 +---------------------+
1051
1052 As you can see, for a field variable, two hist_fields are created: one
1053 representing the variable, in this case next_pid, and one to actually
1054 get the value of the field from the trace stream, like a normal val
1055 field does. These are created separately from normal variable
1056 creation and are saved in the hist_data->field_vars[] array. See
1057 below for how these are used. In addition, a reference hist_field is
1058 also created, which is needed to reference the field variables such as
1059 $next_pid variable in the trace() action.
1060
1061 Note that $wakeup_lat is also a variable reference, referencing the
1062 value of the expression common_timestamp-$ts0, and so also needs to
1063 have a hist field entry representing that reference created.
1064
1065 When hist_trigger_elt_update() is called to get the normal key and
1066 value fields, it also calls update_field_vars(), which goes through
1067 each field_var created for the histogram, and available from
1068 hist_data->field_vars and calls val->fn() to get the data from the
1069 current trace record, and then uses the var's var.idx to set the
1070 variable at the var.idx offset in the appropriate tracing_map_elt's
1071 variable at elt->vars[var.idx].
1072
1073 Once all the variables have been updated, resolve_var_refs() can be
1074 called from event_hist_trigger(), and not only can our $ts0 and
1075 $next_pid references be resolved but the $wakeup_lat reference as
1076 well. At this point, the trace() action can simply access the values
1077 assembled in the var_ref_vals[] array and generate the trace event.
1078
1079 The same process occurs for the field variables associated with the
1080 save() action.
1081
1082 Abbreviations used in the diagram::
1083
1084 hist_data = struct hist_trigger_data
1085 hist_data.fields = struct hist_field
1086 field_var = struct field_var
1087 fn = hist_field_fn_t
1088 FL_KEY = HIST_FIELD_FL_KEY
1089 FL_VAR = HIST_FIELD_FL_VAR
1090 FL_VAR_REF = HIST_FIELD_FL_VAR_REF
1091
1092 trace() action field variable test
1093 ----------------------------------
1094
1095 This example adds to the previous test example by finally making use
1096 of the wakeup_lat variable, but in addition also creates a couple of
1097 field variables that then are all passed to the wakeup_latency() trace
1098 action via the onmatch() handler.
1099
1100 First, we create the wakeup_latency synthetic event::
1101
1102 # echo 'wakeup_latency u64 lat; pid_t pid; char comm[16]' >> synthetic_events
1103
1104 Next, the sched_waking trigger from previous examples::
1105
1106 # echo 'hist:keys=pid:ts0=common_timestamp.usecs' >> events/sched/sched_waking/trigger
1107
1108 Finally, as in the previous test example, we calculate and assign the
1109 wakeup latency using the $ts0 reference from the sched_waking trigger
1110 to the wakeup_lat variable, and finally use it along with a couple
1111 sched_switch event fields, next_pid and next_comm, to generate a
1112 wakeup_latency trace event. The next_pid and next_comm event fields
1113 are automatically converted into field variables for this purpose::
1114
1115 # 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
1117 The sched_waking hist_debug output shows the same data as in the
1118 previous test example::
1119
1120 # cat events/sched/sched_waking/hist_debug
1121
1122 # event histogram
1123 #
1124 # trigger info: hist:keys=pid:vals=hitcount:ts0=common_timestamp.usecs:sort=hitcount:size=2048:clock=global [active]
1125 #
1126
1127 hist_data: 00000000d60ff61f
1128
1129 n_vals: 2
1130 n_keys: 1
1131 n_fields: 3
1132
1133 val fields:
1134
1135 hist_data->fields[0]:
1136 flags:
1137 VAL: HIST_FIELD_FL_HITCOUNT
1138 type: u64
1139 size: 8
1140 is_signed: 0
1141
1142 hist_data->fields[1]:
1143 flags:
1144 HIST_FIELD_FL_VAR
1145 var.name: ts0
1146 var.idx (into tracing_map_elt.vars[]): 0
1147 type: u64
1148 size: 8
1149 is_signed: 0
1150
1151 key fields:
1152
1153 hist_data->fields[2]:
1154 flags:
1155 HIST_FIELD_FL_KEY
1156 ftrace_event_field name: pid
1157 type: pid_t
1158 size: 8
1159 is_signed: 1
1160
1161 The sched_switch hist_debug output shows the same key and value fields
1162 as in the previous test example - note that wakeup_lat is still in the
1163 val fields section, but that the new field variables are not there -
1164 although the field variables are variables, they're held separately in
1165 the hist_data's field_vars[] array. Although the field variables and
1166 the normal variables are located in separate places, you can see that
1167 the actual variable locations for those variables in the
1168 tracing_map_elt.vars[] do have increasing indices as expected:
1169 wakeup_lat takes the var.idx = 0 slot, while the field variables for
1170 next_pid and next_comm have values var.idx = 1, and var.idx = 2. Note
1171 also that those are the same values displayed for the variable
1172 references corresponding to those variables in the variable reference
1173 fields section. Since there are two triggers and thus two hist_data
1174 addresses, those addresses also need to be accounted for when doing
1175 the matching - you can see that the first variable refers to the 0
1176 var.idx on the previous hist trigger (see the hist_data address
1177 associated with that trigger), while the second variable refers to the
1178 0 var.idx on the sched_switch hist trigger, as do all the remaining
1179 variable references.
1180
1181 Finally, the action tracking variables section just shows the system
1182 and event name for the onmatch() handler::
1183
1184 # cat events/sched/sched_switch/hist_debug
1185
1186 # event histogram
1187 #
1188 # 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 #
1190
1191 hist_data: 0000000008f551b7
1192
1193 n_vals: 2
1194 n_keys: 1
1195 n_fields: 3
1196
1197 val fields:
1198
1199 hist_data->fields[0]:
1200 flags:
1201 VAL: HIST_FIELD_FL_HITCOUNT
1202 type: u64
1203 size: 8
1204 is_signed: 0
1205
1206 hist_data->fields[1]:
1207 flags:
1208 HIST_FIELD_FL_VAR
1209 var.name: wakeup_lat
1210 var.idx (into tracing_map_elt.vars[]): 0
1211 type: u64
1212 size: 0
1213 is_signed: 0
1214
1215 key fields:
1216
1217 hist_data->fields[2]:
1218 flags:
1219 HIST_FIELD_FL_KEY
1220 ftrace_event_field name: next_pid
1221 type: pid_t
1222 size: 8
1223 is_signed: 1
1224
1225 variable reference fields:
1226
1227 hist_data->var_refs[0]:
1228 flags:
1229 HIST_FIELD_FL_VAR_REF
1230 name: ts0
1231 var.idx (into tracing_map_elt.vars[]): 0
1232 var.hist_data: 00000000d60ff61f
1233 var_ref_idx (into hist_data->var_refs[]): 0
1234 type: u64
1235 size: 8
1236 is_signed: 0
1237
1238 hist_data->var_refs[1]:
1239 flags:
1240 HIST_FIELD_FL_VAR_REF
1241 name: wakeup_lat
1242 var.idx (into tracing_map_elt.vars[]): 0
1243 var.hist_data: 0000000008f551b7
1244 var_ref_idx (into hist_data->var_refs[]): 1
1245 type: u64
1246 size: 0
1247 is_signed: 0
1248
1249 hist_data->var_refs[2]:
1250 flags:
1251 HIST_FIELD_FL_VAR_REF
1252 name: next_pid
1253 var.idx (into tracing_map_elt.vars[]): 1
1254 var.hist_data: 0000000008f551b7
1255 var_ref_idx (into hist_data->var_refs[]): 2
1256 type: pid_t
1257 size: 4
1258 is_signed: 0
1259
1260 hist_data->var_refs[3]:
1261 flags:
1262 HIST_FIELD_FL_VAR_REF
1263 name: next_comm
1264 var.idx (into tracing_map_elt.vars[]): 2
1265 var.hist_data: 0000000008f551b7
1266 var_ref_idx (into hist_data->var_refs[]): 3
1267 type: char[16]
1268 size: 256
1269 is_signed: 0
1270
1271 field variables:
1272
1273 hist_data->field_vars[0]:
1274
1275 field_vars[0].var:
1276 flags:
1277 HIST_FIELD_FL_VAR
1278 var.name: next_pid
1279 var.idx (into tracing_map_elt.vars[]): 1
1280
1281 field_vars[0].val:
1282 ftrace_event_field name: next_pid
1283 type: pid_t
1284 size: 4
1285 is_signed: 1
1286
1287 hist_data->field_vars[1]:
1288
1289 field_vars[1].var:
1290 flags:
1291 HIST_FIELD_FL_VAR
1292 var.name: next_comm
1293 var.idx (into tracing_map_elt.vars[]): 2
1294
1295 field_vars[1].val:
1296 ftrace_event_field name: next_comm
1297 type: char[16]
1298 size: 256
1299 is_signed: 0
1300
1301 action tracking variables (for onmax()/onchange()/onmatch()):
1302
1303 hist_data->actions[0].match_data.event_system: sched
1304 hist_data->actions[0].match_data.event: sched_waking
1305
1306 The commands below can be used to clean things up for the next test::
1307
1308 # 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
1310 # echo '!hist:keys=pid:ts0=common_timestamp.usecs' >> events/sched/sched_waking/trigger
1311
1312 # echo '!wakeup_latency u64 lat; pid_t pid; char comm[16]' >> synthetic_events
1313
1314 action_data and the trace() action
1315 ----------------------------------
1316
1317 As mentioned above, when the trace() action generates a synthetic
1318 event, all the parameters to the synthetic event either already are
1319 variables or are converted into variables (via field variables), and
1320 finally all those variable values are collected via references to them
1321 into a var_ref_vals[] array.
1322
1323 The values in the var_ref_vals[] array, however, don't necessarily
1324 follow the same ordering as the synthetic event params. To address
1325 that, struct action_data contains another array, var_ref_idx[] that
1326 maps the trace action params to the var_ref_vals[] values. Below is a
1327 diagram illustrating that for the wakeup_latency() synthetic event::
1328
1329 +------------------+ wakeup_latency()
1330 | action_data | event params var_ref_vals[]
1331 +------------------+ +-----------------+ +-----------------+
1332 | .var_ref_idx[] |--->| $wakeup_lat idx |---+ | |
1333 +----------------+ +-----------------+ | +-----------------+
1334 | .synth_event | | $next_pid idx |---|-+ | $wakeup_lat val |
1335 +----------------+ +-----------------+ | | +-----------------+
1336 . | +->| $next_pid val |
1337 . | +-----------------+
1338 . | .
1339 +-----------------+ | .
1340 | | | .
1341 +-----------------+ | +-----------------+
1342 +--->| $wakeup_lat val |
1343 +-----------------+
1344
1345 Basically, how this ends up getting used in the synthetic event probe
1346 function, trace_event_raw_event_synth(), is as follows::
1347
1348 for each field i in .synth_event
1349 val_idx = .var_ref_idx[i]
1350 val = var_ref_vals[val_idx]
1351
1352 action_data and the onXXX() handlers
1353 ------------------------------------
1354
1355 The hist trigger onXXX() actions other than onmatch(), such as onmax()
1356 and onchange(), also make use of and internally create hidden
1357 variables. This information is contained in the
1358 action_data.track_data struct, and is also visible in the hist_debug
1359 output as will be described in the example below.
1360
1361 Typically, the onmax() or onchange() handlers are used in conjunction
1362 with the save() and snapshot() actions. For example::
1363
1364 # echo 'hist:keys=next_pid:wakeup_lat=common_timestamp.usecs-$ts0: \
1365 onmax($wakeup_lat).save(next_comm,prev_pid,prev_prio,prev_comm)' >>
1366 /sys/kernel/debug/tracing/events/sched/sched_switch/trigger
1367
1368 or::
1369
1370 # echo 'hist:keys=next_pid:wakeup_lat=common_timestamp.usecs-$ts0: \
1371 onmax($wakeup_lat).snapshot()' >>
1372 /sys/kernel/debug/tracing/events/sched/sched_switch/trigger
1373
1374 save() action field variable test
1375 ---------------------------------
1376
1377 For this example, instead of generating a synthetic event, the save()
1378 action is used to save field values whenever an onmax() handler
1379 detects that a new max latency has been hit. As in the previous
1380 example, the values being saved are also field values, but in this
1381 case, are kept in a separate hist_data array named save_vars[].
1382
1383 As in previous test examples, we set up the sched_waking trigger::
1384
1385 # echo 'hist:keys=pid:ts0=common_timestamp.usecs' >> events/sched/sched_waking/trigger
1386
1387 In this case, however, we set up the sched_switch trigger to save some
1388 sched_switch field values whenever we hit a new maximum latency. For
1389 both the onmax() handler and save() action, variables will be created,
1390 which we can use the hist_debug files to examine::
1391
1392 # 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
1394 The sched_waking hist_debug output shows the same data as in the
1395 previous test examples::
1396
1397 # cat events/sched/sched_waking/hist_debug
1398
1399 #
1400 # trigger info: hist:keys=pid:vals=hitcount:ts0=common_timestamp.usecs:sort=hitcount:size=2048:clock=global [active]
1401 #
1402
1403 hist_data: 00000000e6290f48
1404
1405 n_vals: 2
1406 n_keys: 1
1407 n_fields: 3
1408
1409 val fields:
1410
1411 hist_data->fields[0]:
1412 flags:
1413 VAL: HIST_FIELD_FL_HITCOUNT
1414 type: u64
1415 size: 8
1416 is_signed: 0
1417
1418 hist_data->fields[1]:
1419 flags:
1420 HIST_FIELD_FL_VAR
1421 var.name: ts0
1422 var.idx (into tracing_map_elt.vars[]): 0
1423 type: u64
1424 size: 8
1425 is_signed: 0
1426
1427 key fields:
1428
1429 hist_data->fields[2]:
1430 flags:
1431 HIST_FIELD_FL_KEY
1432 ftrace_event_field name: pid
1433 type: pid_t
1434 size: 8
1435 is_signed: 1
1436
1437 The output of the sched_switch trigger shows the same val and key
1438 values as before, but also shows a couple new sections.
1439
1440 First, the action tracking variables section now shows the
1441 actions[].track_data information describing the special tracking
1442 variables and references used to track, in this case, the running
1443 maximum value. The actions[].track_data.var_ref member contains the
1444 reference to the variable being tracked, in this case the $wakeup_lat
1445 variable. In order to perform the onmax() handler function, there
1446 also needs to be a variable that tracks the current maximum by getting
1447 updated whenever a new maximum is hit. In this case, we can see that
1448 an auto-generated variable named ' __max' has been created and is
1449 visible in the actions[].track_data.track_var variable.
1450
1451 Finally, in the new 'save action variables' section, we can see that
1452 the 4 params to the save() function have resulted in 4 field variables
1453 being created for the purposes of saving the values of the named
1454 fields when the max is hit. These variables are kept in a separate
1455 save_vars[] array off of hist_data, so are displayed in a separate
1456 section::
1457
1458 # cat events/sched/sched_switch/hist_debug
1459
1460 # event histogram
1461 #
1462 # 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 #
1464
1465 hist_data: 0000000057bcd28d
1466
1467 n_vals: 2
1468 n_keys: 1
1469 n_fields: 3
1470
1471 val fields:
1472
1473 hist_data->fields[0]:
1474 flags:
1475 VAL: HIST_FIELD_FL_HITCOUNT
1476 type: u64
1477 size: 8
1478 is_signed: 0
1479
1480 hist_data->fields[1]:
1481 flags:
1482 HIST_FIELD_FL_VAR
1483 var.name: wakeup_lat
1484 var.idx (into tracing_map_elt.vars[]): 0
1485 type: u64
1486 size: 0
1487 is_signed: 0
1488
1489 key fields:
1490
1491 hist_data->fields[2]:
1492 flags:
1493 HIST_FIELD_FL_KEY
1494 ftrace_event_field name: next_pid
1495 type: pid_t
1496 size: 8
1497 is_signed: 1
1498
1499 variable reference fields:
1500
1501 hist_data->var_refs[0]:
1502 flags:
1503 HIST_FIELD_FL_VAR_REF
1504 name: ts0
1505 var.idx (into tracing_map_elt.vars[]): 0
1506 var.hist_data: 00000000e6290f48
1507 var_ref_idx (into hist_data->var_refs[]): 0
1508 type: u64
1509 size: 8
1510 is_signed: 0
1511
1512 hist_data->var_refs[1]:
1513 flags:
1514 HIST_FIELD_FL_VAR_REF
1515 name: wakeup_lat
1516 var.idx (into tracing_map_elt.vars[]): 0
1517 var.hist_data: 0000000057bcd28d
1518 var_ref_idx (into hist_data->var_refs[]): 1
1519 type: u64
1520 size: 0
1521 is_signed: 0
1522
1523 action tracking variables (for onmax()/onchange()/onmatch()):
1524
1525 hist_data->actions[0].track_data.var_ref:
1526 flags:
1527 HIST_FIELD_FL_VAR_REF
1528 name: wakeup_lat
1529 var.idx (into tracing_map_elt.vars[]): 0
1530 var.hist_data: 0000000057bcd28d
1531 var_ref_idx (into hist_data->var_refs[]): 1
1532 type: u64
1533 size: 0
1534 is_signed: 0
1535
1536 hist_data->actions[0].track_data.track_var:
1537 flags:
1538 HIST_FIELD_FL_VAR
1539 var.name: __max
1540 var.idx (into tracing_map_elt.vars[]): 1
1541 type: u64
1542 size: 8
1543 is_signed: 0
1544
1545 save action variables (save() params):
1546
1547 hist_data->save_vars[0]:
1548
1549 save_vars[0].var:
1550 flags:
1551 HIST_FIELD_FL_VAR
1552 var.name: next_comm
1553 var.idx (into tracing_map_elt.vars[]): 2
1554
1555 save_vars[0].val:
1556 ftrace_event_field name: next_comm
1557 type: char[16]
1558 size: 256
1559 is_signed: 0
1560
1561 hist_data->save_vars[1]:
1562
1563 save_vars[1].var:
1564 flags:
1565 HIST_FIELD_FL_VAR
1566 var.name: prev_pid
1567 var.idx (into tracing_map_elt.vars[]): 3
1568
1569 save_vars[1].val:
1570 ftrace_event_field name: prev_pid
1571 type: pid_t
1572 size: 4
1573 is_signed: 1
1574
1575 hist_data->save_vars[2]:
1576
1577 save_vars[2].var:
1578 flags:
1579 HIST_FIELD_FL_VAR
1580 var.name: prev_prio
1581 var.idx (into tracing_map_elt.vars[]): 4
1582
1583 save_vars[2].val:
1584 ftrace_event_field name: prev_prio
1585 type: int
1586 size: 4
1587 is_signed: 1
1588
1589 hist_data->save_vars[3]:
1590
1591 save_vars[3].var:
1592 flags:
1593 HIST_FIELD_FL_VAR
1594 var.name: prev_comm
1595 var.idx (into tracing_map_elt.vars[]): 5
1596
1597 save_vars[3].val:
1598 ftrace_event_field name: prev_comm
1599 type: char[16]
1600 size: 256
1601 is_signed: 0
1602
1603 The commands below can be used to clean things up for the next test::
1604
1605 # 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
1607 # echo '!hist:keys=pid:ts0=common_timestamp.usecs' >> events/sched/sched_waking/trigger
1608
1609 A couple special cases
1610 ======================
1611
1612 While the above covers the basics of the histogram internals, there
1613 are a couple of special cases that should be discussed, since they
1614 tend to create even more confusion. Those are field variables on other
1615 histograms, and aliases, both described below through example tests
1616 using the hist_debug files.
1617
1618 Test of field variables on other histograms
1619 -------------------------------------------
1620
1621 This example is similar to the previous examples, but in this case,
1622 the sched_switch trigger references a hist trigger field on another
1623 event, namely the sched_waking event. In order to accomplish this, a
1624 field variable is created for the other event, but since an existing
1625 histogram can't be used, as existing histograms are immutable, a new
1626 histogram with a matching variable is created and used, and we'll see
1627 that reflected in the hist_debug output shown below.
1628
1629 First, we create the wakeup_latency synthetic event. Note the
1630 addition of the prio field::
1631
1632 # echo 'wakeup_latency u64 lat; pid_t pid; int prio' >> synthetic_events
1633
1634 As in previous test examples, we set up the sched_waking trigger::
1635
1636 # echo 'hist:keys=pid:ts0=common_timestamp.usecs' >> events/sched/sched_waking/trigger
1637
1638 Here we set up a hist trigger on sched_switch to send a wakeup_latency
1639 event using an onmatch handler naming the sched_waking event. Note
1640 that the third param being passed to the wakeup_latency() is prio,
1641 which is a field name that needs to have a field variable created for
1642 it. There isn't however any prio field on the sched_switch event so
1643 it would seem that it wouldn't be possible to create a field variable
1644 for it. The matching sched_waking event does have a prio field, so it
1645 should be possible to make use of it for this purpose. The problem
1646 with that is that it's not currently possible to define a new variable
1647 on an existing histogram, so it's not possible to add a new prio field
1648 variable to the existing sched_waking histogram. It is however
1649 possible to create an additional new 'matching' sched_waking histogram
1650 for the same event, meaning that it uses the same key and filters, and
1651 define the new prio field variable on that.
1652
1653 Here's the sched_switch trigger::
1654
1655 # 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
1657 And here's the output of the hist_debug information for the
1658 sched_waking hist trigger. Note that there are two histograms
1659 displayed in the output: the first is the normal sched_waking
1660 histogram we've seen in the previous examples, and the second is the
1661 special histogram we created to provide the prio field variable.
1662
1663 Looking at the second histogram below, we see a variable with the name
1664 synthetic_prio. This is the field variable created for the prio field
1665 on that sched_waking histogram::
1666
1667 # cat events/sched/sched_waking/hist_debug
1668
1669 # event histogram
1670 #
1671 # trigger info: hist:keys=pid:vals=hitcount:ts0=common_timestamp.usecs:sort=hitcount:size=2048:clock=global [active]
1672 #
1673
1674 hist_data: 00000000349570e4
1675
1676 n_vals: 2
1677 n_keys: 1
1678 n_fields: 3
1679
1680 val fields:
1681
1682 hist_data->fields[0]:
1683 flags:
1684 VAL: HIST_FIELD_FL_HITCOUNT
1685 type: u64
1686 size: 8
1687 is_signed: 0
1688
1689 hist_data->fields[1]:
1690 flags:
1691 HIST_FIELD_FL_VAR
1692 var.name: ts0
1693 var.idx (into tracing_map_elt.vars[]): 0
1694 type: u64
1695 size: 8
1696 is_signed: 0
1697
1698 key fields:
1699
1700 hist_data->fields[2]:
1701 flags:
1702 HIST_FIELD_FL_KEY
1703 ftrace_event_field name: pid
1704 type: pid_t
1705 size: 8
1706 is_signed: 1
1707
1708
1709 # event histogram
1710 #
1711 # trigger info: hist:keys=pid:vals=hitcount:synthetic_prio=prio:sort=hitcount:size=2048 [active]
1712 #
1713
1714 hist_data: 000000006920cf38
1715
1716 n_vals: 2
1717 n_keys: 1
1718 n_fields: 3
1719
1720 val fields:
1721
1722 hist_data->fields[0]:
1723 flags:
1724 VAL: HIST_FIELD_FL_HITCOUNT
1725 type: u64
1726 size: 8
1727 is_signed: 0
1728
1729 hist_data->fields[1]:
1730 flags:
1731 HIST_FIELD_FL_VAR
1732 ftrace_event_field name: prio
1733 var.name: synthetic_prio
1734 var.idx (into tracing_map_elt.vars[]): 0
1735 type: int
1736 size: 4
1737 is_signed: 1
1738
1739 key fields:
1740
1741 hist_data->fields[2]:
1742 flags:
1743 HIST_FIELD_FL_KEY
1744 ftrace_event_field name: pid
1745 type: pid_t
1746 size: 8
1747 is_signed: 1
1748
1749 Looking at the sched_switch histogram below, we can see a reference to
1750 the synthetic_prio variable on sched_waking, and looking at the
1751 associated hist_data address we see that it is indeed associated with
1752 the new histogram. Note also that the other references are to a
1753 normal variable, wakeup_lat, and to a normal field variable, next_pid,
1754 the details of which are in the field variables section::
1755
1756 # cat events/sched/sched_switch/hist_debug
1757
1758 # event histogram
1759 #
1760 # 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 #
1762
1763 hist_data: 00000000a73b67df
1764
1765 n_vals: 2
1766 n_keys: 1
1767 n_fields: 3
1768
1769 val fields:
1770
1771 hist_data->fields[0]:
1772 flags:
1773 VAL: HIST_FIELD_FL_HITCOUNT
1774 type: u64
1775 size: 8
1776 is_signed: 0
1777
1778 hist_data->fields[1]:
1779 flags:
1780 HIST_FIELD_FL_VAR
1781 var.name: wakeup_lat
1782 var.idx (into tracing_map_elt.vars[]): 0
1783 type: u64
1784 size: 0
1785 is_signed: 0
1786
1787 key fields:
1788
1789 hist_data->fields[2]:
1790 flags:
1791 HIST_FIELD_FL_KEY
1792 ftrace_event_field name: next_pid
1793 type: pid_t
1794 size: 8
1795 is_signed: 1
1796
1797 variable reference fields:
1798
1799 hist_data->var_refs[0]:
1800 flags:
1801 HIST_FIELD_FL_VAR_REF
1802 name: ts0
1803 var.idx (into tracing_map_elt.vars[]): 0
1804 var.hist_data: 00000000349570e4
1805 var_ref_idx (into hist_data->var_refs[]): 0
1806 type: u64
1807 size: 8
1808 is_signed: 0
1809
1810 hist_data->var_refs[1]:
1811 flags:
1812 HIST_FIELD_FL_VAR_REF
1813 name: wakeup_lat
1814 var.idx (into tracing_map_elt.vars[]): 0
1815 var.hist_data: 00000000a73b67df
1816 var_ref_idx (into hist_data->var_refs[]): 1
1817 type: u64
1818 size: 0
1819 is_signed: 0
1820
1821 hist_data->var_refs[2]:
1822 flags:
1823 HIST_FIELD_FL_VAR_REF
1824 name: next_pid
1825 var.idx (into tracing_map_elt.vars[]): 1
1826 var.hist_data: 00000000a73b67df
1827 var_ref_idx (into hist_data->var_refs[]): 2
1828 type: pid_t
1829 size: 4
1830 is_signed: 0
1831
1832 hist_data->var_refs[3]:
1833 flags:
1834 HIST_FIELD_FL_VAR_REF
1835 name: synthetic_prio
1836 var.idx (into tracing_map_elt.vars[]): 0
1837 var.hist_data: 000000006920cf38
1838 var_ref_idx (into hist_data->var_refs[]): 3
1839 type: int
1840 size: 4
1841 is_signed: 1
1842
1843 field variables:
1844
1845 hist_data->field_vars[0]:
1846
1847 field_vars[0].var:
1848 flags:
1849 HIST_FIELD_FL_VAR
1850 var.name: next_pid
1851 var.idx (into tracing_map_elt.vars[]): 1
1852
1853 field_vars[0].val:
1854 ftrace_event_field name: next_pid
1855 type: pid_t
1856 size: 4
1857 is_signed: 1
1858
1859 action tracking variables (for onmax()/onchange()/onmatch()):
1860
1861 hist_data->actions[0].match_data.event_system: sched
1862 hist_data->actions[0].match_data.event: sched_waking
1863
1864 The commands below can be used to clean things up for the next test::
1865
1866 # 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
1868 # echo '!hist:keys=pid:ts0=common_timestamp.usecs' >> events/sched/sched_waking/trigger
1869
1870 # echo '!wakeup_latency u64 lat; pid_t pid; int prio' >> synthetic_events
1871
1872 Alias test
1873 ----------
1874
1875 This example is very similar to previous examples, but demonstrates
1876 the alias flag.
1877
1878 First, we create the wakeup_latency synthetic event::
1879
1880 # echo 'wakeup_latency u64 lat; pid_t pid; char comm[16]' >> synthetic_events
1881
1882 Next, we create a sched_waking trigger similar to previous examples,
1883 but in this case we save the pid in the waking_pid variable::
1884
1885 # echo 'hist:keys=pid:waking_pid=pid:ts0=common_timestamp.usecs' >> events/sched/sched_waking/trigger
1886
1887 For the sched_switch trigger, instead of using $waking_pid directly in
1888 the wakeup_latency synthetic event invocation, we create an alias of
1889 $waking_pid named $woken_pid, and use that in the synthetic event
1890 invocation instead::
1891
1892 # 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
1894 Looking at the sched_waking hist_debug output, in addition to the
1895 normal fields, we can see the waking_pid variable::
1896
1897 # cat events/sched/sched_waking/hist_debug
1898
1899 # event histogram
1900 #
1901 # trigger info: hist:keys=pid:vals=hitcount:waking_pid=pid,ts0=common_timestamp.usecs:sort=hitcount:size=2048:clock=global [active]
1902 #
1903
1904 hist_data: 00000000a250528c
1905
1906 n_vals: 3
1907 n_keys: 1
1908 n_fields: 4
1909
1910 val fields:
1911
1912 hist_data->fields[0]:
1913 flags:
1914 VAL: HIST_FIELD_FL_HITCOUNT
1915 type: u64
1916 size: 8
1917 is_signed: 0
1918
1919 hist_data->fields[1]:
1920 flags:
1921 HIST_FIELD_FL_VAR
1922 ftrace_event_field name: pid
1923 var.name: waking_pid
1924 var.idx (into tracing_map_elt.vars[]): 0
1925 type: pid_t
1926 size: 4
1927 is_signed: 1
1928
1929 hist_data->fields[2]:
1930 flags:
1931 HIST_FIELD_FL_VAR
1932 var.name: ts0
1933 var.idx (into tracing_map_elt.vars[]): 1
1934 type: u64
1935 size: 8
1936 is_signed: 0
1937
1938 key fields:
1939
1940 hist_data->fields[3]:
1941 flags:
1942 HIST_FIELD_FL_KEY
1943 ftrace_event_field name: pid
1944 type: pid_t
1945 size: 8
1946 is_signed: 1
1947
1948 The sched_switch hist_debug output shows that a variable named
1949 woken_pid has been created but that it also has the
1950 HIST_FIELD_FL_ALIAS flag set. It also has the HIST_FIELD_FL_VAR flag
1951 set, which is why it appears in the val field section.
1952
1953 Despite that implementation detail, an alias variable is actually more
1954 like a variable reference; in fact it can be thought of as a reference
1955 to a reference. The implementation copies the var_ref->fn() from the
1956 variable reference being referenced, in this case, the waking_pid
1957 fn(), which is hist_field_var_ref() and makes that the fn() of the
1958 alias. The hist_field_var_ref() fn() requires the var_ref_idx of the
1959 variable reference it's using, so waking_pid's var_ref_idx is also
1960 copied to the alias. The end result is that when the value of alias
1961 is retrieved, in the end it just does the same thing the original
1962 reference would have done and retrieves the same value from the
1963 var_ref_vals[] array. You can verify this in the output by noting
1964 that the var_ref_idx of the alias, in this case woken_pid, is the same
1965 as the var_ref_idx of the reference, waking_pid, in the variable
1966 reference fields section.
1967
1968 Additionally, once it gets that value, since it is also a variable, it
1969 then saves that value into its var.idx. So the var.idx of the
1970 woken_pid alias is 0, which it fills with the value from var_ref_idx 0
1971 when its fn() is called to update itself. You'll also notice that
1972 there's a woken_pid var_ref in the variable refs section. That is the
1973 reference to the woken_pid alias variable, and you can see that it
1974 retrieves the value from the same var.idx as the woken_pid alias, 0,
1975 and then in turn saves that value in its own var_ref_idx slot, 3, and
1976 the value at this position is finally what gets assigned to the
1977 $woken_pid slot in the trace event invocation::
1978
1979 # cat events/sched/sched_switch/hist_debug
1980
1981 # event histogram
1982 #
1983 # 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 #
1985
1986 hist_data: 0000000055d65ed0
1987
1988 n_vals: 3
1989 n_keys: 1
1990 n_fields: 4
1991
1992 val fields:
1993
1994 hist_data->fields[0]:
1995 flags:
1996 VAL: HIST_FIELD_FL_HITCOUNT
1997 type: u64
1998 size: 8
1999 is_signed: 0
2000
2001 hist_data->fields[1]:
2002 flags:
2003 HIST_FIELD_FL_VAR
2004 HIST_FIELD_FL_ALIAS
2005 var.name: woken_pid
2006 var.idx (into tracing_map_elt.vars[]): 0
2007 var_ref_idx (into hist_data->var_refs[]): 0
2008 type: pid_t
2009 size: 4
2010 is_signed: 1
2011
2012 hist_data->fields[2]:
2013 flags:
2014 HIST_FIELD_FL_VAR
2015 var.name: wakeup_lat
2016 var.idx (into tracing_map_elt.vars[]): 1
2017 type: u64
2018 size: 0
2019 is_signed: 0
2020
2021 key fields:
2022
2023 hist_data->fields[3]:
2024 flags:
2025 HIST_FIELD_FL_KEY
2026 ftrace_event_field name: next_pid
2027 type: pid_t
2028 size: 8
2029 is_signed: 1
2030
2031 variable reference fields:
2032
2033 hist_data->var_refs[0]:
2034 flags:
2035 HIST_FIELD_FL_VAR_REF
2036 name: waking_pid
2037 var.idx (into tracing_map_elt.vars[]): 0
2038 var.hist_data: 00000000a250528c
2039 var_ref_idx (into hist_data->var_refs[]): 0
2040 type: pid_t
2041 size: 4
2042 is_signed: 1
2043
2044 hist_data->var_refs[1]:
2045 flags:
2046 HIST_FIELD_FL_VAR_REF
2047 name: ts0
2048 var.idx (into tracing_map_elt.vars[]): 1
2049 var.hist_data: 00000000a250528c
2050 var_ref_idx (into hist_data->var_refs[]): 1
2051 type: u64
2052 size: 8
2053 is_signed: 0
2054
2055 hist_data->var_refs[2]:
2056 flags:
2057 HIST_FIELD_FL_VAR_REF
2058 name: wakeup_lat
2059 var.idx (into tracing_map_elt.vars[]): 1
2060 var.hist_data: 0000000055d65ed0
2061 var_ref_idx (into hist_data->var_refs[]): 2
2062 type: u64
2063 size: 0
2064 is_signed: 0
2065
2066 hist_data->var_refs[3]:
2067 flags:
2068 HIST_FIELD_FL_VAR_REF
2069 name: woken_pid
2070 var.idx (into tracing_map_elt.vars[]): 0
2071 var.hist_data: 0000000055d65ed0
2072 var_ref_idx (into hist_data->var_refs[]): 3
2073 type: pid_t
2074 size: 4
2075 is_signed: 1
2076
2077 hist_data->var_refs[4]:
2078 flags:
2079 HIST_FIELD_FL_VAR_REF
2080 name: next_comm
2081 var.idx (into tracing_map_elt.vars[]): 2
2082 var.hist_data: 0000000055d65ed0
2083 var_ref_idx (into hist_data->var_refs[]): 4
2084 type: char[16]
2085 size: 256
2086 is_signed: 0
2087
2088 field variables:
2089
2090 hist_data->field_vars[0]:
2091
2092 field_vars[0].var:
2093 flags:
2094 HIST_FIELD_FL_VAR
2095 var.name: next_comm
2096 var.idx (into tracing_map_elt.vars[]): 2
2097
2098 field_vars[0].val:
2099 ftrace_event_field name: next_comm
2100 type: char[16]
2101 size: 256
2102 is_signed: 0
2103
2104 action tracking variables (for onmax()/onchange()/onmatch()):
2105
2106 hist_data->actions[0].match_data.event_system: sched
2107 hist_data->actions[0].match_data.event: sched_waking
2108
2109 The commands below can be used to clean things up for the next test::
2110
2111 # 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
2113 # echo '!hist:keys=pid:ts0=common_timestamp.usecs' >> events/sched/sched_waking/trigger
2114
2115 # echo '!wakeup_latency u64 lat; pid_t pid; char comm[16]' >> synthetic_events