text: /* ring_buffer.h: Simple ring buffer API */
  
  /*
   * Copyright (c) 2015 Intel Corporation
   *
   * SPDX-License-Identifier: Apache-2.0
   */
  /** @file */
  
  #ifndef ZEPHYR_INCLUDE_RING_BUFFER_H_
  #define ZEPHYR_INCLUDE_RING_BUFFER_H_
  
  #include <kernel.h>
  #include <misc/util.h>
  #include <errno.h>
  #include <string.h>
  
  #ifdef __cplusplus
  extern "C" {
  #endif
  
  #define SIZE32_OF(x) (sizeof((x))/sizeof(u32_t))
  
  /**
   * @brief A structure to represent a ring buffer
   */
  struct ring_buf {
  	u32_t head;	 /**< Index in buf for the head element */
  	u32_t tail;	 /**< Index in buf for the tail element */
  	union ring_buf_misc {
  		struct ring_buf_misc_item_mode {
  			u32_t dropped_put_count; /**< Running tally of the
  						   * number of failed put
  						   * attempts.
  						   */
  		} item_mode;
  		struct ring_buf_misc_byte_mode {
  			u32_t tmp_tail;
  			u32_t tmp_head;
  		} byte_mode;
  	} misc;
  	u32_t size;   /**< Size of buf in 32-bit chunks */
  
  	union ring_buf_buffer {
  		u32_t *buf32;	 /**< Memory region for stored entries */
  		u8_t *buf8;
  	} buf;
  	u32_t mask;   /**< Modulo mask if size is a power of 2 */
  };
  
  /**
   * @defgroup ring_buffer_apis Ring Buffer APIs
   * @ingroup kernel_apis
   * @{
   */
  
  /**
   * @brief Statically define and initialize a high performance ring buffer.
   *
   * This macro establishes a ring buffer whose size must be a power of 2;
   * that is, the ring buffer contains 2^pow 32-bit words, where @a pow is
   * the specified ring buffer size exponent. A high performance ring buffer
   * doesn't require the use of modulo arithmetic operations to maintain itself.
   *
   * The ring buffer can be accessed outside the module where it is defined
   * using:
   *
   * @code extern struct ring_buf <name>; @endcode
   *
   * @param name Name of the ring buffer.
   * @param pow Ring buffer size exponent.
   */
  #define RING_BUF_ITEM_DECLARE_POW2(name, pow) \
  	static u32_t _ring_buffer_data_##name[1 << (pow)]; \
  	struct ring_buf name = { \
  		.size = (1 << (pow)), \
  		.mask = (1 << (pow)) - 1, \
  		.buf = { .buf32 = _ring_buffer_data_##name } \
  	}
  
  /** @deprecated Renamed to RING_BUF_ITEM_DECLARE_POW2. */
  #define SYS_RING_BUF_DECLARE_POW2(name, pow) \
  	__DEPRECATED_MACRO RING_BUF_ITEM_DECLARE_POW2(name, pow)
  
  /**
   * @brief Statically define and initialize a standard ring buffer.
   *
   * This macro establishes a ring buffer of an arbitrary size. A standard
   * ring buffer uses modulo arithmetic operations to maintain itself.
   *
   * The ring buffer can be accessed outside the module where it is defined
   * using:
   *
   * @code extern struct ring_buf <name>; @endcode
   *
   * @param name Name of the ring buffer.
   * @param size32 Size of ring buffer (in 32-bit words).
   */
  #define RING_BUF_ITEM_DECLARE_SIZE(name, size32) \
  	static u32_t _ring_buffer_data_##name[size32]; \
  	struct ring_buf name = { \
  		.size = size32, \
  		.buf = { .buf32 = _ring_buffer_data_##name} \
  	}
  
  /** @deprecated Renamed to RING_BUF_ITEM_DECLARE_SIZE. */
  #define SYS_RING_BUF_DECLARE_SIZE(name, size32) \
  	__DEPRECATED_MACRO RING_BUF_ITEM_DECLARE_SIZE(name, size32)
  
  /**
   * @brief Statically define and initialize a ring buffer for byte data.
   *
   * This macro establishes a ring buffer of an arbitrary size.
   *
   * The ring buffer can be accessed outside the module where it is defined
   * using:
   *
   * @code extern struct ring_buf <name>; @endcode
   *
   * @param name  Name of the ring buffer.
   * @param size8 Size of ring buffer (in bytes).
   */
  #define RING_BUF_DECLARE(name, size8) \
  	static u8_t _ring_buffer_data_##name[size8]; \
  	struct ring_buf name = { \
  		.size = size8, \
  		.buf = { .buf8 = _ring_buffer_data_##name} \
  	}
  
  
  /**
   * @brief Initialize a ring buffer.
   *
   * This routine initializes a ring buffer, prior to its first use. It is only
   * used for ring buffers not defined using RING_BUF_DECLARE,
   * RING_BUF_ITEM_DECLARE_POW2 or RING_BUF_ITEM_DECLARE_SIZE.
   *
   * Setting @a size to a power of 2 establishes a high performance ring buffer
   * that doesn't require the use of modulo arithmetic operations to maintain
   * itself.
   *
   * @param buf Address of ring buffer.
   * @param size Ring buffer size (in 32-bit words or bytes).
   * @param data Ring buffer data area (u32_t data[size] or u8_t data[size] for
   *	       bytes mode).
   */
  static inline void ring_buf_init(struct ring_buf *buf, u32_t size, void *data)
  {
  	memset(buf, 0, sizeof(struct ring_buf));
  	buf->size = size;
  	buf->buf.buf32 = data;
  	if (is_power_of_two(size)) {
  		buf->mask = size - 1;
  	} else {
  		buf->mask = 0;
  	}
  }
  
  /** @deprecated Renamed to ring_buf_init. */
  __deprecated static inline void sys_ring_buf_init(struct ring_buf *buf,
  						  u32_t size, u32_t *data)
  {
  	ring_buf_init(buf, size, data);
  }
  
  /** @brief Determine free space based on ring buffer parameters.
   *
   * @note Function for internal use.
   *
   * @param size Ring buffer size.
   * @param head Ring buffer head.
   * @param tail Ring buffer tail.
   *
   *  @return Ring buffer free space (in 32-bit words or bytes).
   */
  static inline int z_ring_buf_custom_space_get(u32_t size, u32_t head,
  					      u32_t tail)
  {
  	if (tail < head) {
  		return head - tail - 1;
  	}
  
  	/* buf->tail > buf->head */
  	return (size - tail) + head - 1;
  }
  
  /**
   * @brief Determine if a ring buffer is empty.
   *
   * @param buf Address of ring buffer.
   *
   * @return 1 if the ring buffer is empty, or 0 if not.
   */
  static inline int ring_buf_is_empty(struct ring_buf *buf)
  {
  	return (buf->head == buf->tail);
  }
  /** @deprecated Renamed to ring_buf_is_empty. */
  __deprecated static inline int sys_ring_buf_is_empty(struct ring_buf *buf)
  {
  	return ring_buf_is_empty(buf);
  }
  
  /**
   * @brief Determine free space in a ring buffer.
   *
   * @param buf Address of ring buffer.
   *
   * @return Ring buffer free space (in 32-bit words or bytes).
   */
  static inline int ring_buf_space_get(struct ring_buf *buf)
  {
  	return z_ring_buf_custom_space_get(buf->size, buf->head, buf->tail);
  }
  
  /** @deprecated Renamed to ring_buf_space_get. */
  __deprecated static inline int sys_ring_buf_space_get(struct ring_buf *buf)
  {
  	return ring_buf_space_get(buf);
  }
  
  /**
   * @brief Write a data item to a ring buffer.
   *
   * This routine writes a data item to ring buffer @a buf. The data item
   * is an array of 32-bit words (from zero to 1020 bytes in length),
   * coupled with a 16-bit type identifier and an 8-bit integer value.
   *
   * @warning
   * Use cases involving multiple writers to the ring buffer must prevent
   * concurrent write operations, either by preventing all writers from
   * being preempted or by using a mutex to govern writes to the ring buffer.
   *
   * @param buf Address of ring buffer.
   * @param type Data item's type identifier (application specific).
   * @param value Data item's integer value (application specific).
   * @param data Address of data item.
   * @param size32 Data item size (number of 32-bit words).
   *
   * @retval 0 Data item was written.
   * @retval -EMSGSIZE Ring buffer has insufficient free space.
   */
  int ring_buf_item_put(struct ring_buf *buf, u16_t type, u8_t value,
  		      u32_t *data, u8_t size32);
  
  
  /** @deprecated Renamed to ring_buf_item_put. */
  __deprecated static inline int sys_ring_buf_put(struct ring_buf *buf,
  						u16_t type, u8_t value,
  						u32_t *data, u8_t size32)
  {
  	return ring_buf_item_put(buf, type, value, data, size32);
  }
  
  /**
   * @brief Read a data item from a ring buffer.
   *
   * This routine reads a data item from ring buffer @a buf. The data item
   * is an array of 32-bit words (up to 1020 bytes in length),
   * coupled with a 16-bit type identifier and an 8-bit integer value.
   *
   * @warning
   * Use cases involving multiple reads of the ring buffer must prevent
   * concurrent read operations, either by preventing all readers from
   * being preempted or by using a mutex to govern reads to the ring buffer.
   *
   * @param buf Address of ring buffer.
   * @param type Area to store the data item's type identifier.
   * @param value Area to store the data item's integer value.
   * @param data Area to store the data item.
   * @param size32 Size of the data item storage area (number of 32-bit chunks).
   *
   * @retval 0 Data item was fetched; @a size32 now contains the number of
   *         32-bit words read into data area @a data.
   * @retval -EAGAIN Ring buffer is empty.
   * @retval -EMSGSIZE Data area @a data is too small; @a size32 now contains
   *         the number of 32-bit words needed.
   */
  int ring_buf_item_get(struct ring_buf *buf, u16_t *type, u8_t *value,
  		      u32_t *data, u8_t *size32);
  
  /** @deprecated Renamed to ring_buf_item_get. */
  __deprecated static inline int sys_ring_buf_get(struct ring_buf *buf,
  						u16_t *type, u8_t *value,
  						u32_t *data, u8_t *size32)
  {
  	return ring_buf_item_get(buf, type, value, data, size32);
  }
  
  /**
   * @brief Allocate buffer for writing data to a ring buffer.
   *
   * With this routine, memory copying can be reduced since internal ring buffer
   * can be used directly by the user. Once data is written to allocated area
   * number of bytes written can be confirmed (see @ref ring_buf_put_finish).
   *
   * @warning
   * Use cases involving multiple writers to the ring buffer must prevent
   * concurrent write operations, either by preventing all writers from
   * being preempted or by using a mutex to govern writes to the ring buffer.
   *
   * @warning
   * Ring buffer instance should not mix byte access and item access
   * (calls prefixed with ring_buf_item_).
   *
   * @param[in]  buf  Address of ring buffer.
   * @param[out] data Pointer to the address. It is set to a location within
   *		    ring buffer.
   * @param[in]  size Requested allocation size (in bytes).
   *
   * @return Size of allocated buffer which can be smaller than requested if
   *	   there is not enough free space or buffer wraps.
   */
  u32_t ring_buf_put_claim(struct ring_buf *buf, u8_t **data, u32_t size);
  
  /**
   * @brief Indicate number of bytes written to allocated buffers.
   *
   * @warning
   * Use cases involving multiple writers to the ring buffer must prevent
   * concurrent write operations, either by preventing all writers from
   * being preempted or by using a mutex to govern writes to the ring buffer.
   *
   * @warning
   * Ring buffer instance should not mix byte access and item access
   * (calls prefixed with ring_buf_item_).
   *
   * @param  buf  Address of ring buffer.
   * @param  size Number of valid bytes in the allocated buffers.
   *
   * @retval 0 Successful operation.
   * @retval -EINVAL Provided @a size exceeds free space in the ring buffer.
   */
  int ring_buf_put_finish(struct ring_buf *buf, u32_t size);
  
  /**
   * @brief Write (copy) data to a ring buffer.
   *
   * This routine writes data to a ring buffer @a buf.
   *
   * @warning
   * Use cases involving multiple writers to the ring buffer must prevent
   * concurrent write operations, either by preventing all writers from
   * being preempted or by using a mutex to govern writes to the ring buffer.
   *
   * @warning
   * Ring buffer instance should not mix byte access and item access
   * (calls prefixed with ring_buf_item_).
   *
   * @param buf Address of ring buffer.
   * @param data Address of data.
   * @param size Data size (in bytes).
   *
   * @retval Number of bytes written.
   */
  u32_t ring_buf_put(struct ring_buf *buf, const u8_t *data, u32_t size);
  
  /**
   * @brief Get address of a valid data in a ring buffer.
   *
   * With this routine, memory copying can be reduced since internal ring buffer
   * can be used directly by the user. Once data is processed it can be freed
   * using @ref ring_buf_get_finish.
   *
   * @warning
   * Use cases involving multiple reads of the ring buffer must prevent
   * concurrent read operations, either by preventing all readers from
   * being preempted or by using a mutex to govern reads to the ring buffer.
   *
   * @warning
   * Ring buffer instance should not mix byte access and item access
   * (calls prefixed with ring_buf_item_).
   *
   * @param[in]  buf  Address of ring buffer.
   * @param[out] data Pointer to the address. It is set to a location within
   *		    ring buffer.
   * @param[in]  size Requested size (in bytes).
   *
   * @return Number of valid bytes in the provided buffer which can be smaller
   *	   than requested if there is not enough free space or buffer wraps.
   */
  u32_t ring_buf_get_claim(struct ring_buf *buf, u8_t **data, u32_t size);
  
  /**
   * @brief Indicate number of bytes read from claimed buffer.
   *
   * @warning
   * Use cases involving multiple reads of the ring buffer must prevent
   * concurrent read operations, either by preventing all readers from
   * being preempted or by using a mutex to govern reads to the ring buffer.
   *
   * @warning
   * Ring buffer instance should not mix byte access and  item mode
   * (calls prefixed with ring_buf_item_).
   *
   * @param  buf  Address of ring buffer.
   * @param  size Number of bytes that can be freed.
   *
   * @retval 0 Successful operation.
   * @retval -EINVAL Provided @a size exceeds valid bytes in the ring buffer.
   */
  int ring_buf_get_finish(struct ring_buf *buf, u32_t size);
  
  /**
   * @brief Read data from a ring buffer.
   *
   * This routine reads data from a ring buffer @a buf.
   *
   * @warning
   * Use cases involving multiple reads of the ring buffer must prevent
   * concurrent read operations, either by preventing all readers from
   * being preempted or by using a mutex to govern reads to the ring buffer.
   *
   * @warning
   * Ring buffer instance should not mix byte access and  item mode
   * (calls prefixed with ring_buf_item_).
   *
   * @param buf  Address of ring buffer.
   * @param data Address of the output buffer.
   * @param size Data size (in bytes).
   *
   * @retval Number of bytes written to the output buffer.
   */
  u32_t ring_buf_get(struct ring_buf *buf, u8_t *data, u32_t size);
  
  /**
   * @}
   */
  
  #ifdef __cplusplus
  }
  #endif
  
  #endif /* ZEPHYR_INCLUDE_RING_BUFFER_H_ */
  