CHERIoT RTOS
A compartmentalised RTOS for CHERIoT hardware
Loading...
Searching...
No Matches
stream_buffer.h
Go to the documentation of this file.
1#pragma once
2#include "FreeRTOS.h"
3#include <queue.h>
4
5/**
6 * \file
7 * \brief FreeRTOS stream compatibility APIs.
8 *
9 * This file defines the compatibility wrappers for FreeRTOS's stream
10 * abstraction. This is intended for porting code from FreeRTOS and should not
11 * be used in new CHERIoT software. The functions in this file wrap the APIs
12 * exposed in queue.h. Streams are implemented as queues of bytes (CHERIoT RTOS
13 * message queues allow inserting and receiving multiple queue elements at the
14 * same time). These are implemented in the `message_queue_library` library
15 * and, if used across a trust boundary, the `message_queue` compartment, which
16 * must be linked to the final firmware image.
17 */
18
19/**
20 * Stream handle. This is used to reference streams in the API functions.
21 */
23
24#ifndef CHERIOT_NO_AMBIENT_MALLOC
25/**
26 * Create a stream buffer that can store `xBufferSizeBytes` bytes.
27 *
28 * Returns NULL if queue creation failed, false otherwise.
29 */
30static inline StreamBufferHandle_t
31xStreamBufferCreate(size_t xBufferSizeBytes, size_t xTriggerLevelBytes)
32{
33 (void)xTriggerLevelBytes;
34 StreamBufferHandle_t ret = NULL;
35 struct Timeout timeout = {0, UnlimitedTimeout};
36 int rc =
37 queue_create(&timeout, MALLOC_CAPABILITY, &ret, 1, xBufferSizeBytes);
38 return ret;
39}
40
41/**
42 * Destroy a queue.
43 *
44 * Note that, unlike the underlying CHERIoT RTOS API, this has no mechanism to
45 * signal failure. If memory deallocation fails (for example, as a result of
46 * insufficient stack or trusted-stack space, this API may leak the queue.
47 */
48static inline void vStreamBufferDelete(StreamBufferHandle_t xStreamBuffer)
49{
50 struct Timeout timeout = {0, UnlimitedTimeout};
51 (void)queue_destroy(MALLOC_CAPABILITY, xStreamBuffer);
52}
53#endif
54
55/**
56 * Sends `xDataLengthBytes` of data from `pvTxData` to the stream
57 * `xStreamBuffer`.
58 *
59 * Returns the number of bytes read or zero in case of an error.
60 * Unlike the underlying CHERIoT RTOS API, this API has no way of signalling
61 * specific errors so all errors are reported as zero return values.
62 */
63static inline size_t xStreamBufferSend(StreamBufferHandle_t xStreamBuffer,
64 const void *pvTxData,
65 size_t xDataLengthBytes,
66 TickType_t waitTicks)
67{
68 struct Timeout timeout = {0, waitTicks};
69 int rv =
70 queue_send_multiple(&timeout, xStreamBuffer, pvTxData, xDataLengthBytes);
71 if (rv < 0)
72 {
73 return 0;
74 }
75 return rv;
76}
77
78/*
79 * Send to the stream from an ISR. We do not allow running code from ISRs and
80 * so this behaves like a non-blocking `xStreamBufferSend`.
81 *
82 * The `pxHigherPriorityTaskWoken` parameter is used to return whether a yield
83 * is necessary. A yield is never necessary in this implementation and so this
84 * is unconditionally given a value of `pdFALSE`.
85 */
86static inline size_t
87xStreamBufferSendFromISR(StreamBufferHandle_t xStreamBuffer,
88 const void *pvTxData,
89 size_t xDataLengthBytes,
90 BaseType_t *pxHigherPriorityTaskWoken)
91{
92 *pxHigherPriorityTaskWoken = pdFALSE;
93 return xStreamBufferSend(xStreamBuffer, pvTxData, xDataLengthBytes, 0);
94}
95
96/**
97 * Receive up to `xBufferLengthBytes` bytes into `pvRxData` from the stream
98 * given by `xStreamBuffer`.
99 *
100 * Returns the number of bytes read, this may be zero in case of an error.
101 * Unlike the underlying CHERIoT RTOS API, this API has no way of signalling
102 * specific errors so all errors are reported as zero return values.
103 */
104static inline size_t xStreamBufferReceive(StreamBufferHandle_t xStreamBuffer,
105 void *pvRxData,
106 size_t xBufferLengthBytes,
107 TickType_t xTicksToWait)
108{
109 struct Timeout timeout = {0, xTicksToWait};
110 int rv = queue_receive_multiple(
111 &timeout, xStreamBuffer, pvRxData, xBufferLengthBytes);
112 if (rv < 0)
113 {
114 return 0;
115 }
116 return rv;
117}
118
119/*
120 * Receive from the stream from an ISR. We do not allow running code from ISRs
121 * and so this behaves like a non-blocking `xStreamBufferReceive`.
122 *
123 * The `pxHigherPriorityTaskWoken` parameter is used to return whether a yield
124 * is necessary. A yield is never necessary in this implementation and so this
125 * is unconditionally given a value of `pdFALSE`.
126 */
127static inline size_t
128xStreamBufferReceiveFromISR(StreamBufferHandle_t xStreamBuffer,
129 void *pvRxData,
130 size_t xBufferLengthBytes,
131 BaseType_t *pxHigherPriorityTaskWoken)
132{
133 *pxHigherPriorityTaskWoken = pdFALSE;
134 return xStreamBufferSend(xStreamBuffer, pvRxData, xBufferLengthBytes, 0);
135}
136
137/**
138 * Returns the amount of data in a stream, in bytes.
139 *
140 * This API is intrinsically racy because more data can be sent to the queue in
141 * between calling this function and acting on the result.
142 *
143 * Note that, unlike FreeRTOS streams, CHERIoT RTOS message queues are thread
144 * safe and so this amount can also *decrease* if another thread receives from
145 * this stream.
146 */
147static inline size_t
149{
150 size_t outItems;
151 // Stream buffers use an item size of one and so the number of items and the
152 // number of bytes is the same.
153 (void)queue_items_remaining(xStreamBuffer, &outItems);
154 return outItems;
155}
156
157/**
158 * Returns the amount of space available in a stream, in bytes.
159 *
160 * This API is intrinsically racy because more data can be read from the queue
161 * in between calling this function and acting on the result.
162 *
163 * Note that, unlike FreeRTOS streams, CHERIoT RTOS message queues are thread
164 * safe and so this amount can also *decrease* if another thread sends over
165 * this stream.
166 */
167static inline size_t
169{
170 size_t outItems;
171 // Stream buffers use an item size of one and so the number of items and the
172 // number of bytes is the same.
173 (void)queue_items_remaining(xStreamBuffer, &outItems);
174 return xStreamBuffer->queueSize - outItems;
175}
176
177/**
178 * Updates the trigger level of the stream.
179 *
180 * Trigger levels are not currently supported by CHERIoT RTOS.
181 */
182__attribute__((
183 deprecated("Trigger levels are not currently supported in the FreeRTOS "
184 "streams compatibility layer"))) static inline BaseType_t
186 size_t xTriggerLevel)
187{
188 return pdFALSE;
189}
190
191/**
192 * Returns `pdTRUE` if the stream is empty, `pdFALSE` otherwise.
193 *
194 * Note, this API is inherently racy.
195 */
196static inline BaseType_t
198{
199 return xStreamBufferBytesAvailable(xStreamBuffer) == 0;
200}
201
202/**
203 * Returns `pdTRUE` if the stream is full, `pdFALSE` otherwise.
204 *
205 * Note, this API is inherently racy.
206 */
208{
209 return xStreamBufferSpacesAvailable(xStreamBuffer) == 0;
210}
211
212/**
213 * Reset the stream, unless another thread is currently active using it.
214 *
215 * This differs slightly from the FreeRTOS implementation, threads blocked
216 * waiting to acquire the endpoint locks do not prevent this operation and any
217 * threads waiting to send will become unblocked.
218 */
220{
221 struct Timeout timeout = {0, 0};
222 return queue_reset(&timeout, xStreamBuffer) == 0;
223}
224
225/**
226 * Reset a stream from an ISR. We do not allow running code from
227 * ISRs and so this behaves like a non-blocking `xStreamBufferReset`.
228 */
229static inline BaseType_t
231{
232 return xStreamBufferReset(xStreamBuffer);
233}
FreeRTOS queue compatibility APIs.
FreeRTOS porting layer.
int32_t BaseType_t
FreeRTOS default signed integer type.
Definition FreeRTOS.h:179
Ticks TickType_t
FreeRTOS type for durations expressed in ticks.
Definition FreeRTOS.h:175
#define pdFALSE
FreeRTOS definition of false.
Definition FreeRTOS.h:48
int __cheri_libcall queue_send_multiple(TimeoutArgument timeout, struct MessageQueue *handle, const void *src, size_t count)
Send multiple messages to the queue specified by handle.
int __cheri_libcall queue_destroy(AllocatorCapability heapCapability, struct MessageQueue *handle)
Destroys a queue.
int __cheri_libcall queue_create(TimeoutArgument timeout, AllocatorCapability heapCapability, struct MessageQueue **outQueue, size_t elementSize, size_t elementCount)
Allocates space for a queue using heapCapability and stores a handle to it via outQueue.
int __cheri_libcall queue_items_remaining(struct MessageQueue *handle, size_t *items)
Returns the number of items in the queue specified by handle via items.
int __cheri_libcall queue_reset(TimeoutArgument timeout, struct MessageQueue *queue)
Reset a queue to its initial state.
int __cheri_libcall queue_receive_multiple(TimeoutArgument timeout, struct MessageQueue *handle, void *dst, size_t count)
Receive multiple messages to the queue specified by handle.
static BaseType_t xStreamBufferSetTriggerLevel(StreamBufferHandle_t xStreamBuffer, size_t xTriggerLevel)
Updates the trigger level of the stream.
static size_t xStreamBufferReceive(StreamBufferHandle_t xStreamBuffer, void *pvRxData, size_t xBufferLengthBytes, TickType_t xTicksToWait)
Receive up to xBufferLengthBytes bytes into pvRxData from the stream given by xStreamBuffer.
static size_t xStreamBufferSpacesAvailable(StreamBufferHandle_t xStreamBuffer)
Returns the amount of space available in a stream, in bytes.
static size_t xStreamBufferBytesAvailable(StreamBufferHandle_t xStreamBuffer)
Returns the amount of data in a stream, in bytes.
static void vStreamBufferDelete(StreamBufferHandle_t xStreamBuffer)
Destroy a queue.
static StreamBufferHandle_t xStreamBufferCreate(size_t xBufferSizeBytes, size_t xTriggerLevelBytes)
Create a stream buffer that can store xBufferSizeBytes bytes.
static BaseType_t xStreamBufferResetFromISR(StreamBufferHandle_t xStreamBuffer)
Reset a stream from an ISR.
static BaseType_t xStreamBufferIsFull(StreamBufferHandle_t xStreamBuffer)
Returns pdTRUE if the stream is full, pdFALSE otherwise.
static BaseType_t xStreamBufferReset(StreamBufferHandle_t xStreamBuffer)
Reset the stream, unless another thread is currently active using it.
struct MessageQueue * StreamBufferHandle_t
Stream handle.
static size_t xStreamBufferSend(StreamBufferHandle_t xStreamBuffer, const void *pvTxData, size_t xDataLengthBytes, TickType_t waitTicks)
Sends xDataLengthBytes of data from pvTxData to the stream xStreamBuffer.
static BaseType_t xStreamBufferIsEmpty(StreamBufferHandle_t xStreamBuffer)
Returns pdTRUE if the stream is empty, pdFALSE otherwise.
Structure representing a queue.
Definition queue.h:44
size_t queueSize
The size of the queue.
Definition queue.h:53
Structure representing a timeout.
Definition timeout.h:47
static const Ticks UnlimitedTimeout
Value indicating an unbounded timeout for use with Timeout.
Definition timeout.h:22