1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
|
.. SPDX-License-Identifier: GPL-2.0
================
Perf ring buffer
================
.. CONTENTS
1. Introduction
2. Ring buffer implementation
2.1 Basic algorithm
2.2 Ring buffer for different tracing modes
2.2.1 Default mode
2.2.2 Per-thread mode
2.2.3 Per-CPU mode
2.2.4 System wide mode
2.3 Accessing buffer
2.3.1 Producer-consumer model
2.3.2 Properties of the ring buffers
2.3.3 Writing samples into buffer
2.3.4 Reading samples from buffer
2.3.5 Memory synchronization
3. The mechanism of AUX ring buffer
3.1 The relationship between AUX and regular ring buffers
3.2 AUX events
3.3 Snapshot mode
1. Introduction
===============
The ring buffer is a fundamental mechanism for data transfer. perf uses
ring buffers to transfer event data from kernel to user space, another
kind of ring buffer which is so called auxiliary (AUX) ring buffer also
plays an important role for hardware tracing with Intel PT, Arm
CoreSight, etc.
The ring buffer implementation is critical but it's also a very
challenging work. On the one hand, the kernel and perf tool in the user
space use the ring buffer to exchange data and stores data into data
file, thus the ring buffer needs to transfer data with high throughput;
on the other hand, the ring buffer management should avoid significant
overload to distract profiling results.
This documentation dives into the details for perf ring buffer with two
parts: firstly it explains the perf ring buffer implementation, then the
second part discusses the AUX ring buffer mechanism.
2. Ring buffer implementation
=============================
2.1 Basic algorithm
-------------------
That said, a typical ring buffer is managed by a head pointer and a tail
pointer; the head pointer is manipulated by a writer and the tail
pointer is updated by a reader respectively.
::
+---------------------------+
| | |***|***|***| | |
+---------------------------+
`-> Tail `-> Head
* : the data is filled by the writer.
Figure 1. Ring buffer
Perf uses the same way to manage its ring buffer. In the implementation
there are two key data structures held together in a set of consecutive
pages, the control structure and then the ring buffer itself. The page
with the control structure in is known as the "user page". Being held
in continuous virtual addresses simplifies locating the ring buffer
address, it is in the pages after the page with the user page.
The control structure is named as ``perf_event_mmap_page``, it contains a
head pointer ``data_head`` and a tail pointer ``data_tail``. When the
kernel starts to fill records into the ring buffer, it updates the head
pointer to reserve the memory so later it can safely store events into
the buffer. On the other side, when the user page is a writable mapping,
the perf tool has the permission to update the tail pointer after consuming
data from the ring buffer. Yet another case is for the user page's
read-only mapping, which is to be addressed in the section
:ref:`writing_samples_into_buffer`.
::
user page ring buffer
+---------+---------+ +---------------------------------------+
|data_head|data_tail|...| | |***|***|***|***|***| | | |
+---------+---------+ +---------------------------------------+
` `----------------^ ^
`----------------------------------------------|
* : the data is filled by the writer.
Figure 2. Perf ring buffer
When using the ``perf record`` tool, we can specify the ring buffer size
with option ``-m`` or ``--mmap-pages=``, the given size will be rounded up
to a power of two that is a multiple of a page size. Though the kernel
allocates at once for all memory pages, it's deferred to map the pages
to VMA area until the perf tool accesses the buffer from the user space.
In other words, at the first time accesses the buffer's page from user
space in the perf tool, a data abort exception for page fault is taken
and the kernel uses this occasion to map the page into process VMA
(see ``perf_mmap_fault()``), thus the perf tool can continue to access
the page after returning from the exception.
2.2 Ring buffer for different tracing modes
-------------------------------------------
The perf profiles programs with different modes: default mode, per thread
mode, per cpu mode, and system wide mode. This section describes these
modes and how the ring buffer meets requirements for them. At last we
will review the race conditions caused by these modes.
2.2.1 Default mode
^^^^^^^^^^^^^^^^^^
Usually we execute ``perf record`` command followed by a profiling program
name, like below command::
perf record test_program
This command doesn't specify any options for CPU and thread modes, the
perf tool applies the default mode on the perf event. It maps all the
CPUs in the system and the profiled program's PID on the perf event, and
it enables inheritance mode on the event so that child tasks inherits
the events. As a result, the perf event is attributed as::
evsel::cpus::map[] = { 0 .. _SC_NPROCESSORS_ONLN-1 }
evsel::threads::map[] = { pid }
evsel::attr::inherit = 1
These attributions finally will be reflected on the deployment of ring
buffers. As shown below, the perf tool allocates individual ring buffer
for each CPU, but it only enables events for the profiled program rather
than for all threads in the system. The *T1* thread represents the
thread context of the 'test_program', whereas *T2* and *T3* are irrelevant
threads in the system. The perf samples are exclusively collected for
the *T1* thread and stored in the ring buffer associated with the CPU on
which the *T1* thread is running.
::
T1 T2 T1
+----+ +-----------+ +----+
CPU0 |xxxx| |xxxxxxxxxxx| |xxxx|
+----+--------------+-----------+----------+----+-------->
| |
v v
+-----------------------------------------------------+
| Ring buffer 0 |
+-----------------------------------------------------+
T1
+-----+
CPU1 |xxxxx|
-----+-----+--------------------------------------------->
|
v
+-----------------------------------------------------+
| Ring buffer 1 |
+-----------------------------------------------------+
T1 T3
+----+ +-------+
CPU2 |xxxx| |xxxxxxx|
--------------------------+----+--------+-------+-------->
|
v
+-----------------------------------------------------+
| Ring buffer 2 |
+-----------------------------------------------------+
T1
+--------------+
CPU3 |xxxxxxxxxxxxxx|
-----------+--------------+------------------------------>
|
v
+-----------------------------------------------------+
| Ring buffer 3 |
+-----------------------------------------------------+
T1: Thread 1; T2: Thread 2; T3: Thread 3
x: Thread is in running state
Figure 3. Ring buffer for default mode
2.2.2 Per-thread mode
^^^^^^^^^^^^^^^^^^^^^
By specifying option ``--per-thread`` in perf command, e.g.
::
perf record --per-thread test_program
The perf event doesn't map to any CPUs and is only bound to the
profiled process, thus, the perf event's attributions are::
evsel::cpus::map[0] = { -1 }
evsel::threads::map[] = { pid }
evsel::attr::inherit = 0
In this mode, a single ring buffer is allocated for the profiled thread;
if the thread is scheduled on a CPU, the events on that CPU will be
enabled; and if the thread is scheduled out from the CPU, the events on
the CPU will be disabled. When the thread is migrated from one CPU to
another, the events are to be disabled on the previous CPU and enabled
on the next CPU correspondingly.
::
T1 T2 T1
+----+ +-----------+ +----+
CPU0 |xxxx| |xxxxxxxxxxx| |xxxx|
+----+--------------+-----------+----------+----+-------->
| |
| T1 |
| +-----+ |
CPU1 | |xxxxx| |
--|--+-----+----------------------------------|---------->
| | |
| | T1 T3 |
| | +----+ +---+ |
CPU2 | | |xxxx| |xxx| |
--|-----|-----------------+----+--------+---+-|---------->
| | | |
| | T1 | |
| | +--------------+ | |
CPU3 | | |xxxxxxxxxxxxxx| | |
--|-----|--+--------------+-|-----------------|---------->
| | | | |
v v v v v
+-----------------------------------------------------+
| Ring buffer |
+-----------------------------------------------------+
T1: Thread 1
x: Thread is in running state
Figure 4. Ring buffer for per-thread mode
When perf runs in per-thread mode, a ring buffer is allocated for the
profiled thread *T1*. The ring buffer is dedicated for thread *T1*, if the
thread *T1* is running, the perf events will be recorded into the ring
buffer; when the thread is sleeping, all associated events will be
disabled, thus no trace data will be recorded into the ring buffer.
2.2.3 Per-CPU mode
^^^^^^^^^^^^^^^^^^
The option ``-C`` is used to collect samples on the list of CPUs, for
example the below perf command receives option ``-C 0,2``::
perf record -C 0,2 test_program
It maps the perf event to CPUs 0 and 2, and the event is not associated to any
PID. Thus the perf event attributions are set as::
evsel::cpus::map[0] = { 0, 2 }
evsel::threads::map[] = { -1 }
evsel::attr::inherit = 0
This results in the session of ``perf record`` will sample all threads on CPU0
and CPU2, and be terminated until test_program exits. Even there have tasks
running on CPU1 and CPU3, since the ring buffer is absent for them, any
activities on these two CPUs will be ignored. A usage case is to combine the
options for per-thread mode and per-CPU mode, e.g. the options ``–C 0,2`` and
``––per–thread`` are specified together, the samples are recorded only when
the profiled thread is scheduled on any of the listed CPUs.
::
T1 T2 T1
+----+ +-----------+ +----+
CPU0 |xxxx| |xxxxxxxxxxx| |xxxx|
+----+--------------+-----------+----------+----+-------->
| | |
v v v
+-----------------------------------------------------+
| Ring buffer 0 |
+-----------------------------------------------------+
T1
+-----+
CPU1 |xxxxx|
-----+-----+--------------------------------------------->
T1 T3
+----+ +-------+
CPU2 |xxxx| |xxxxxxx|
--------------------------+----+--------+-------+-------->
| |
v v
+-----------------------------------------------------+
| Ring buffer 1 |
+-----------------------------------------------------+
T1
+--------------+
CPU3 |xxxxxxxxxxxxxx|
-----------+--------------+------------------------------>
T1: Thread 1; T2: Thread 2; T3: Thread 3
x: Thread is in running state
Figure 5. Ring buffer for per-CPU mode
2.2.4 System wide mode
^^^^^^^^^^^^^^^^^^^^^^
By using option ``–a`` or ``––all–cpus``, perf collects samples on all CPUs
for all tasks, we call it as the system wide mode, the command is::
perf record -a test_program
Similar to the per-CPU mode, the perf event doesn't bind to any PID, and
it maps to all CPUs in the system::
evsel::cpus::map[] = { 0 .. _SC_NPROCESSORS_ONLN-1 }
evsel::threads::map[] = { -1 }
evsel::attr::inherit = 0
In the system wide mode, every CPU has its own ring buffer, all threads
are monitored during the running state and the samples are recorded into
the ring buffer belonging to the CPU which the events occurred on.
::
T1 T2 T1
+----+ +-----------+ +----+
CPU0 |xxxx| |xxxxxxxxxxx| |xxxx|
+----+--------------+-----------+----------+----+-------->
| | |
v v v
+-----------------------------------------------------+
| Ring buffer 0 |
+-----------------------------------------------------+
T1
+-----+
CPU1 |xxxxx|
-----+-----+--------------------------------------------->
|
v
+-----------------------------------------------------+
| Ring buffer 1 |
+-----------------------------------------------------+
T1 T3
+----+ +-------+
CPU2 |xxxx| |xxxxxxx|
--------------------------+----+--------+-------+-------->
| |
v v
+-----------------------------------------------------+
| Ring buffer 2 |
+-----------------------------------------------------+
T1
+--------------+
CPU3 |xxxxxxxxxxxxxx|
-----------+--------------+------------------------------>
|
v
+-----------------------------------------------------+
| Ring buffer 3 |
+-----------------------------------------------------+
T1: Thread 1; T2: Thread 2; T3: Thread 3
x: Thread is in running state
Figure 6. Ring buffer for system wide mode
2.3 Accessing buffer
--------------------
Based on the understanding of how the ring buffer is allocated in
various modes, this section explains access the ring buffer.
2.3.1 Producer-consumer model
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
In the Linux kernel, the PMU events can produce samples which are stored
into the ring buffer; the perf command in user space consumes the
samples by reading out data from the ring buffer and finally saves the
data into the file for post analysis. It’s a typical producer-consumer
model for using the ring buffer.
The perf process polls on the PMU events and sleeps when no events are
incoming. To prevent frequent exchanges between the kernel and user
space, the kernel event core layer introduces a watermark, which is
stored in the ``perf_buffer::watermark``. When a sample is recorded into
the ring buffer, and if the used buffer exceeds the watermark, the
kernel wakes up the perf process to read samples from the ring buffer.
::
Perf
/ | Read samples
Polling / `--------------| Ring buffer
v v ;---------------------v
+----------------+ +---------+---------+ +-------------------+
|Event wait queue| |data_head|data_tail| |***|***| | |***|
+----------------+ +---------+---------+ +-------------------+
^ ^ `------------------------^
| Wake up tasks | Store samples
+-----------------------------+
| Kernel event core layer |
+-----------------------------+
* : the data is filled by the writer.
Figure 7. Writing and reading the ring buffer
When the kernel event core layer notifies the user space, because
multiple events might share the same ring buffer for recording samples,
the core layer iterates every event associated with the ring buffer and
wakes up tasks waiting on the event. This is fulfilled by the kernel
function ``ring_buffer_wakeup()``.
After the perf process is woken up, it starts to check the ring buffers
one by one, if it finds any ring buffer containing samples it will read
out the samples for statistics or saving into the data file. Given the
perf process is able to run on any CPU, this leads to the ring buffer
potentially being accessed from multiple CPUs simultaneously, which
causes race conditions. The race condition handling is described in the
section :ref:`memory_synchronization`.
2.3.2 Properties of the ring buffers
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Linux kernel supports two write directions for the ring buffer: forward and
backward. The forward writing saves samples from the beginning of the ring
buffer, the backward writing stores data from the end of the ring buffer with
the reversed direction. The perf tool determines the writing direction.
Additionally, the tool can map buffers in either read-write mode or read-only
mode to the user space.
The ring buffer in the read-write mode is mapped with the property
``PROT_READ | PROT_WRITE``. With the write permission, the perf tool
updates the ``data_tail`` to indicate the data start position. Combining
with the head pointer ``data_head``, which works as the end position of
the current data, the perf tool can easily know where read out the data
from.
Alternatively, in the read-only mode, only the kernel keeps to update
the ``data_head`` while the user space cannot access the ``data_tail`` due
to the mapping property ``PROT_READ``.
As a result, the matrix below illustrates the various combinations of
direction and mapping characteristics. The perf tool employs two of these
combinations to support buffer types: the non-overwrite buffer and the
overwritable buffer.
.. list-table::
:widths: 1 1 1
:header-rows: 1
* - Mapping mode
- Forward
- Backward
* - read-write
- Non-overwrite ring buffer
- Not used
* - read-only
- Not used
- Overwritable ring buffer
The non-overwrite ring buffer uses the read-write mapping with forward
writing. It starts to save data from the beginning of the ring buffer
and wrap around when overflow, which is used with the read-write mode in
the normal ring buffer. When the consumer doesn't keep up with the
producer, it would lose some data, the kernel keeps how many records it
lost and generates the ``PERF_RECORD_LOST`` records in the next time
when it finds a space in the ring buffer.
The overwritable ring buffer uses the backward writing with the
read-only mode. It saves the data from the end of the ring buffer and
the ``data_head`` keeps the position of current data, the perf always
knows where it starts to read and until the end of the ring buffer, thus
it don't need the ``data_tail``. In this mode, it will not generate the
``PERF_RECORD_LOST`` records.
.. _writing_samples_into_buffer:
2.3.3 Writing samples into buffer
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
When a sample is taken and saved into the ring buffer, the kernel
prepares sample fields based on the sample type; then it prepares the
info for writing ring buffer which is stored in the structure
``perf_output_handle``. In the end, the kernel outputs the sample into
the ring buffer and updates the head pointer in the user page so the
perf tool can see the latest value.
The structure ``perf_output_handle`` serves as a temporary context for
tracking the information related to the buffer. The advantages of it is
that it enables concurrent writing to the buffer by different events.
For example, a software event and a hardware PMU event both are enabled
for profiling, two instances of ``perf_output_handle`` serve as separate
contexts for the software event and the hardware event respectively.
This allows each event to reserve its own memory space for populating
the record data.
2.3.4 Reading samples from buffer
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
In the user space, the perf tool utilizes the ``perf_event_mmap_page``
structure to handle the head and tail of the buffer. It also uses
``perf_mmap`` structure to keep track of a context for the ring buffer, this
context includes information about the buffer's starting and ending
addresses. Additionally, the mask value can be utilized to compute the
circular buffer pointer even for an overflow.
Similar to the kernel, the perf tool in the user space first reads out
the recorded data from the ring buffer, and then updates the buffer's
tail pointer ``perf_event_mmap_page::data_tail``.
.. _memory_synchronization:
2.3.5 Memory synchronization
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The modern CPUs with relaxed memory model cannot promise the memory
ordering, this means it’s possible to access the ring buffer and the
``perf_event_mmap_page`` structure out of order. To assure the specific
sequence for memory accessing perf ring buffer, memory barriers are
used to assure the data dependency. The rationale for the memory
synchronization is as below::
Kernel User space
if (LOAD ->data_tail) { LOAD ->data_head
(A) smp_rmb() (C)
STORE $data LOAD $data
smp_wmb() (B) smp_mb() (D)
STORE ->data_head STORE ->data_tail
}
The comments in tools/include/linux/ring_buffer.h gives nice description
for w
|