LCOV - code coverage report
Current view: top level - zephyr/sys - spsc_pbuf.h Hit Total Coverage
Test: new.info Lines: 17 31 54.8 %
Date: 2025-01-09 18:14:39

          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 1.14