LCOV - code coverage report
Current view: top level - zephyr/sys - spsc_pbuf.h Coverage Total Hit
Test: new.info Lines: 54.8 % 31 17
Test Date: 2025-09-05 16:43:28

            Line data    Source code
       1            0 : /*
       2              :  * Copyright (c) 2022 Nordic Semiconductor ASA
       3              :  *
       4              :  * SPDX-License-Identifier: Apache-2.0
       5              :  */
       6              : 
       7              : #ifndef ZEPHYR_INCLUDE_SYS_SPSC_PBUF_H_
       8              : #define ZEPHYR_INCLUDE_SYS_SPSC_PBUF_H_
       9              : 
      10              : #include <zephyr/cache.h>
      11              : #include <zephyr/devicetree.h>
      12              : 
      13              : #ifdef __cplusplus
      14              : extern "C" {
      15              : #endif
      16              : 
      17              : /**
      18              :  * @brief Single producer, single consumer packet buffer API
      19              :  * @defgroup spsc_buf SPSC (Single producer, single consumer) packet buffer API
      20              :  * @ingroup datastructure_apis
      21              :  * @{
      22              :  */
      23              : 
      24              : /**@defgroup SPSC_PBUF_FLAGS SPSC packet buffer flags
      25              :  * @{
      26              :  */
      27              : 
      28              : /** @brief Flag indicating that cache shall be handled.
      29              :  *
      30              :  * It shall be used only when packet buffer is shared between two cores as on a single
      31              :  * core cache shall not be handled manually because it results in data corruption.
      32              :  */
      33            1 : #define SPSC_PBUF_CACHE BIT(0)
      34              : 
      35              : /** @brief Size of the field which stores maximum utilization. */
      36            1 : #define SPSC_PBUF_UTILIZATION_BITS 24
      37              : 
      38              : /** @brief Offset of the field which stores maximum utilization. */
      39            1 : #define SPSC_PBUF_UTILIZATION_OFFSET 8
      40              : 
      41              : /**@} */
      42              : 
      43              : #if CONFIG_DCACHE_LINE_SIZE != 0
      44              : #define Z_SPSC_PBUF_LOCAL_DCACHE_LINE CONFIG_DCACHE_LINE_SIZE
      45              : #else
      46              : #define Z_SPSC_PBUF_LOCAL_DCACHE_LINE DT_PROP_OR(CPU, d_cache_line_size, 0)
      47              : #endif
      48              : 
      49              : #ifndef CONFIG_SPSC_PBUF_REMOTE_DCACHE_LINE
      50            0 : #define CONFIG_SPSC_PBUF_REMOTE_DCACHE_LINE 0
      51              : #endif
      52              : 
      53              : #define Z_SPSC_PBUF_DCACHE_LINE \
      54              :         MAX(CONFIG_SPSC_PBUF_REMOTE_DCACHE_LINE, Z_SPSC_PBUF_LOCAL_DCACHE_LINE)
      55              : 
      56              : /** @brief Maximum packet length. */
      57            1 : #define SPSC_PBUF_MAX_LEN 0xFF00
      58              : 
      59              : /** @brief First part of packet buffer control block.
      60              :  *
      61              :  * This part contains only data set during the initialization and data touched
      62              :  * by the reader. If packet is shared between to cores then data changed by
      63              :  * the reader should be on different cache line than the data changed by the
      64              :  * writer.
      65              :  */
      66            1 : struct spsc_pbuf_common {
      67            0 :         uint32_t len;           /* Length of data[] in bytes. */
      68            0 :         uint32_t flags;         /* Flags. See @ref SPSC_PBUF_FLAGS */
      69            0 :         uint32_t rd_idx;        /* Index of the first valid byte in data[] */
      70              : };
      71              : 
      72              : /* Padding to fill cache line. */
      73              : #define Z_SPSC_PBUF_PADDING \
      74              :         MAX(0, Z_SPSC_PBUF_DCACHE_LINE - (int)sizeof(struct spsc_pbuf_common))
      75              : 
      76              : /** @brief Remaining part of a packet buffer when cache is used.
      77              :  *
      78              :  * It contains data that is only changed by the writer. A gap is added to ensure
      79              :  * that it is in different cache line than the data changed by the reader.
      80              :  */
      81            1 : struct spsc_pbuf_ext_cache {
      82            0 :         uint8_t reserved[Z_SPSC_PBUF_PADDING];
      83            0 :         uint32_t wr_idx;        /* Index of the first free byte in data[] */
      84            0 :         uint8_t data[];         /* Buffer data. */
      85              : };
      86              : 
      87              : /** @brief Remaining part of a packet buffer when cache is not used. */
      88            1 : struct spsc_pbuf_ext_nocache {
      89            0 :         uint32_t wr_idx;        /* Index of the first free byte in data[] */
      90            0 :         uint8_t data[];         /* Buffer data. */
      91              : };
      92              : 
      93              : /**
      94              :  * @brief Single producer, single consumer packet buffer
      95              :  *
      96              :  * The SPSC packet buffer implements lightweight unidirectional packet buffer
      97              :  * with read/write semantics on top of a memory region shared
      98              :  * by the reader and writer. It optionally embeds cache and memory barrier
      99              :  * management to ensure correct data access.
     100              :  *
     101              :  * This structure supports single writer and reader. Data stored in the buffer
     102              :  * is encapsulated to a message (with length header).
     103              :  *
     104              :  */
     105            1 : struct spsc_pbuf {
     106            0 :         struct spsc_pbuf_common common;
     107              :         union {
     108            0 :                 struct spsc_pbuf_ext_cache cache;
     109            0 :                 struct spsc_pbuf_ext_nocache nocache;
     110            0 :         } ext;
     111              : };
     112              : 
     113              : /** @brief Get buffer capacity.
     114              :  *
     115              :  * This value is the amount of data that is dedicated for storing packets. Since
     116              :  * each packet is prefixed with 2 byte length header, longest possible packet is
     117              :  * less than that.
     118              :  *
     119              :  * @param pb    A buffer.
     120              :  *
     121              :  * @return Packet buffer capacity.
     122              :  */
     123            1 : static inline uint32_t spsc_pbuf_capacity(struct spsc_pbuf *pb)
     124              : {
     125              :         return pb->common.len - sizeof(uint32_t);
     126              : }
     127              : 
     128              : /**
     129              :  * @brief Initialize the packet buffer.
     130              :  *
     131              :  * This function initializes the packet buffer on top of a dedicated
     132              :  * memory region.
     133              :  *
     134              :  * @param buf                   Pointer to a memory region on which buffer is
     135              :  *                              created. When cache is used it must be aligned to
     136              :  *                              Z_SPSC_PBUF_DCACHE_LINE, otherwise it must
     137              :  *                              be 32 bit word aligned.
     138              :  * @param blen                  Length of the buffer. Must be large enough to
     139              :  *                              contain the internal structure and at least two
     140              :  *                              bytes of data (one is reserved for written
     141              :  *                              messages length).
     142              :  * @param flags                 Option flags. See @ref SPSC_PBUF_FLAGS.
     143              :  * @retval struct spsc_pbuf*    Pointer to the created buffer. The pointer
     144              :  *                              points to the same address as buf.
     145              :  * @retval NULL                 Invalid buffer alignment.
     146              :  */
     147            1 : struct spsc_pbuf *spsc_pbuf_init(void *buf, size_t blen, uint32_t flags);
     148              : 
     149              : /**
     150              :  * @brief Write specified amount of data to the packet buffer.
     151              :  *
     152              :  * It combines @ref spsc_pbuf_alloc and @ref spsc_pbuf_commit into a single call.
     153              :  *
     154              :  * @param pb    A buffer to which to write.
     155              :  * @param buf   Pointer to the data to be written to the buffer.
     156              :  * @param len   Number of bytes to be written to the buffer. Must be positive
     157              :  *              but less than @ref SPSC_PBUF_MAX_LEN.
     158              :  * @retval int  Number of bytes written, negative error code on fail.
     159              :  *              -EINVAL, if len == 0.
     160              :  *              -ENOMEM, if len is bigger than the buffer can fit.
     161              :  */
     162            1 : int spsc_pbuf_write(struct spsc_pbuf *pb, const char *buf, uint16_t len);
     163              : 
     164              : /**
     165              :  * @brief Allocate space in the packet buffer.
     166              :  *
     167              :  * This function attempts to allocate @p len bytes of continuous memory within
     168              :  * the packet buffer. An internal padding is added at the end of the buffer, if
     169              :  * wrapping occurred during allocation. Apart from padding, allocation does not
     170              :  * change the state of the buffer so if after allocation packet is not needed
     171              :  * a commit is not needed.
     172              :  *
     173              :  * Allocated buffer must be committed (@ref spsc_pbuf_commit) to make the packet
     174              :  * available for reading.
     175              :  *
     176              :  * Packet buffer ensures that allocated buffers are 32 bit word aligned.
     177              :  *
     178              :  * @note If data cache is used, it is the user responsibility to write back the
     179              :  * new data.
     180              :  *
     181              :  * @param[in]  pb       A buffer to which to write.
     182              :  * @param[in]  len      Allocation length. Must be positive. If less than @ref SPSC_PBUF_MAX_LEN
     183              :  *                      then if requested length cannot be allocated, an attempt to allocate
     184              :  *                      largest possible is performed (which may include adding wrap padding).
     185              :  *                      If @ref SPSC_PBUF_MAX_LEN is used then an attempt to allocate largest
     186              :  *                      buffer without applying wrap padding is performed.
     187              :  * @param[out] buf      Location where buffer address is written on successful allocation.
     188              :  *
     189              :  * @retval non-negative Amount of space that got allocated. Can be equal or smaller than %p len.
     190              :  * @retval -EINVAL if @p len is forbidden.
     191              :  */
     192            1 : int spsc_pbuf_alloc(struct spsc_pbuf *pb, uint16_t len, char **buf);
     193              : 
     194              : /**
     195              :  * @brief Commit packet to the buffer.
     196              :  *
     197              :  * Commit a packet which was previously allocated (@ref spsc_pbuf_alloc).
     198              :  * If cache is used, cache writeback is performed on the written data.
     199              :  *
     200              :  * @param pb    A buffer to which to write.
     201              :  * @param len   Packet length. Must be equal or less than the length used for allocation.
     202              :  */
     203            1 : void spsc_pbuf_commit(struct spsc_pbuf *pb, uint16_t len);
     204              : 
     205              : /**
     206              :  * @brief Read specified amount of data from the packet buffer.
     207              :  *
     208              :  * Single read allows to read the message send by the single write.
     209              :  * The provided %p buf must be big enough to store the whole message.
     210              :  *
     211              :  * It combines @ref spsc_pbuf_claim and @ref spsc_pbuf_free into a single call.
     212              :  *
     213              :  * @param pb            A buffer from which data will be read.
     214              :  * @param buf           Data pointer to which read data will be written.
     215              :  *                      If NULL, len of stored message is returned.
     216              :  * @param len           Number of bytes to be read from the buffer.
     217              :  * @retval int          Bytes read, negative error code on fail.
     218              :  *                      Bytes to be read, if buf == NULL.
     219              :  *                      -ENOMEM, if message can not fit in provided buf.
     220              :  *                      -EAGAIN, if not whole message is ready yet.
     221              :  */
     222            1 : int spsc_pbuf_read(struct spsc_pbuf *pb, char *buf, uint16_t len);
     223              : 
     224              : /**
     225              :  * @brief Claim packet from the buffer.
     226              :  *
     227              :  * It claims a single packet from the buffer in the order of the commitment
     228              :  * by the @ref spsc_pbuf_commit function. The first committed packet will be claimed first.
     229              :  * The returned buffer is 32 bit word aligned and points to the continuous memory.
     230              :  * Claimed packet must be freed using the @ref spsc_pbuf_free function.
     231              :  *
     232              :  * @note If data cache is used, cache is invalidate on the packet.
     233              :  *
     234              :  * @param[in] pb        A buffer from which packet will be claimed.
     235              :  * @param[in,out] buf   A location where claimed packet address is written.
     236              :  *                      It is 32 bit word aligned and points to the continuous memory.
     237              :  *
     238              :  * @retval 0 No packets in the buffer.
     239              :  * @retval positive packet length.
     240              :  */
     241            1 : uint16_t spsc_pbuf_claim(struct spsc_pbuf *pb, char **buf);
     242              : 
     243              : /**
     244              :  * @brief Free the packet to the buffer.
     245              :  *
     246              :  * Packet must be claimed (@ref spsc_pbuf_claim) before it can be freed.
     247              :  *
     248              :  * @param pb    A packet buffer from which packet was claimed.
     249              :  * @param len   Claimed packet length.
     250              :  */
     251            1 : void spsc_pbuf_free(struct spsc_pbuf *pb, uint16_t len);
     252              : 
     253              : /**
     254              :  * @brief Get maximum utilization of the packet buffer.
     255              :  *
     256              :  * Function can be used to tune the buffer size. Feature is enabled by
     257              :  * CONFIG_SPSC_PBUF_UTILIZATION. Utilization is updated by the consumer.
     258              :  *
     259              :  * @param pb    A packet buffer.
     260              :  *
     261              :  * @retval -ENOTSUP     Feature not enabled.
     262              :  * @retval non-negative Maximum utilization.
     263              :  */
     264            1 : int spsc_pbuf_get_utilization(struct spsc_pbuf *pb);
     265              : /**
     266              :  * @}
     267              :  */
     268              : 
     269              : #ifdef __cplusplus
     270              : }
     271              : #endif
     272              : 
     273              : #endif /* ZEPHYR_INCLUDE_SYS_SPSC_PBUF_H_ */
        

Generated by: LCOV version 2.0-1