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 75fc1f2750SBernard Iremonger.. _pg_figure_4: 76fc1f2750SBernard Iremonger 77fc1f2750SBernard Iremonger**Figure 4. Ring Structure** 78fc1f2750SBernard Iremonger 79fc1f2750SBernard Iremonger.. image5_png has been replaced 80fc1f2750SBernard Iremonger 81fc1f2750SBernard Iremonger|ring1| 82fc1f2750SBernard Iremonger 83fc1f2750SBernard IremongerReferences for Ring Implementation in FreeBSD* 84fc1f2750SBernard Iremonger---------------------------------------------- 85fc1f2750SBernard Iremonger 86fc1f2750SBernard IremongerThe following code was added in FreeBSD 8.0, and is used in some network device drivers (at least in Intel drivers): 87fc1f2750SBernard Iremonger 88fc1f2750SBernard Iremonger * `bufring.h in FreeBSD <http://svn.freebsd.org/viewvc/base/release/8.0.0/sys/sys/buf_ring.h?revision=199625&view=markup>`_ 89fc1f2750SBernard Iremonger 90fc1f2750SBernard Iremonger * `bufring.c in FreeBSD <http://svn.freebsd.org/viewvc/base/release/8.0.0/sys/kern/subr_bufring.c?revision=199625&view=markup>`_ 91fc1f2750SBernard Iremonger 92fc1f2750SBernard IremongerLockless Ring Buffer in Linux* 93fc1f2750SBernard Iremonger------------------------------ 94fc1f2750SBernard Iremonger 95fc1f2750SBernard IremongerThe following is a link describing the `Linux Lockless Ring Buffer Design <http://lwn.net/Articles/340400/>`_. 96fc1f2750SBernard Iremonger 97fc1f2750SBernard IremongerAdditional Features 98fc1f2750SBernard Iremonger------------------- 99fc1f2750SBernard Iremonger 100fc1f2750SBernard IremongerName 101fc1f2750SBernard Iremonger~~~~ 102fc1f2750SBernard Iremonger 103fc1f2750SBernard IremongerA ring is identified by a unique name. 104fc1f2750SBernard IremongerIt is not possible to create two rings with the same name (rte_ring_create() returns NULL if this is attempted). 105fc1f2750SBernard Iremonger 106fc1f2750SBernard IremongerWater Marking 107fc1f2750SBernard Iremonger~~~~~~~~~~~~~ 108fc1f2750SBernard Iremonger 109fc1f2750SBernard IremongerThe ring can have a high water mark (threshold). 110fc1f2750SBernard IremongerOnce an enqueue operation reaches the high water mark, the producer is notified, if the water mark is configured. 111fc1f2750SBernard Iremonger 112fc1f2750SBernard IremongerThis mechanism can be used, for example, to exert a back pressure on I/O to inform the LAN to PAUSE. 113fc1f2750SBernard Iremonger 114fc1f2750SBernard IremongerDebug 115fc1f2750SBernard Iremonger~~~~~ 116fc1f2750SBernard Iremonger 117fc1f2750SBernard IremongerWhen debug is enabled (CONFIG_RTE_LIBRTE_RING_DEBUG is set), 118fc1f2750SBernard Iremongerthe library stores some per-ring statistic counters about the number of enqueues/dequeues. 119fc1f2750SBernard IremongerThese statistics are per-core to avoid concurrent accesses or atomic operations. 120fc1f2750SBernard Iremonger 121fc1f2750SBernard IremongerUse Cases 122fc1f2750SBernard Iremonger--------- 123fc1f2750SBernard Iremonger 124fc1f2750SBernard IremongerUse cases for the Ring library include: 125fc1f2750SBernard Iremonger 126fc1f2750SBernard Iremonger * Communication between applications in the Intel® DPDK 127fc1f2750SBernard Iremonger 128fc1f2750SBernard Iremonger * Used by memory pool allocator 129fc1f2750SBernard Iremonger 130fc1f2750SBernard IremongerAnatomy of a Ring Buffer 131fc1f2750SBernard Iremonger------------------------ 132fc1f2750SBernard Iremonger 133fc1f2750SBernard IremongerThis section explains how a ring buffer operates. 134fc1f2750SBernard IremongerThe ring structure is composed of two head and tail couples; one is used by producers and one is used by the consumers. 135fc1f2750SBernard IremongerThe figures of the following sections refer to them as prod_head, prod_tail, cons_head and cons_tail. 136fc1f2750SBernard Iremonger 137fc1f2750SBernard IremongerEach figure represents a simplified state of the ring, which is a circular buffer. 138fc1f2750SBernard IremongerThe content of the function local variables is represented on the top of the figure, 139fc1f2750SBernard Iremongerand the content of ring structure is represented on the bottom of the figure. 140fc1f2750SBernard Iremonger 141fc1f2750SBernard IremongerSingle Producer Enqueue 142fc1f2750SBernard Iremonger~~~~~~~~~~~~~~~~~~~~~~~ 143fc1f2750SBernard Iremonger 144fc1f2750SBernard IremongerThis section explains what occurs when a producer adds an object to the ring. 145fc1f2750SBernard IremongerIn this example, only the producer head and tail (prod_head and prod_tail) are modified, 146fc1f2750SBernard Iremongerand there is only one producer. 147fc1f2750SBernard Iremonger 148fc1f2750SBernard IremongerThe initial state is to have a prod_head and prod_tail pointing at the same location. 149fc1f2750SBernard Iremonger 150fc1f2750SBernard IremongerEnqueue First Step 151fc1f2750SBernard Iremonger^^^^^^^^^^^^^^^^^^ 152fc1f2750SBernard Iremonger 153fc1f2750SBernard IremongerFirst, *ring->prod_head* and ring->cons_tail are copied in local variables. 154fc1f2750SBernard IremongerThe prod_next local variable points to the next element of the table, or several elements after in case of bulk enqueue. 155fc1f2750SBernard Iremonger 156fc1f2750SBernard IremongerIf there is not enough room in the ring (this is detected by checking cons_tail), it returns an error. 157fc1f2750SBernard Iremonger 158fc1f2750SBernard Iremonger.. image6_png has been replaced 159fc1f2750SBernard Iremonger 160fc1f2750SBernard Iremonger|ring-enqueue1| 161fc1f2750SBernard Iremonger 162fc1f2750SBernard IremongerEnqueue Second Step 163fc1f2750SBernard Iremonger^^^^^^^^^^^^^^^^^^^ 164fc1f2750SBernard Iremonger 165fc1f2750SBernard IremongerThe second step is to modify *ring->prod_head* in ring structure to point to the same location as prod_next. 166fc1f2750SBernard Iremonger 167fc1f2750SBernard IremongerA pointer to the added object is copied in the ring (obj4). 168fc1f2750SBernard Iremonger 169fc1f2750SBernard Iremonger.. image7_png has been replaced 170fc1f2750SBernard Iremonger 171fc1f2750SBernard Iremonger|ring-enqueue2| 172fc1f2750SBernard Iremonger 173fc1f2750SBernard IremongerEnqueue Last Step 174fc1f2750SBernard Iremonger^^^^^^^^^^^^^^^^^ 175fc1f2750SBernard Iremonger 176fc1f2750SBernard 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*. 177fc1f2750SBernard IremongerThe enqueue operation is finished. 178fc1f2750SBernard Iremonger 179fc1f2750SBernard Iremonger.. image8_png has been replaced 180fc1f2750SBernard Iremonger 181fc1f2750SBernard Iremonger|ring-enqueue3| 182fc1f2750SBernard Iremonger 183fc1f2750SBernard IremongerSingle Consumer Dequeue 184fc1f2750SBernard Iremonger~~~~~~~~~~~~~~~~~~~~~~~ 185fc1f2750SBernard Iremonger 186fc1f2750SBernard IremongerThis section explains what occurs when a consumer dequeues an object from the ring. 187fc1f2750SBernard IremongerIn this example, only the consumer head and tail (cons_head and cons_tail) are modified and there is only one consumer. 188fc1f2750SBernard Iremonger 189fc1f2750SBernard IremongerThe initial state is to have a cons_head and cons_tail pointing at the same location. 190fc1f2750SBernard Iremonger 191fc1f2750SBernard IremongerDequeue First Step 192fc1f2750SBernard Iremonger^^^^^^^^^^^^^^^^^^ 193fc1f2750SBernard Iremonger 194fc1f2750SBernard IremongerFirst, ring->cons_head and ring->prod_tail are copied in local variables. 195fc1f2750SBernard IremongerThe cons_next local variable points to the next element of the table, or several elements after in the case of bulk dequeue. 196fc1f2750SBernard Iremonger 197fc1f2750SBernard IremongerIf there are not enough objects in the ring (this is detected by checking prod_tail), it returns an error. 198fc1f2750SBernard Iremonger 199fc1f2750SBernard Iremonger.. image9_png has been replaced 200fc1f2750SBernard Iremonger 201fc1f2750SBernard Iremonger|ring-dequeue1| 202fc1f2750SBernard Iremonger 203fc1f2750SBernard IremongerDequeue Second Step 204fc1f2750SBernard Iremonger^^^^^^^^^^^^^^^^^^^ 205fc1f2750SBernard Iremonger 206fc1f2750SBernard IremongerThe second step is to modify ring->cons_head in the ring structure to point to the same location as cons_next. 207fc1f2750SBernard Iremonger 208fc1f2750SBernard IremongerThe pointer to the dequeued object (obj1) is copied in the pointer given by the user. 209fc1f2750SBernard Iremonger 210fc1f2750SBernard Iremonger.. image10_png has been replaced 211fc1f2750SBernard Iremonger 212fc1f2750SBernard Iremonger|ring-dequeue2| 213fc1f2750SBernard Iremonger 214fc1f2750SBernard IremongerDequeue Last Step 215fc1f2750SBernard Iremonger^^^^^^^^^^^^^^^^^ 216fc1f2750SBernard Iremonger 217fc1f2750SBernard IremongerFinally, ring->cons_tail in the ring structure is modified to point to the same location as ring->cons_head. 218fc1f2750SBernard IremongerThe dequeue operation is finished. 219fc1f2750SBernard Iremonger 220fc1f2750SBernard Iremonger.. image11_png has been replaced 221fc1f2750SBernard Iremonger 222fc1f2750SBernard Iremonger|ring-dequeue3| 223fc1f2750SBernard Iremonger 224fc1f2750SBernard IremongerMultiple Producers Enqueue 225fc1f2750SBernard Iremonger~~~~~~~~~~~~~~~~~~~~~~~~~~ 226fc1f2750SBernard Iremonger 227fc1f2750SBernard IremongerThis section explains what occurs when two producers concurrently add an object to the ring. 228fc1f2750SBernard IremongerIn this example, only the producer head and tail (prod_head and prod_tail) are modified. 229fc1f2750SBernard Iremonger 230fc1f2750SBernard IremongerThe initial state is to have a prod_head and prod_tail pointing at the same location. 231fc1f2750SBernard Iremonger 232fc1f2750SBernard IremongerMC Enqueue First Step 233fc1f2750SBernard Iremonger^^^^^^^^^^^^^^^^^^^^^ 234fc1f2750SBernard Iremonger 235fc1f2750SBernard IremongerOn both cores, *ring->prod_head* and ring->cons_tail are copied in local variables. 236fc1f2750SBernard IremongerThe prod_next local variable points to the next element of the table, 237fc1f2750SBernard Iremongeror several elements after in the case of bulk enqueue. 238fc1f2750SBernard Iremonger 239*0058f08dSPablo de LaraIf there is not enough room in the ring (this is detected by checking cons_tail), it returns an error. 240fc1f2750SBernard Iremonger 241fc1f2750SBernard Iremonger.. image12_png has been replaced 242fc1f2750SBernard Iremonger 243fc1f2750SBernard Iremonger|ring-mp-enqueue1| 244fc1f2750SBernard Iremonger 245fc1f2750SBernard IremongerMC Enqueue Second Step 246fc1f2750SBernard Iremonger^^^^^^^^^^^^^^^^^^^^^^ 247fc1f2750SBernard Iremonger 248fc1f2750SBernard IremongerThe second step is to modify ring->prod_head in the ring structure to point to the same location as prod_next. 249fc1f2750SBernard IremongerThis operation is done using a Compare And Swap (CAS) instruction, which does the following operations atomically: 250fc1f2750SBernard Iremonger 251fc1f2750SBernard Iremonger* If ring->prod_head is different to local variable prod_head, 252fc1f2750SBernard Iremonger the CAS operation fails, and the code restarts at first step. 253fc1f2750SBernard Iremonger 254fc1f2750SBernard Iremonger* Otherwise, ring->prod_head is set to local prod_next, 255fc1f2750SBernard Iremonger the CAS operation is successful, and processing continues. 256fc1f2750SBernard Iremonger 257fc1f2750SBernard IremongerIn the figure, the operation succeeded on core 1, and step one restarted on core 2. 258fc1f2750SBernard Iremonger 259fc1f2750SBernard Iremonger.. image13_png has been replaced 260fc1f2750SBernard Iremonger 261fc1f2750SBernard Iremonger|ring-mp-enqueue2| 262fc1f2750SBernard Iremonger 263fc1f2750SBernard IremongerMC Enqueue Third Step 264fc1f2750SBernard Iremonger^^^^^^^^^^^^^^^^^^^^^ 265fc1f2750SBernard Iremonger 266fc1f2750SBernard IremongerThe CAS operation is retried on core 2 with success. 267fc1f2750SBernard Iremonger 268fc1f2750SBernard IremongerThe core 1 updates one element of the ring(obj4), and the core 2 updates another one (obj5). 269fc1f2750SBernard Iremonger 270fc1f2750SBernard Iremonger.. image14_png has been replaced 271fc1f2750SBernard Iremonger 272fc1f2750SBernard Iremonger|ring-mp-enqueue3| 273fc1f2750SBernard Iremonger 274fc1f2750SBernard IremongerMC Enqueue Fourth Step 275fc1f2750SBernard Iremonger^^^^^^^^^^^^^^^^^^^^^^ 276fc1f2750SBernard Iremonger 277fc1f2750SBernard IremongerEach core now wants to update ring->prod_tail. 278fc1f2750SBernard IremongerA core can only update it if ring->prod_tail is equal to the prod_head local variable. 279fc1f2750SBernard IremongerThis is only true on core 1. The operation is finished on core 1. 280fc1f2750SBernard Iremonger 281fc1f2750SBernard Iremonger.. image15_png has been replaced 282fc1f2750SBernard Iremonger 283fc1f2750SBernard Iremonger|ring-mp-enqueue4| 284fc1f2750SBernard Iremonger 285fc1f2750SBernard IremongerMC Enqueue Last Step 286fc1f2750SBernard Iremonger^^^^^^^^^^^^^^^^^^^^ 287fc1f2750SBernard Iremonger 288fc1f2750SBernard IremongerOnce ring->prod_tail is updated by core 1, core 2 is allowed to update it too. 289fc1f2750SBernard IremongerThe operation is also finished on core 2. 290fc1f2750SBernard Iremonger 291fc1f2750SBernard Iremonger.. image16_png has been replaced 292fc1f2750SBernard Iremonger 293fc1f2750SBernard Iremonger|ring-mp-enqueue5| 294fc1f2750SBernard Iremonger 295fc1f2750SBernard IremongerModulo 32-bit Indexes 296fc1f2750SBernard Iremonger~~~~~~~~~~~~~~~~~~~~~ 297fc1f2750SBernard Iremonger 298fc1f2750SBernard IremongerIn the preceding figures, the prod_head, prod_tail, cons_head and cons_tail indexes are represented by arrows. 299fc1f2750SBernard IremongerIn the actual implementation, these values are not between 0 and size(ring)-1 as would be assumed. 300fc1f2750SBernard IremongerThe indexes are between 0 and 2^32 -1, and we mask their value when we access the pointer table (the ring itself). 301fc1f2750SBernard Iremonger32-bit modulo also implies that operations on indexes (such as, add/subtract) will automatically do 2^32 modulo 302fc1f2750SBernard Iremongerif the result overflows the 32-bit number range. 303fc1f2750SBernard Iremonger 304fc1f2750SBernard IremongerThe following are two examples that help to explain how indexes are used in a ring. 305fc1f2750SBernard Iremonger 306fc1f2750SBernard Iremonger.. note:: 307fc1f2750SBernard Iremonger 308fc1f2750SBernard Iremonger To simplify the explanation, operations with modulo 16-bit are used instead of modulo 32-bit. 309fc1f2750SBernard Iremonger In addition, the four indexes are defined as unsigned 16-bit integers, 310fc1f2750SBernard Iremonger as opposed to unsigned 32-bit integers in the more realistic case. 311fc1f2750SBernard Iremonger 312fc1f2750SBernard Iremonger.. image17_png has been replaced 313fc1f2750SBernard Iremonger 314fc1f2750SBernard Iremonger|ring-modulo1| 315fc1f2750SBernard Iremonger 316fc1f2750SBernard IremongerThis ring contains 11000 entries. 317fc1f2750SBernard Iremonger 318fc1f2750SBernard Iremonger.. image18_png has been replaced 319fc1f2750SBernard Iremonger 320fc1f2750SBernard Iremonger|ring-modulo2| 321fc1f2750SBernard Iremonger 322fc1f2750SBernard IremongerThis ring contains 12536 entries. 323fc1f2750SBernard Iremonger 324fc1f2750SBernard Iremonger.. note:: 325fc1f2750SBernard Iremonger 326fc1f2750SBernard Iremonger For ease of understanding, we use modulo 65536 operations in the above examples. 327fc1f2750SBernard Iremonger In real execution cases, this is redundant for low efficiency, but is done automatically when the result overflows. 328fc1f2750SBernard Iremonger 329fc1f2750SBernard IremongerThe code always maintains a distance between producer and consumer between 0 and size(ring)-1. 330fc1f2750SBernard IremongerThanks to this property, we can do subtractions between 2 index values in a modulo-32bit base: 331fc1f2750SBernard Iremongerthat's why the overflow of the indexes is not a problem. 332fc1f2750SBernard Iremonger 333fc1f2750SBernard IremongerAt any time, entries and free_entries are between 0 and size(ring)-1, 334fc1f2750SBernard Iremongereven if only the first term of subtraction has overflowed: 335fc1f2750SBernard Iremonger 336fc1f2750SBernard Iremonger.. code-block:: c 337fc1f2750SBernard Iremonger 338fc1f2750SBernard Iremonger uint32_t entries = (prod_tail - cons_head); 339fc1f2750SBernard Iremonger uint32_t free_entries = (mask + cons_tail -prod_head); 340fc1f2750SBernard Iremonger 341fc1f2750SBernard IremongerReferences 342fc1f2750SBernard Iremonger---------- 343fc1f2750SBernard Iremonger 344fc1f2750SBernard 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) 345fc1f2750SBernard Iremonger 346fc1f2750SBernard 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) 347fc1f2750SBernard Iremonger 348fc1f2750SBernard Iremonger * `Linux Lockless Ring Buffer Design <http://lwn.net/Articles/340400/>`_ 349fc1f2750SBernard Iremonger 350fc1f2750SBernard Iremonger.. |ring1| image:: img/ring1.svg 351fc1f2750SBernard Iremonger 352fc1f2750SBernard Iremonger.. |ring-enqueue1| image:: img/ring-enqueue1.svg 353fc1f2750SBernard Iremonger 354fc1f2750SBernard Iremonger.. |ring-enqueue2| image:: img/ring-enqueue2.svg 355fc1f2750SBernard Iremonger 356fc1f2750SBernard Iremonger.. |ring-enqueue3| image:: img/ring-enqueue3.svg 357fc1f2750SBernard Iremonger 358fc1f2750SBernard Iremonger.. |ring-dequeue1| image:: img/ring-dequeue1.svg 359fc1f2750SBernard Iremonger 360fc1f2750SBernard Iremonger.. |ring-dequeue2| image:: img/ring-dequeue2.svg 361fc1f2750SBernard Iremonger 362fc1f2750SBernard Iremonger.. |ring-dequeue3| image:: img/ring-dequeue3.svg 363fc1f2750SBernard Iremonger 364fc1f2750SBernard Iremonger.. |ring-mp-enqueue1| image:: img/ring-mp-enqueue1.svg 365fc1f2750SBernard Iremonger 366fc1f2750SBernard Iremonger.. |ring-mp-enqueue2| image:: img/ring-mp-enqueue2.svg 367fc1f2750SBernard Iremonger 368fc1f2750SBernard Iremonger.. |ring-mp-enqueue3| image:: img/ring-mp-enqueue3.svg 369fc1f2750SBernard Iremonger 370fc1f2750SBernard Iremonger.. |ring-mp-enqueue4| image:: img/ring-mp-enqueue4.svg 371fc1f2750SBernard Iremonger 372fc1f2750SBernard Iremonger.. |ring-mp-enqueue5| image:: img/ring-mp-enqueue5.svg 373fc1f2750SBernard Iremonger 374fc1f2750SBernard Iremonger.. |ring-modulo1| image:: img/ring-modulo1.svg 375fc1f2750SBernard Iremonger 376fc1f2750SBernard Iremonger.. |ring-modulo2| image:: img/ring-modulo2.svg 377