zephyr/include/sys/winstream.h
Marc Herbert 4990001013 lib/os: clarify that the winstream object does not track reads
Clarify that the reader MUST track the last sequence number read and
that the 'start' offset is not involved in that.

Some pre-conceptions + the sentence "the current state of the stream"
threw me off for a while. Thanks Andy for explaining this to me.

Signed-off-by: Marc Herbert <marc.herbert@intel.com>
2022-02-21 20:59:48 -05:00

96 lines
3.9 KiB
C

/*
* Copyright (c) 2021 Intel Corporation
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_INCLUDE_SYS_WINSTREAM_H_
#define ZEPHYR_INCLUDE_SYS_WINSTREAM_H_
#include <stdint.h>
/** @brief Lockless shared memory byte stream IPC
*
* The sys_winstream utility implements a unidirectional byte stream
* with simple read/write semantics on top of a memory region shared
* by the writer and reader. It requires no locking or
* synchronization mechanisms beyond reliable ordering of memory
* operations, and so is a good fit for use with heterogenous shared
* memory environments (for example, where Zephyr needs to talk to
* other CPUs in the system running their own software).
*
* This object does not keep track of the last sequence number read: the
* reader must keep that state and provide it on every read
* operation. After reaching "steady state", 'end' and 'start' are one
* byte apart because the buffer is always full.
*/
struct sys_winstream {
uint32_t len; /* Length of data[] in bytes */
uint32_t start; /* Index of first valid byte in data[] */
uint32_t end; /* Index of next byte in data[] to write */
uint32_t seq; /* Mod-2^32 index of 'end' since stream init */
uint8_t data[];
};
/** @brief Construct a sys_winstream from a region of memory
*
* This function initializes a sys_winstream in an arbitrarily-sized
* region of memory, returning the resulting object (which is
* guaranteed to be at the same address as the buffer). The memory
* must (obviously) be shared between the reader and writer, and all
* operations to it must be coherent and consistently ordered.
*
* @param buf Pointer to a region of memory to contain the stream
* @param buflen Length of the buffer, must be large enough to contain
* the struct sys_winstream and at least one byte of
* data.
* @return A pointer to an initialized sys_winstream (same address as
* the buf parameter).
*/
static inline struct sys_winstream *sys_winstream_init(void *buf, int buflen)
{
struct sys_winstream *ws = buf, tmp = { .len = buflen - sizeof(*ws) };
*ws = tmp;
return ws;
}
/** @brief Write bytes to a sys_winstream
*
* This function writes the specified number of bytes into the stream.
* It will always return synchronously, it does not block or engage in
* any kind of synchronization beyond memory write ordering. Any
* bytes passed beyond what can be stored in the buffer will be
* silently dropped, but readers can detect their presence via the
* sequence number.
*
* @param ws A sys_winstream to which to write
* @param data Pointer to bytes to be written
* @param len Number of bytes to write
*/
void sys_winstream_write(struct sys_winstream *ws,
const char *data, uint32_t len);
/** @brief Read bytes from a sys_winstream
*
* This function will read bytes from a sys_winstream into a specified
* buffer. It will always return in constant time, it does not block
* or engage in any kind of synchronization beyond memory ordering.
* The number of bytes read into the buffer will be returned, but note
* that it is possible that an underflow can occur if the writer gets
* ahead of our context. That situation can be detected via the
* sequence number returned via a pointer (i.e. if "*seq != old_seq +
* return_value", an underflow occurred and bytes were dropped).
*
* @param ws A sys_winstream from which to read
* @param seq A pointer to an integer containing the last sequence
* number read from the stream, or zero to indicate "start
* of stream". It is updated in place and returned for
* future calls and for detecting underflows.
* @param buf A buffer into which to store the data read
* @param buflen The length of buf in bytes
* @return The number of bytes written into the buffer
*/
uint32_t sys_winstream_read(struct sys_winstream *ws,
uint32_t *seq, char *buf, uint32_t buflen);
#endif /* ZEPHYR_INCLUDE_SYS_WINSTREAM_H_ */