doc: misc: Add documentation for MPSC Packet Buffer
Add documentation for Multi Producer Single Consumer Packet Buffer. Signed-off-by: Krzysztof Chruscinski <krzysztof.chruscinski@nordicsemi.no>
This commit is contained in:
parent
345d12e8e0
commit
9c6b159d68
2 changed files with 148 additions and 0 deletions
|
@ -30,5 +30,6 @@ needed will be provided by the user.
|
|||
|
||||
slist.rst
|
||||
dlist.rst
|
||||
mpsc_pbuf.rst
|
||||
rbtree.rst
|
||||
ring_buffers.rst
|
||||
|
|
147
doc/reference/data_structures/mpsc_pbuf.rst
Normal file
147
doc/reference/data_structures/mpsc_pbuf.rst
Normal file
|
@ -0,0 +1,147 @@
|
|||
.. _mpsc_pbuf:
|
||||
|
||||
Multi Producer Single Consumer Packet Buffer
|
||||
============================================
|
||||
|
||||
A :dfn:`Multi Producer Single Consumer Packet Buffer (MPSC_PBUF)` is a circular
|
||||
buffer, whose contents are stored in first-in-first-out order. Variable size
|
||||
packets are stored in the buffer. Packet buffer works under assumption that there
|
||||
is a single context that consumes the data. However, it is possible that another
|
||||
context may interfere to flush the data and never come back (panic case).
|
||||
Packet is produced in two steps: first requested amount of data is allocated,
|
||||
producer fills the data and commits it. Consuming a packet is also performed in
|
||||
two steps: consumer claims the packet, gets pointer to it and length and later
|
||||
on packet is freed. This approach reduces memory copying.
|
||||
|
||||
A :dfn:`MPSC Packet Buffer` has the following key properties:
|
||||
|
||||
* Allocate, commit scheme used for packet producing.
|
||||
* Claim, free scheme used for packet consuming.
|
||||
* Allocator ensures that continue memory of requested length is allocated.
|
||||
* Following policies can be applied when requested space cannot be allocated:
|
||||
|
||||
* **Overwrite** - oldest entries are dropped until requested amount of memory can
|
||||
be allocated. For each dropped packet user callback is called.
|
||||
* **No overwrite** - When requested amount of space cannot be allocated,
|
||||
allocation fails.
|
||||
* Dedicated, optimized API for storing short packets.
|
||||
* Allocation with timeout.
|
||||
|
||||
Internals
|
||||
---------
|
||||
|
||||
Each packet in the buffer contains ``MPSC_PBUF`` specific header which is used
|
||||
for internal management. Header consists of 2 bit flags. In order to optimize
|
||||
memory usage, header can be added on top of the user header using
|
||||
:c:macro:`MPSC_PBUF_HDR` and remaining bits in the first word can be application
|
||||
specific. Header consists of following flags:
|
||||
|
||||
* valid - bit set to one when packet contains valid user packet
|
||||
* busy - bit set when packet is being consumed (claimed but not free)
|
||||
|
||||
Header state:
|
||||
|
||||
+-------+------+----------------------+
|
||||
| valid | busy | description |
|
||||
+-------+------+----------------------+
|
||||
| 0 | 0 | space is free |
|
||||
+-------+------+----------------------+
|
||||
| 1 | 0 | valid packet |
|
||||
+-------+------+----------------------+
|
||||
| 1 | 1 | claimed valid packet |
|
||||
+-------+------+----------------------+
|
||||
| 0 | 1 | internal skip packet |
|
||||
+-------+------+----------------------+
|
||||
|
||||
Packet buffer space contains free space, valid user packets and internal skip
|
||||
packets. Internal skip packets indicates padding, e.g. at the of the buffer.
|
||||
|
||||
Allocation
|
||||
^^^^^^^^^^
|
||||
|
||||
Using pairs for read and write indexes, available space is determined. If
|
||||
space can be allocated, temporary write index is moved and pointer to a space
|
||||
witing buffer is returned. Packet header is reset. If allocation required
|
||||
wrapping of the write index, a skip packet is added to the end of buffer. If
|
||||
space cannot be allocated and overwrite is disabled then ``NULL`` pointer is
|
||||
returned or context blocks if allocation was with timeout.
|
||||
|
||||
Allocation with overwrite
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
If overwrite is enabled, oldest packets are dropped until requested amount of
|
||||
space can be allocated. When packets are dropped ``busy`` flag is checked in the
|
||||
header to ensure that currently consumed packet is not overwritten. In that case,
|
||||
skip packet is added before busy packet and packets following the busy packet
|
||||
are dropped. When busy packet is being freed, such situation is detected and
|
||||
packet is converted to skip packet to avoid double processing.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
Packet header definition
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Packet header details can be found in :zephyr_file:`include/sys/mpsc_packet.h`.
|
||||
API functions can be found in :zephyr_file:`include/sys/mpsc_pbuf.h`. Headers
|
||||
are split to avoid include spam when declaring the packet.
|
||||
|
||||
User header structure must start with internal header:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
#include <sys/mpsc_packet.h>
|
||||
|
||||
struct foo_header {
|
||||
MPSC_PBUF_HDR;
|
||||
uint32_t length: 32 - MPSC_PBUF_HDR_BITS;
|
||||
};
|
||||
|
||||
Packet buffer configuration
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Configuration structure contains buffer details, configuration flags and
|
||||
callbacks. Following callbacks are used by the packet buffer:
|
||||
|
||||
* Drop notification - callback called whenever a packet is dropped due to
|
||||
overwrite.
|
||||
* Get packet length - callback to determine packet length
|
||||
|
||||
Packet producing
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
Standard, two step method:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
foo_packet *packet = mpsc_pbuf_alloc(buffer, len, K_NO_WAIT);
|
||||
|
||||
fill_data(packet);
|
||||
|
||||
mpsc_pbuf_commit(buffer, packet);
|
||||
|
||||
Performance optimized storing of small packets:
|
||||
|
||||
* 32 bit word packet
|
||||
* 32 bit word with pointer packet
|
||||
|
||||
Note that since packets are written by value, they should already contain
|
||||
``valid`` bit set in the header.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
mpsc_pbuf_put_word(buffer, data);
|
||||
mpsc_pbuf_put_word_ext(buffer, data, ptr);
|
||||
|
||||
Packet consuming
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
Two step method:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
foo_packet *packet = mpsc_pbuf_claim(buffer);
|
||||
|
||||
process(packet);
|
||||
|
||||
mpsc_pbuf_free(buffer, packet);
|
Loading…
Add table
Add a link
Reference in a new issue