1 /*
2  * Copyright (c) 2021 Intel Corporation
3  * SPDX-License-Identifier: Apache-2.0
4  */
5 #ifndef ZEPHYR_INCLUDE_SYS_WINSTREAM_H_
6 #define ZEPHYR_INCLUDE_SYS_WINSTREAM_H_
7 
8 #include <stdint.h>
9 
10 /** @brief Lockless shared memory byte stream IPC
11  *
12  * The sys_winstream utility implements a unidirectional byte stream
13  * with simple read/write semantics on top of a memory region shared
14  * by the writer and reader.  It requires no locking or
15  * synchronization mechanisms beyond reliable ordering of memory
16  * operations, and so is a good fit for use with heterogeneous shared
17  * memory environments (for example, where Zephyr needs to talk to
18  * other CPUs in the system running their own software).
19  *
20  * This object does not keep track of the last sequence number read: the
21  * reader must keep that state and provide it on every read
22  * operation. After reaching "steady state", 'end' and 'start' are one
23  * byte apart because the buffer is always full.
24  */
25 struct sys_winstream {
26 	uint32_t len;   /* Length of data[] in bytes */
27 	uint32_t start; /* Index of first valid byte in data[] */
28 	uint32_t end;   /* Index of next byte in data[] to write */
29 	uint32_t seq;   /* Mod-2^32 index of 'end' since stream init */
30 	uint8_t data[];
31 };
32 
33 /** @brief Construct a sys_winstream from a region of memory
34  *
35  * This function initializes a sys_winstream in an arbitrarily-sized
36  * region of memory, returning the resulting object (which is
37  * guaranteed to be at the same address as the buffer).  The memory
38  * must (obviously) be shared between the reader and writer, and all
39  * operations to it must be coherent and consistently ordered.
40  *
41  * @param buf Pointer to a region of memory to contain the stream
42  * @param buflen Length of the buffer, must be large enough to contain
43  *               the struct sys_winstream and at least one byte of
44  *               data.
45  * @return A pointer to an initialized sys_winstream (same address as
46  *         the buf parameter).
47  */
sys_winstream_init(void * buf,int buflen)48 static inline struct sys_winstream *sys_winstream_init(void *buf, int buflen)
49 {
50 	struct sys_winstream *ws = buf, tmp = { .len = buflen - sizeof(*ws) };
51 
52 	*ws = tmp;
53 	return ws;
54 }
55 
56 /** @brief Write bytes to a sys_winstream
57  *
58  * This function writes the specified number of bytes into the stream.
59  * It will always return synchronously, it does not block or engage in
60  * any kind of synchronization beyond memory write ordering.  Any
61  * bytes passed beyond what can be stored in the buffer will be
62  * silently dropped, but readers can detect their presence via the
63  * sequence number.
64  *
65  * @param ws A sys_winstream to which to write
66  * @param data Pointer to bytes to be written
67  * @param len Number of bytes to write
68  */
69 void sys_winstream_write(struct sys_winstream *ws,
70 			 const char *data, uint32_t len);
71 
72 /** @brief Read bytes from a sys_winstream
73  *
74  * This function will read bytes from a sys_winstream into a specified
75  * buffer.  It will always return in constant time, it does not block
76  * or engage in any kind of synchronization beyond memory ordering.
77  * The number of bytes read into the buffer will be returned, but note
78  * that it is possible that an underflow can occur if the writer gets
79  * ahead of our context.  That situation can be detected via the
80  * sequence number returned via a pointer (i.e. if "*seq != old_seq +
81  * return_value", an underflow occurred and bytes were dropped).
82  *
83  * @param ws A sys_winstream from which to read
84  * @param seq A pointer to an integer containing the last sequence
85  *            number read from the stream, or zero to indicate "start
86  *            of stream". It is updated in place and returned for
87  *            future calls and for detecting underflows.
88  * @param buf A buffer into which to store the data read
89  * @param buflen The length of buf in bytes
90  * @return The number of bytes written into the buffer
91  */
92 uint32_t sys_winstream_read(struct sys_winstream *ws,
93 			    uint32_t *seq, char *buf, uint32_t buflen);
94 
95 #endif /* ZEPHYR_INCLUDE_SYS_WINSTREAM_H_ */
96