1fc1f2750SBernard Iremonger.. BSD LICENSE 2fc1f2750SBernard Iremonger Copyright(c) 2010-2014 Intel Corporation. All rights reserved. 3fc1f2750SBernard Iremonger All rights reserved. 4fc1f2750SBernard Iremonger 5fc1f2750SBernard Iremonger Redistribution and use in source and binary forms, with or without 6fc1f2750SBernard Iremonger modification, are permitted provided that the following conditions 7fc1f2750SBernard Iremonger are met: 8fc1f2750SBernard Iremonger 9fc1f2750SBernard Iremonger * Redistributions of source code must retain the above copyright 10fc1f2750SBernard Iremonger notice, this list of conditions and the following disclaimer. 11fc1f2750SBernard Iremonger * Redistributions in binary form must reproduce the above copyright 12fc1f2750SBernard Iremonger notice, this list of conditions and the following disclaimer in 13fc1f2750SBernard Iremonger the documentation and/or other materials provided with the 14fc1f2750SBernard Iremonger distribution. 15fc1f2750SBernard Iremonger * Neither the name of Intel Corporation nor the names of its 16fc1f2750SBernard Iremonger contributors may be used to endorse or promote products derived 17fc1f2750SBernard Iremonger from this software without specific prior written permission. 18fc1f2750SBernard Iremonger 19fc1f2750SBernard Iremonger THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20fc1f2750SBernard Iremonger "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21fc1f2750SBernard Iremonger LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22fc1f2750SBernard Iremonger A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23fc1f2750SBernard Iremonger OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24fc1f2750SBernard Iremonger SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25fc1f2750SBernard Iremonger LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26fc1f2750SBernard Iremonger DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27fc1f2750SBernard Iremonger THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28fc1f2750SBernard Iremonger (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29fc1f2750SBernard Iremonger OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30fc1f2750SBernard Iremonger 31fc1f2750SBernard Iremonger.. _Ring_Library: 32fc1f2750SBernard Iremonger 33fc1f2750SBernard IremongerRing Library 34fc1f2750SBernard Iremonger============ 35fc1f2750SBernard Iremonger 36fc1f2750SBernard IremongerThe ring allows the management of queues. 37fc1f2750SBernard IremongerInstead of having a linked list of infinite size, the rte_ring has the following properties: 38fc1f2750SBernard Iremonger 39fc1f2750SBernard Iremonger* FIFO 40fc1f2750SBernard Iremonger 41fc1f2750SBernard Iremonger* Maximum size is fixed, the pointers are stored in a table 42fc1f2750SBernard Iremonger 43fc1f2750SBernard Iremonger* Lockless implementation 44fc1f2750SBernard Iremonger 45fc1f2750SBernard Iremonger* Multi-consumer or single-consumer dequeue 46fc1f2750SBernard Iremonger 47fc1f2750SBernard Iremonger* Multi-producer or single-producer enqueue 48fc1f2750SBernard Iremonger 49fc1f2750SBernard Iremonger* Bulk dequeue - Dequeues the specified count of objects if successful; otherwise fails 50fc1f2750SBernard Iremonger 51fc1f2750SBernard Iremonger* Bulk enqueue - Enqueues the specified count of objects if successful; otherwise fails 52fc1f2750SBernard Iremonger 53fc1f2750SBernard Iremonger* Burst dequeue - Dequeue the maximum available objects if the specified count cannot be fulfilled 54fc1f2750SBernard Iremonger 55fc1f2750SBernard Iremonger* Burst enqueue - Enqueue the maximum available objects if the specified count cannot be fulfilled 56fc1f2750SBernard Iremonger 57fc1f2750SBernard IremongerThe advantages of this data structure over a linked list queue are as follows: 58fc1f2750SBernard Iremonger 59fc1f2750SBernard Iremonger* Faster; only requires a single Compare-And-Swap instruction of sizeof(void \*) instead of several double-Compare-And-Swap instructions. 60fc1f2750SBernard Iremonger 61fc1f2750SBernard Iremonger* Simpler than a full lockless queue. 62fc1f2750SBernard Iremonger 63fc1f2750SBernard Iremonger* Adapted to bulk enqueue/dequeue operations. 64fc1f2750SBernard Iremonger As pointers are stored in a table, a dequeue of several objects will not produce as many cache misses as in a linked queue. 65fc1f2750SBernard Iremonger Also, a bulk dequeue of many objects does not cost more than a dequeue of a simple object. 66fc1f2750SBernard Iremonger 67fc1f2750SBernard IremongerThe disadvantages: 68fc1f2750SBernard Iremonger 69fc1f2750SBernard Iremonger* Size is fixed 70fc1f2750SBernard Iremonger 71fc1f2750SBernard Iremonger* Having many rings costs more in terms of memory than a linked list queue. An empty ring contains at least N pointers. 72fc1f2750SBernard Iremonger 73fc1f2750SBernard IremongerA simplified representation of a Ring is shown in with consumer and producer head and tail pointers to objects stored in the data structure. 74fc1f2750SBernard Iremonger 75*4a22e6eeSJohn McNamara.. _figure_ring1: 76fc1f2750SBernard Iremonger 77*4a22e6eeSJohn McNamara.. figure:: img/ring1.* 78fc1f2750SBernard Iremonger 79*4a22e6eeSJohn McNamara Ring Structure 80fc1f2750SBernard Iremonger 81fc1f2750SBernard Iremonger 82fc1f2750SBernard IremongerReferences for Ring Implementation in FreeBSD* 83fc1f2750SBernard Iremonger---------------------------------------------- 84fc1f2750SBernard Iremonger 85fc1f2750SBernard IremongerThe following code was added in FreeBSD 8.0, and is used in some network device drivers (at least in Intel drivers): 86fc1f2750SBernard Iremonger 87fc1f2750SBernard Iremonger * `bufring.h in FreeBSD <http://svn.freebsd.org/viewvc/base/release/8.0.0/sys/sys/buf_ring.h?revision=199625&view=markup>`_ 88fc1f2750SBernard Iremonger 89fc1f2750SBernard Iremonger * `bufring.c in FreeBSD <http://svn.freebsd.org/viewvc/base/release/8.0.0/sys/kern/subr_bufring.c?revision=199625&view=markup>`_ 90fc1f2750SBernard Iremonger 91fc1f2750SBernard IremongerLockless Ring Buffer in Linux* 92fc1f2750SBernard Iremonger------------------------------ 93fc1f2750SBernard Iremonger 94fc1f2750SBernard IremongerThe following is a link describing the `Linux Lockless Ring Buffer Design <http://lwn.net/Articles/340400/>`_. 95fc1f2750SBernard Iremonger 96fc1f2750SBernard IremongerAdditional Features 97fc1f2750SBernard Iremonger------------------- 98fc1f2750SBernard Iremonger 99fc1f2750SBernard IremongerName 100fc1f2750SBernard Iremonger~~~~ 101fc1f2750SBernard Iremonger 102fc1f2750SBernard IremongerA ring is identified by a unique name. 103fc1f2750SBernard IremongerIt is not possible to create two rings with the same name (rte_ring_create() returns NULL if this is attempted). 104fc1f2750SBernard Iremonger 105fc1f2750SBernard IremongerWater Marking 106fc1f2750SBernard Iremonger~~~~~~~~~~~~~ 107fc1f2750SBernard Iremonger 108fc1f2750SBernard IremongerThe ring can have a high water mark (threshold). 109fc1f2750SBernard IremongerOnce an enqueue operation reaches the high water mark, the producer is notified, if the water mark is configured. 110fc1f2750SBernard Iremonger 111fc1f2750SBernard IremongerThis mechanism can be used, for example, to exert a back pressure on I/O to inform the LAN to PAUSE. 112fc1f2750SBernard Iremonger 113fc1f2750SBernard IremongerDebug 114fc1f2750SBernard Iremonger~~~~~ 115fc1f2750SBernard Iremonger 116fc1f2750SBernard IremongerWhen debug is enabled (CONFIG_RTE_LIBRTE_RING_DEBUG is set), 117fc1f2750SBernard Iremongerthe library stores some per-ring statistic counters about the number of enqueues/dequeues. 118fc1f2750SBernard IremongerThese statistics are per-core to avoid concurrent accesses or atomic operations. 119fc1f2750SBernard Iremonger 120fc1f2750SBernard IremongerUse Cases 121fc1f2750SBernard Iremonger--------- 122fc1f2750SBernard Iremonger 123fc1f2750SBernard IremongerUse cases for the Ring library include: 124fc1f2750SBernard Iremonger 12548624fd9SSiobhan Butler * Communication between applications in the DPDK 126fc1f2750SBernard Iremonger 127fc1f2750SBernard Iremonger * Used by memory pool allocator 128fc1f2750SBernard Iremonger 129fc1f2750SBernard IremongerAnatomy of a Ring Buffer 130fc1f2750SBernard Iremonger------------------------ 131fc1f2750SBernard Iremonger 132fc1f2750SBernard IremongerThis section explains how a ring buffer operates. 133fc1f2750SBernard IremongerThe ring structure is composed of two head and tail couples; one is used by producers and one is used by the consumers. 134fc1f2750SBernard IremongerThe figures of the following sections refer to them as prod_head, prod_tail, cons_head and cons_tail. 135fc1f2750SBernard Iremonger 136fc1f2750SBernard IremongerEach figure represents a simplified state of the ring, which is a circular buffer. 137fc1f2750SBernard IremongerThe content of the function local variables is represented on the top of the figure, 138fc1f2750SBernard Iremongerand the content of ring structure is represented on the bottom of the figure. 139fc1f2750SBernard Iremonger 140fc1f2750SBernard IremongerSingle Producer Enqueue 141fc1f2750SBernard Iremonger~~~~~~~~~~~~~~~~~~~~~~~ 142fc1f2750SBernard Iremonger 143fc1f2750SBernard IremongerThis section explains what occurs when a producer adds an object to the ring. 144fc1f2750SBernard IremongerIn this example, only the producer head and tail (prod_head and prod_tail) are modified, 145fc1f2750SBernard Iremongerand there is only one producer. 146fc1f2750SBernard Iremonger 147fc1f2750SBernard IremongerThe initial state is to have a prod_head and prod_tail pointing at the same location. 148fc1f2750SBernard Iremonger 149fc1f2750SBernard IremongerEnqueue First Step 150fc1f2750SBernard Iremonger^^^^^^^^^^^^^^^^^^ 151fc1f2750SBernard Iremonger 152fc1f2750SBernard IremongerFirst, *ring->prod_head* and ring->cons_tail are copied in local variables. 153fc1f2750SBernard IremongerThe prod_next local variable points to the next element of the table, or several elements after in case of bulk enqueue. 154fc1f2750SBernard Iremonger 155fc1f2750SBernard IremongerIf there is not enough room in the ring (this is detected by checking cons_tail), it returns an error. 156fc1f2750SBernard Iremonger 157fc1f2750SBernard Iremonger 158*4a22e6eeSJohn McNamara.. _figure_ring-enqueue1: 159*4a22e6eeSJohn McNamara 160*4a22e6eeSJohn McNamara.. figure:: img/ring-enqueue1.* 161*4a22e6eeSJohn McNamara 162*4a22e6eeSJohn McNamara Enqueue first step 163*4a22e6eeSJohn McNamara 164fc1f2750SBernard Iremonger 165fc1f2750SBernard IremongerEnqueue Second Step 166fc1f2750SBernard Iremonger^^^^^^^^^^^^^^^^^^^ 167fc1f2750SBernard Iremonger 168fc1f2750SBernard IremongerThe second step is to modify *ring->prod_head* in ring structure to point to the same location as prod_next. 169fc1f2750SBernard Iremonger 170fc1f2750SBernard IremongerA pointer to the added object is copied in the ring (obj4). 171fc1f2750SBernard Iremonger 172fc1f2750SBernard Iremonger 173*4a22e6eeSJohn McNamara.. _figure_ring-enqueue2: 174*4a22e6eeSJohn McNamara 175*4a22e6eeSJohn McNamara.. figure:: img/ring-enqueue2.* 176*4a22e6eeSJohn McNamara 177*4a22e6eeSJohn McNamara Enqueue second step 178*4a22e6eeSJohn McNamara 179fc1f2750SBernard Iremonger 180fc1f2750SBernard IremongerEnqueue Last Step 181fc1f2750SBernard Iremonger^^^^^^^^^^^^^^^^^ 182fc1f2750SBernard Iremonger 183fc1f2750SBernard IremongerOnce 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*. 184fc1f2750SBernard IremongerThe enqueue operation is finished. 185fc1f2750SBernard Iremonger 186fc1f2750SBernard Iremonger 187*4a22e6eeSJohn McNamara.. _figure_ring-enqueue3: 188*4a22e6eeSJohn McNamara 189*4a22e6eeSJohn McNamara.. figure:: img/ring-enqueue3.* 190*4a22e6eeSJohn McNamara 191*4a22e6eeSJohn McNamara Enqueue last step 192*4a22e6eeSJohn McNamara 193fc1f2750SBernard Iremonger 194fc1f2750SBernard IremongerSingle Consumer Dequeue 195fc1f2750SBernard Iremonger~~~~~~~~~~~~~~~~~~~~~~~ 196fc1f2750SBernard Iremonger 197fc1f2750SBernard IremongerThis section explains what occurs when a consumer dequeues an object from the ring. 198fc1f2750SBernard IremongerIn this example, only the consumer head and tail (cons_head and cons_tail) are modified and there is only one consumer. 199fc1f2750SBernard Iremonger 200fc1f2750SBernard IremongerThe initial state is to have a cons_head and cons_tail pointing at the same location. 201fc1f2750SBernard Iremonger 202fc1f2750SBernard IremongerDequeue First Step 203fc1f2750SBernard Iremonger^^^^^^^^^^^^^^^^^^ 204fc1f2750SBernard Iremonger 205fc1f2750SBernard IremongerFirst, ring->cons_head and ring->prod_tail are copied in local variables. 206fc1f2750SBernard IremongerThe cons_next local variable points to the next element of the table, or several elements after in the case of bulk dequeue. 207fc1f2750SBernard Iremonger 208fc1f2750SBernard IremongerIf there are not enough objects in the ring (this is detected by checking prod_tail), it returns an error. 209fc1f2750SBernard Iremonger 210fc1f2750SBernard Iremonger 211*4a22e6eeSJohn McNamara.. _figure_ring-dequeue1: 212*4a22e6eeSJohn McNamara 213*4a22e6eeSJohn McNamara.. figure:: img/ring-dequeue1.* 214*4a22e6eeSJohn McNamara 215*4a22e6eeSJohn McNamara Dequeue last step 216*4a22e6eeSJohn McNamara 217fc1f2750SBernard Iremonger 218fc1f2750SBernard IremongerDequeue Second Step 219fc1f2750SBernard Iremonger^^^^^^^^^^^^^^^^^^^ 220fc1f2750SBernard Iremonger 221fc1f2750SBernard IremongerThe second step is to modify ring->cons_head in the ring structure to point to the same location as cons_next. 222fc1f2750SBernard Iremonger 223fc1f2750SBernard IremongerThe pointer to the dequeued object (obj1) is copied in the pointer given by the user. 224fc1f2750SBernard Iremonger 225fc1f2750SBernard Iremonger 226*4a22e6eeSJohn McNamara.. _figure_ring-dequeue2: 227*4a22e6eeSJohn McNamara 228*4a22e6eeSJohn McNamara.. figure:: img/ring-dequeue2.* 229*4a22e6eeSJohn McNamara 230*4a22e6eeSJohn McNamara Dequeue second step 231*4a22e6eeSJohn McNamara 232fc1f2750SBernard Iremonger 233fc1f2750SBernard IremongerDequeue Last Step 234fc1f2750SBernard Iremonger^^^^^^^^^^^^^^^^^ 235fc1f2750SBernard Iremonger 236fc1f2750SBernard IremongerFinally, ring->cons_tail in the ring structure is modified to point to the same location as ring->cons_head. 237fc1f2750SBernard IremongerThe dequeue operation is finished. 238fc1f2750SBernard Iremonger 239fc1f2750SBernard Iremonger 240*4a22e6eeSJohn McNamara.. _figure_ring-dequeue3: 241*4a22e6eeSJohn McNamara 242*4a22e6eeSJohn McNamara.. figure:: img/ring-dequeue3.* 243*4a22e6eeSJohn McNamara 244*4a22e6eeSJohn McNamara Dequeue last step 245*4a22e6eeSJohn McNamara 246fc1f2750SBernard Iremonger 247fc1f2750SBernard IremongerMultiple Producers Enqueue 248fc1f2750SBernard Iremonger~~~~~~~~~~~~~~~~~~~~~~~~~~ 249fc1f2750SBernard Iremonger 250fc1f2750SBernard IremongerThis section explains what occurs when two producers concurrently add an object to the ring. 251fc1f2750SBernard IremongerIn this example, only the producer head and tail (prod_head and prod_tail) are modified. 252fc1f2750SBernard Iremonger 253fc1f2750SBernard IremongerThe initial state is to have a prod_head and prod_tail pointing at the same location. 254fc1f2750SBernard Iremonger 255*4a22e6eeSJohn McNamaraMultiple Consumer Enqueue First Step 256*4a22e6eeSJohn McNamara^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 257fc1f2750SBernard Iremonger 258fc1f2750SBernard IremongerOn both cores, *ring->prod_head* and ring->cons_tail are copied in local variables. 259fc1f2750SBernard IremongerThe prod_next local variable points to the next element of the table, 260fc1f2750SBernard Iremongeror several elements after in the case of bulk enqueue. 261fc1f2750SBernard Iremonger 2620058f08dSPablo de LaraIf there is not enough room in the ring (this is detected by checking cons_tail), it returns an error. 263fc1f2750SBernard Iremonger 264fc1f2750SBernard Iremonger 265*4a22e6eeSJohn McNamara.. _figure_ring-mp-enqueue1: 266fc1f2750SBernard Iremonger 267*4a22e6eeSJohn McNamara.. figure:: img/ring-mp-enqueue1.* 268*4a22e6eeSJohn McNamara 269*4a22e6eeSJohn McNamara Multiple consumer enqueue first step 270*4a22e6eeSJohn McNamara 271*4a22e6eeSJohn McNamara 272*4a22e6eeSJohn McNamaraMultiple Consumer Enqueue Second Step 273*4a22e6eeSJohn McNamara^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 274fc1f2750SBernard Iremonger 275fc1f2750SBernard IremongerThe second step is to modify ring->prod_head in the ring structure to point to the same location as prod_next. 276fc1f2750SBernard IremongerThis operation is done using a Compare And Swap (CAS) instruction, which does the following operations atomically: 277fc1f2750SBernard Iremonger 278fc1f2750SBernard Iremonger* If ring->prod_head is different to local variable prod_head, 279fc1f2750SBernard Iremonger the CAS operation fails, and the code restarts at first step. 280fc1f2750SBernard Iremonger 281fc1f2750SBernard Iremonger* Otherwise, ring->prod_head is set to local prod_next, 282fc1f2750SBernard Iremonger the CAS operation is successful, and processing continues. 283fc1f2750SBernard Iremonger 284fc1f2750SBernard IremongerIn the figure, the operation succeeded on core 1, and step one restarted on core 2. 285fc1f2750SBernard Iremonger 286fc1f2750SBernard Iremonger 287*4a22e6eeSJohn McNamara.. _figure_ring-mp-enqueue2: 288fc1f2750SBernard Iremonger 289*4a22e6eeSJohn McNamara.. figure:: img/ring-mp-enqueue2.* 290*4a22e6eeSJohn McNamara 291*4a22e6eeSJohn McNamara Multiple consumer enqueue second step 292*4a22e6eeSJohn McNamara 293*4a22e6eeSJohn McNamara 294*4a22e6eeSJohn McNamaraMultiple Consumer Enqueue Third Step 295*4a22e6eeSJohn McNamara^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 296fc1f2750SBernard Iremonger 297fc1f2750SBernard IremongerThe CAS operation is retried on core 2 with success. 298fc1f2750SBernard Iremonger 299fc1f2750SBernard IremongerThe core 1 updates one element of the ring(obj4), and the core 2 updates another one (obj5). 300fc1f2750SBernard Iremonger 301fc1f2750SBernard Iremonger 302*4a22e6eeSJohn McNamara.. _figure_ring-mp-enqueue3: 303fc1f2750SBernard Iremonger 304*4a22e6eeSJohn McNamara.. figure:: img/ring-mp-enqueue3.* 305*4a22e6eeSJohn McNamara 306*4a22e6eeSJohn McNamara Multiple consumer enqueue third step 307*4a22e6eeSJohn McNamara 308*4a22e6eeSJohn McNamara 309*4a22e6eeSJohn McNamaraMultiple Consumer Enqueue Fourth Step 310*4a22e6eeSJohn McNamara^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 311fc1f2750SBernard Iremonger 312fc1f2750SBernard IremongerEach core now wants to update ring->prod_tail. 313fc1f2750SBernard IremongerA core can only update it if ring->prod_tail is equal to the prod_head local variable. 314fc1f2750SBernard IremongerThis is only true on core 1. The operation is finished on core 1. 315fc1f2750SBernard Iremonger 316fc1f2750SBernard Iremonger 317*4a22e6eeSJohn McNamara.. _figure_ring-mp-enqueue4: 318fc1f2750SBernard Iremonger 319*4a22e6eeSJohn McNamara.. figure:: img/ring-mp-enqueue4.* 320*4a22e6eeSJohn McNamara 321*4a22e6eeSJohn McNamara Multiple consumer enqueue fourth step 322*4a22e6eeSJohn McNamara 323*4a22e6eeSJohn McNamara 324*4a22e6eeSJohn McNamaraMultiple Consumer Enqueue Last Step 325*4a22e6eeSJohn McNamara^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 326fc1f2750SBernard Iremonger 327fc1f2750SBernard IremongerOnce ring->prod_tail is updated by core 1, core 2 is allowed to update it too. 328fc1f2750SBernard IremongerThe operation is also finished on core 2. 329fc1f2750SBernard Iremonger 330fc1f2750SBernard Iremonger 331*4a22e6eeSJohn McNamara.. _figure_ring-mp-enqueue5: 332*4a22e6eeSJohn McNamara 333*4a22e6eeSJohn McNamara.. figure:: img/ring-mp-enqueue5.* 334*4a22e6eeSJohn McNamara 335*4a22e6eeSJohn McNamara Multiple consumer enqueue last step 336*4a22e6eeSJohn McNamara 337fc1f2750SBernard Iremonger 338fc1f2750SBernard IremongerModulo 32-bit Indexes 339fc1f2750SBernard Iremonger~~~~~~~~~~~~~~~~~~~~~ 340fc1f2750SBernard Iremonger 341fc1f2750SBernard IremongerIn the preceding figures, the prod_head, prod_tail, cons_head and cons_tail indexes are represented by arrows. 342fc1f2750SBernard IremongerIn the actual implementation, these values are not between 0 and size(ring)-1 as would be assumed. 343fc1f2750SBernard IremongerThe indexes are between 0 and 2^32 -1, and we mask their value when we access the pointer table (the ring itself). 344fc1f2750SBernard Iremonger32-bit modulo also implies that operations on indexes (such as, add/subtract) will automatically do 2^32 modulo 345fc1f2750SBernard Iremongerif the result overflows the 32-bit number range. 346fc1f2750SBernard Iremonger 347fc1f2750SBernard IremongerThe following are two examples that help to explain how indexes are used in a ring. 348fc1f2750SBernard Iremonger 349fc1f2750SBernard Iremonger.. note:: 350fc1f2750SBernard Iremonger 351fc1f2750SBernard Iremonger To simplify the explanation, operations with modulo 16-bit are used instead of modulo 32-bit. 352fc1f2750SBernard Iremonger In addition, the four indexes are defined as unsigned 16-bit integers, 353fc1f2750SBernard Iremonger as opposed to unsigned 32-bit integers in the more realistic case. 354fc1f2750SBernard Iremonger 355fc1f2750SBernard Iremonger 356*4a22e6eeSJohn McNamara.. _figure_ring-modulo1: 357*4a22e6eeSJohn McNamara 358*4a22e6eeSJohn McNamara.. figure:: img/ring-modulo1.* 359*4a22e6eeSJohn McNamara 360*4a22e6eeSJohn McNamara Modulo 32-bit indexes - Example 1 361*4a22e6eeSJohn McNamara 362fc1f2750SBernard Iremonger 363fc1f2750SBernard IremongerThis ring contains 11000 entries. 364fc1f2750SBernard Iremonger 365fc1f2750SBernard Iremonger 366*4a22e6eeSJohn McNamara.. _figure_ring-modulo2: 367*4a22e6eeSJohn McNamara 368*4a22e6eeSJohn McNamara.. figure:: img/ring-modulo2.* 369*4a22e6eeSJohn McNamara 370*4a22e6eeSJohn McNamara Modulo 32-bit indexes - Example 2 371*4a22e6eeSJohn McNamara 372fc1f2750SBernard Iremonger 373fc1f2750SBernard IremongerThis ring contains 12536 entries. 374fc1f2750SBernard Iremonger 375fc1f2750SBernard Iremonger.. note:: 376fc1f2750SBernard Iremonger 377fc1f2750SBernard Iremonger For ease of understanding, we use modulo 65536 operations in the above examples. 378fc1f2750SBernard Iremonger In real execution cases, this is redundant for low efficiency, but is done automatically when the result overflows. 379fc1f2750SBernard Iremonger 380fc1f2750SBernard IremongerThe code always maintains a distance between producer and consumer between 0 and size(ring)-1. 381fc1f2750SBernard IremongerThanks to this property, we can do subtractions between 2 index values in a modulo-32bit base: 382fc1f2750SBernard Iremongerthat's why the overflow of the indexes is not a problem. 383fc1f2750SBernard Iremonger 384fc1f2750SBernard IremongerAt any time, entries and free_entries are between 0 and size(ring)-1, 385fc1f2750SBernard Iremongereven if only the first term of subtraction has overflowed: 386fc1f2750SBernard Iremonger 387fc1f2750SBernard Iremonger.. code-block:: c 388fc1f2750SBernard Iremonger 389fc1f2750SBernard Iremonger uint32_t entries = (prod_tail - cons_head); 390fc1f2750SBernard Iremonger uint32_t free_entries = (mask + cons_tail -prod_head); 391fc1f2750SBernard Iremonger 392fc1f2750SBernard IremongerReferences 393fc1f2750SBernard Iremonger---------- 394fc1f2750SBernard Iremonger 395fc1f2750SBernard Iremonger * `bufring.h in FreeBSD <http://svn.freebsd.org/viewvc/base/release/8.0.0/sys/sys/buf_ring.h?revision=199625&view=markup>`_ (version 8) 396fc1f2750SBernard Iremonger 397fc1f2750SBernard Iremonger * `bufring.c in FreeBSD <http://svn.freebsd.org/viewvc/base/release/8.0.0/sys/kern/subr_bufring.c?revision=199625&view=markup>`_ (version 8) 398fc1f2750SBernard Iremonger 399fc1f2750SBernard Iremonger * `Linux Lockless Ring Buffer Design <http://lwn.net/Articles/340400/>`_ 400