1.. _mpsc_pbuf: 2 3Multi Producer Single Consumer Packet Buffer 4============================================ 5 6A :dfn:`Multi Producer Single Consumer Packet Buffer (MPSC_PBUF)` is a circular 7buffer, whose contents are stored in first-in-first-out order. Variable size 8packets are stored in the buffer. Packet buffer works under assumption that there 9is a single context that consumes the data. However, it is possible that another 10context may interfere to flush the data and never come back (panic case). 11Packet is produced in two steps: first requested amount of data is allocated, 12producer fills the data and commits it. Consuming a packet is also performed in 13two steps: consumer claims the packet, gets pointer to it and length and later 14on packet is freed. This approach reduces memory copying. 15 16A :dfn:`MPSC Packet Buffer` has the following key properties: 17 18* Allocate, commit scheme used for packet producing. 19* Claim, free scheme used for packet consuming. 20* Allocator ensures that contiguous memory of requested length is allocated. 21* Following policies can be applied when requested space cannot be allocated: 22 23 * **Overwrite** - oldest entries are dropped until requested amount of memory can 24 be allocated. For each dropped packet user callback is called. 25 * **No overwrite** - When requested amount of space cannot be allocated, 26 allocation fails. 27* Dedicated, optimized API for storing short packets. 28* Allocation with timeout. 29 30Internals 31--------- 32 33Each packet in the buffer contains ``MPSC_PBUF`` specific header which is used 34for internal management. Header consists of 2 bit flags. In order to optimize 35memory usage, header can be added on top of the user header using 36:c:macro:`MPSC_PBUF_HDR` and remaining bits in the first word can be application 37specific. Header consists of following flags: 38 39* valid - bit set to one when packet contains valid user packet 40* busy - bit set when packet is being consumed (claimed but not free) 41 42Header state: 43 44+-------+------+----------------------+ 45| valid | busy | description | 46+-------+------+----------------------+ 47| 0 | 0 | space is free | 48+-------+------+----------------------+ 49| 1 | 0 | valid packet | 50+-------+------+----------------------+ 51| 1 | 1 | claimed valid packet | 52+-------+------+----------------------+ 53| 0 | 1 | internal skip packet | 54+-------+------+----------------------+ 55 56Packet buffer space contains free space, valid user packets and internal skip 57packets. Internal skip packets indicates padding, e.g. at the of the buffer. 58 59Allocation 60^^^^^^^^^^ 61 62Using pairs for read and write indexes, available space is determined. If 63space can be allocated, temporary write index is moved and pointer to a space 64within buffer is returned. Packet header is reset. If allocation required 65wrapping of the write index, a skip packet is added to the end of buffer. If 66space cannot be allocated and overwrite is disabled then ``NULL`` pointer is 67returned or context blocks if allocation was with timeout. 68 69Allocation with overwrite 70^^^^^^^^^^^^^^^^^^^^^^^^^ 71 72If overwrite is enabled, oldest packets are dropped until requested amount of 73space can be allocated. When packets are dropped ``busy`` flag is checked in the 74header to ensure that currently consumed packet is not overwritten. In that case, 75skip packet is added before busy packet and packets following the busy packet 76are dropped. When busy packet is being freed, such situation is detected and 77packet is converted to skip packet to avoid double processing. 78 79Usage 80----- 81 82Packet header definition 83^^^^^^^^^^^^^^^^^^^^^^^^ 84 85Packet header details can be found in :zephyr_file:`include/zephyr/sys/mpsc_packet.h`. 86API functions can be found in :zephyr_file:`include/zephyr/sys/mpsc_pbuf.h`. Headers 87are split to avoid include spam when declaring the packet. 88 89User header structure must start with internal header: 90 91.. code-block:: c 92 93 #include <zephyr/sys/mpsc_packet.h> 94 95 struct foo_header { 96 MPSC_PBUF_HDR; 97 uint32_t length: 32 - MPSC_PBUF_HDR_BITS; 98 }; 99 100Packet buffer configuration 101^^^^^^^^^^^^^^^^^^^^^^^^^^^ 102 103Configuration structure contains buffer details, configuration flags and 104callbacks. Following callbacks are used by the packet buffer: 105 106* Drop notification - callback called whenever a packet is dropped due to 107 overwrite. 108* Get packet length - callback to determine packet length 109 110Packet producing 111^^^^^^^^^^^^^^^^ 112 113Standard, two step method: 114 115.. code-block:: c 116 117 foo_packet *packet = mpsc_pbuf_alloc(buffer, len, K_NO_WAIT); 118 119 fill_data(packet); 120 121 mpsc_pbuf_commit(buffer, packet); 122 123Performance optimized storing of small packets: 124 125* 32 bit word packet 126* 32 bit word with pointer packet 127 128Note that since packets are written by value, they should already contain 129``valid`` bit set in the header. 130 131.. code-block:: c 132 133 mpsc_pbuf_put_word(buffer, data); 134 mpsc_pbuf_put_word_ext(buffer, data, ptr); 135 136Packet consuming 137^^^^^^^^^^^^^^^^ 138 139Two step method: 140 141.. code-block:: c 142 143 foo_packet *packet = mpsc_pbuf_claim(buffer); 144 145 process(packet); 146 147 mpsc_pbuf_free(buffer, packet); 148