]> git.proxmox.com Git - ceph.git/blame - ceph/src/seastar/dpdk/doc/guides/prog_guide/ring_lib.rst
bump version to 19.2.0-pve1
[ceph.git] / ceph / src / seastar / dpdk / doc / guides / prog_guide / ring_lib.rst
CommitLineData
9f95a23c
TL
1.. SPDX-License-Identifier: BSD-3-Clause
2 Copyright(c) 2010-2014 Intel Corporation.
7c673cae
FG
3
4.. _Ring_Library:
5
6Ring Library
7============
8
9The ring allows the management of queues.
10Instead of having a linked list of infinite size, the rte_ring has the following properties:
11
12* FIFO
13
f51cf556
TL
14* Maximum size is fixed, the objects are stored in a table
15
16* Objects can be pointers or elements of multiple of 4 byte size
7c673cae
FG
17
18* Lockless implementation
19
20* Multi-consumer or single-consumer dequeue
21
22* Multi-producer or single-producer enqueue
23
24* Bulk dequeue - Dequeues the specified count of objects if successful; otherwise fails
25
26* Bulk enqueue - Enqueues the specified count of objects if successful; otherwise fails
27
28* Burst dequeue - Dequeue the maximum available objects if the specified count cannot be fulfilled
29
30* Burst enqueue - Enqueue the maximum available objects if the specified count cannot be fulfilled
31
32The advantages of this data structure over a linked list queue are as follows:
33
f51cf556 34* Faster; only requires a single 32 bit Compare-And-Swap instruction instead of several pointer size Compare-And-Swap instructions.
7c673cae
FG
35
36* Simpler than a full lockless queue.
37
38* Adapted to bulk enqueue/dequeue operations.
f51cf556 39 As objects are stored in a table, a dequeue of several objects will not produce as many cache misses as in a linked queue.
7c673cae
FG
40 Also, a bulk dequeue of many objects does not cost more than a dequeue of a simple object.
41
42The disadvantages:
43
44* Size is fixed
45
f51cf556 46* Having many rings costs more in terms of memory than a linked list queue. An empty ring contains at least N objects.
7c673cae
FG
47
48A simplified representation of a Ring is shown in with consumer and producer head and tail pointers to objects stored in the data structure.
49
50.. _figure_ring1:
51
52.. figure:: img/ring1.*
53
54 Ring Structure
55
56
57References for Ring Implementation in FreeBSD*
58----------------------------------------------
59
60The following code was added in FreeBSD 8.0, and is used in some network device drivers (at least in Intel drivers):
61
62 * `bufring.h in FreeBSD <http://svn.freebsd.org/viewvc/base/release/8.0.0/sys/sys/buf_ring.h?revision=199625&amp;view=markup>`_
63
64 * `bufring.c in FreeBSD <http://svn.freebsd.org/viewvc/base/release/8.0.0/sys/kern/subr_bufring.c?revision=199625&amp;view=markup>`_
65
66Lockless Ring Buffer in Linux*
67------------------------------
68
69The following is a link describing the `Linux Lockless Ring Buffer Design <http://lwn.net/Articles/340400/>`_.
70
71Additional Features
72-------------------
73
74Name
75~~~~
76
77A ring is identified by a unique name.
78It is not possible to create two rings with the same name (rte_ring_create() returns NULL if this is attempted).
79
7c673cae
FG
80Use Cases
81---------
82
83Use cases for the Ring library include:
84
85 * Communication between applications in the DPDK
86
87 * Used by memory pool allocator
88
89Anatomy of a Ring Buffer
90------------------------
91
92This section explains how a ring buffer operates.
93The ring structure is composed of two head and tail couples; one is used by producers and one is used by the consumers.
94The figures of the following sections refer to them as prod_head, prod_tail, cons_head and cons_tail.
95
96Each figure represents a simplified state of the ring, which is a circular buffer.
97The content of the function local variables is represented on the top of the figure,
98and the content of ring structure is represented on the bottom of the figure.
99
100Single Producer Enqueue
101~~~~~~~~~~~~~~~~~~~~~~~
102
103This section explains what occurs when a producer adds an object to the ring.
104In this example, only the producer head and tail (prod_head and prod_tail) are modified,
105and there is only one producer.
106
107The initial state is to have a prod_head and prod_tail pointing at the same location.
108
109Enqueue First Step
110^^^^^^^^^^^^^^^^^^
111
112First, *ring->prod_head* and ring->cons_tail are copied in local variables.
113The prod_next local variable points to the next element of the table, or several elements after in case of bulk enqueue.
114
115If there is not enough room in the ring (this is detected by checking cons_tail), it returns an error.
116
117
118.. _figure_ring-enqueue1:
119
120.. figure:: img/ring-enqueue1.*
121
122 Enqueue first step
123
124
125Enqueue Second Step
126^^^^^^^^^^^^^^^^^^^
127
128The second step is to modify *ring->prod_head* in ring structure to point to the same location as prod_next.
129
f51cf556 130The added object is copied in the ring (obj4).
7c673cae
FG
131
132
133.. _figure_ring-enqueue2:
134
135.. figure:: img/ring-enqueue2.*
136
137 Enqueue second step
138
139
140Enqueue Last Step
141^^^^^^^^^^^^^^^^^
142
143Once the object is added in the ring, ring->prod_tail in the ring structure is modified to point to the same location as *ring->prod_head*.
144The enqueue operation is finished.
145
146
147.. _figure_ring-enqueue3:
148
149.. figure:: img/ring-enqueue3.*
150
151 Enqueue last step
152
153
154Single Consumer Dequeue
155~~~~~~~~~~~~~~~~~~~~~~~
156
157This section explains what occurs when a consumer dequeues an object from the ring.
158In this example, only the consumer head and tail (cons_head and cons_tail) are modified and there is only one consumer.
159
160The initial state is to have a cons_head and cons_tail pointing at the same location.
161
162Dequeue First Step
163^^^^^^^^^^^^^^^^^^
164
165First, ring->cons_head and ring->prod_tail are copied in local variables.
166The cons_next local variable points to the next element of the table, or several elements after in the case of bulk dequeue.
167
168If there are not enough objects in the ring (this is detected by checking prod_tail), it returns an error.
169
170
171.. _figure_ring-dequeue1:
172
173.. figure:: img/ring-dequeue1.*
174
f51cf556 175 Dequeue first step
7c673cae
FG
176
177
178Dequeue Second Step
179^^^^^^^^^^^^^^^^^^^
180
181The second step is to modify ring->cons_head in the ring structure to point to the same location as cons_next.
182
f51cf556 183The dequeued object (obj1) is copied in the pointer given by the user.
7c673cae
FG
184
185
186.. _figure_ring-dequeue2:
187
188.. figure:: img/ring-dequeue2.*
189
190 Dequeue second step
191
192
193Dequeue Last Step
194^^^^^^^^^^^^^^^^^
195
196Finally, ring->cons_tail in the ring structure is modified to point to the same location as ring->cons_head.
197The dequeue operation is finished.
198
199
200.. _figure_ring-dequeue3:
201
202.. figure:: img/ring-dequeue3.*
203
204 Dequeue last step
205
206
207Multiple Producers Enqueue
208~~~~~~~~~~~~~~~~~~~~~~~~~~
209
210This section explains what occurs when two producers concurrently add an object to the ring.
211In this example, only the producer head and tail (prod_head and prod_tail) are modified.
212
213The initial state is to have a prod_head and prod_tail pointing at the same location.
214
215Multiple Producers Enqueue First Step
216^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
217
218On both cores, *ring->prod_head* and ring->cons_tail are copied in local variables.
219The prod_next local variable points to the next element of the table,
220or several elements after in the case of bulk enqueue.
221
222If there is not enough room in the ring (this is detected by checking cons_tail), it returns an error.
223
224
225.. _figure_ring-mp-enqueue1:
226
227.. figure:: img/ring-mp-enqueue1.*
228
229 Multiple producer enqueue first step
230
231
232Multiple Producers Enqueue Second Step
233^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
234
235The second step is to modify ring->prod_head in the ring structure to point to the same location as prod_next.
236This operation is done using a Compare And Swap (CAS) instruction, which does the following operations atomically:
237
238* If ring->prod_head is different to local variable prod_head,
239 the CAS operation fails, and the code restarts at first step.
240
241* Otherwise, ring->prod_head is set to local prod_next,
242 the CAS operation is successful, and processing continues.
243
244In the figure, the operation succeeded on core 1, and step one restarted on core 2.
245
246
247.. _figure_ring-mp-enqueue2:
248
249.. figure:: img/ring-mp-enqueue2.*
250
251 Multiple producer enqueue second step
252
253
254Multiple Producers Enqueue Third Step
255^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
256
257The CAS operation is retried on core 2 with success.
258
259The core 1 updates one element of the ring(obj4), and the core 2 updates another one (obj5).
260
261
262.. _figure_ring-mp-enqueue3:
263
264.. figure:: img/ring-mp-enqueue3.*
265
266 Multiple producer enqueue third step
267
268
269Multiple Producers Enqueue Fourth Step
270^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
271
272Each core now wants to update ring->prod_tail.
273A core can only update it if ring->prod_tail is equal to the prod_head local variable.
274This is only true on core 1. The operation is finished on core 1.
275
276
277.. _figure_ring-mp-enqueue4:
278
279.. figure:: img/ring-mp-enqueue4.*
280
281 Multiple producer enqueue fourth step
282
283
284Multiple Producers Enqueue Last Step
285^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
286
287Once ring->prod_tail is updated by core 1, core 2 is allowed to update it too.
288The operation is also finished on core 2.
289
290
291.. _figure_ring-mp-enqueue5:
292
293.. figure:: img/ring-mp-enqueue5.*
294
295 Multiple producer enqueue last step
296
297
298Modulo 32-bit Indexes
299~~~~~~~~~~~~~~~~~~~~~
300
301In the preceding figures, the prod_head, prod_tail, cons_head and cons_tail indexes are represented by arrows.
302In the actual implementation, these values are not between 0 and size(ring)-1 as would be assumed.
f51cf556 303The indexes are between 0 and 2^32 -1, and we mask their value when we access the object table (the ring itself).
7c673cae
FG
30432-bit modulo also implies that operations on indexes (such as, add/subtract) will automatically do 2^32 modulo
305if the result overflows the 32-bit number range.
306
307The following are two examples that help to explain how indexes are used in a ring.
308
309.. note::
310
311 To simplify the explanation, operations with modulo 16-bit are used instead of modulo 32-bit.
312 In addition, the four indexes are defined as unsigned 16-bit integers,
313 as opposed to unsigned 32-bit integers in the more realistic case.
314
315
316.. _figure_ring-modulo1:
317
318.. figure:: img/ring-modulo1.*
319
320 Modulo 32-bit indexes - Example 1
321
322
323This ring contains 11000 entries.
324
325
326.. _figure_ring-modulo2:
327
328.. figure:: img/ring-modulo2.*
329
330 Modulo 32-bit indexes - Example 2
331
332
333This ring contains 12536 entries.
334
335.. note::
336
337 For ease of understanding, we use modulo 65536 operations in the above examples.
338 In real execution cases, this is redundant for low efficiency, but is done automatically when the result overflows.
339
340The code always maintains a distance between producer and consumer between 0 and size(ring)-1.
341Thanks to this property, we can do subtractions between 2 index values in a modulo-32bit base:
342that's why the overflow of the indexes is not a problem.
343
344At any time, entries and free_entries are between 0 and size(ring)-1,
345even if only the first term of subtraction has overflowed:
346
347.. code-block:: c
348
349 uint32_t entries = (prod_tail - cons_head);
350 uint32_t free_entries = (mask + cons_tail -prod_head);
351
f51cf556
TL
352Producer/consumer synchronization modes
353---------------------------------------
354
355rte_ring supports different synchronization modes for producers and consumers.
356These modes can be specified at ring creation/init time via ``flags``
357parameter.
358That should help users to configure ring in the most suitable way for his
359specific usage scenarios.
360Currently supported modes:
361
362.. _Ring_Library_MPMC_Mode:
363
364MP/MC (default one)
365~~~~~~~~~~~~~~~~~~~
366
367Multi-producer (/multi-consumer) mode. This is a default enqueue (/dequeue)
368mode for the ring. In this mode multiple threads can enqueue (/dequeue)
369objects to (/from) the ring. For 'classic' DPDK deployments (with one thread
370per core) this is usually the most suitable and fastest synchronization mode.
371As a well known limitation - it can perform quite pure on some overcommitted
372scenarios.
373
374.. _Ring_Library_SPSC_Mode:
375
376SP/SC
377~~~~~
378Single-producer (/single-consumer) mode. In this mode only one thread at a time
379is allowed to enqueue (/dequeue) objects to (/from) the ring.
380
381.. _Ring_Library_MT_RTS_Mode:
382
383MP_RTS/MC_RTS
384~~~~~~~~~~~~~
385
386Multi-producer (/multi-consumer) with Relaxed Tail Sync (RTS) mode.
387The main difference from the original MP/MC algorithm is that
388tail value is increased not by every thread that finished enqueue/dequeue,
389but only by the last one.
390That allows threads to avoid spinning on ring tail value,
391leaving actual tail value change to the last thread at a given instance.
392That technique helps to avoid the Lock-Waiter-Preemption (LWP) problem on tail
393update and improves average enqueue/dequeue times on overcommitted systems.
394To achieve that RTS requires 2 64-bit CAS for each enqueue(/dequeue) operation:
395one for head update, second for tail update.
396In comparison the original MP/MC algorithm requires one 32-bit CAS
397for head update and waiting/spinning on tail value.
398
399.. _Ring_Library_MT_HTS_Mode:
400
401MP_HTS/MC_HTS
402~~~~~~~~~~~~~
403
404Multi-producer (/multi-consumer) with Head/Tail Sync (HTS) mode.
405In that mode enqueue/dequeue operation is fully serialized:
406at any given moment only one enqueue/dequeue operation can proceed.
407This is achieved by allowing a thread to proceed with changing ``head.value``
408only when ``head.value == tail.value``.
409Both head and tail values are updated atomically (as one 64-bit value).
410To achieve that 64-bit CAS is used by head update routine.
411That technique also avoids the Lock-Waiter-Preemption (LWP) problem on tail
412update and helps to improve ring enqueue/dequeue behavior in overcommitted
413scenarios. Another advantage of fully serialized producer/consumer -
414it provides the ability to implement MT safe peek API for rte_ring.
415
416Ring Peek API
417-------------
418
419For ring with serialized producer/consumer (HTS sync mode) it is possible
420to split public enqueue/dequeue API into two phases:
421
422* enqueue/dequeue start
423
424* enqueue/dequeue finish
425
426That allows user to inspect objects in the ring without removing them
427from it (aka MT safe peek) and reserve space for the objects in the ring
428before actual enqueue.
429Note that this API is available only for two sync modes:
430
431* Single Producer/Single Consumer (SP/SC)
432
433* Multi-producer/Multi-consumer with Head/Tail Sync (HTS)
434
435It is a user responsibility to create/init ring with appropriate sync modes
436selected. As an example of usage:
437
438.. code-block:: c
439
440 /* read 1 elem from the ring: */
441 uint32_t n = rte_ring_dequeue_bulk_start(ring, &obj, 1, NULL);
442 if (n != 0) {
443 /* examine object */
444 if (object_examine(obj) == KEEP)
445 /* decided to keep it in the ring. */
446 rte_ring_dequeue_finish(ring, 0);
447 else
448 /* decided to remove it from the ring. */
449 rte_ring_dequeue_finish(ring, n);
450 }
451
452Note that between ``_start_`` and ``_finish_`` none other thread can proceed
453with enqueue(/dequeue) operation till ``_finish_`` completes.
454
455Ring Peek Zero Copy API
456-----------------------
457
458Along with the advantages of the peek APIs, zero copy APIs provide the ability
459to copy the data to the ring memory directly without the need for temporary
460storage (for ex: array of mbufs on the stack).
461
462These APIs make it possible to split public enqueue/dequeue API into 3 phases:
463
464* enqueue/dequeue start
465
466* copy data to/from the ring
467
468* enqueue/dequeue finish
469
470Note that this API is available only for two sync modes:
471
472* Single Producer/Single Consumer (SP/SC)
473
474* Multi-producer/Multi-consumer with Head/Tail Sync (HTS)
475
476It is a user responsibility to create/init ring with appropriate sync modes.
477Following is an example of usage:
478
479.. code-block:: c
480
481 /* Reserve space on the ring */
482 n = rte_ring_enqueue_zc_burst_start(r, 32, &zcd, NULL);
483 /* Pkt I/O core polls packets from the NIC */
484 if (n != 0) {
485 nb_rx = rte_eth_rx_burst(portid, queueid, zcd->ptr1, zcd->n1);
486 if (nb_rx == zcd->n1 && n != zcd->n1)
487 nb_rx += rte_eth_rx_burst(portid, queueid, zcd->ptr2,
488 n - zcd->n1);
489 /* Provide packets to the packet processing cores */
490 rte_ring_enqueue_zc_finish(r, nb_rx);
491 }
492
493Note that between ``_start_`` and ``_finish_`` no other thread can proceed
494with enqueue(/dequeue) operation till ``_finish_`` completes.
495
7c673cae
FG
496References
497----------
498
499 * `bufring.h in FreeBSD <http://svn.freebsd.org/viewvc/base/release/8.0.0/sys/sys/buf_ring.h?revision=199625&amp;view=markup>`_ (version 8)
500
501 * `bufring.c in FreeBSD <http://svn.freebsd.org/viewvc/base/release/8.0.0/sys/kern/subr_bufring.c?revision=199625&amp;view=markup>`_ (version 8)
502
503 * `Linux Lockless Ring Buffer Design <http://lwn.net/Articles/340400/>`_