PatchworkOS  966e257
A non-POSIX operating system.
Loading...
Searching...
No Matches
ring.h
Go to the documentation of this file.
1#pragma once
2
3#include <errno.h>
4#include <stdint.h>
5#include <string.h>
6
7/**
8 * @brief Ring buffer.
9 * @defgroup kernel_utils_ring Ring Buffer
10 * @ingroup kernel_utils
11 *
12 * @{
13 */
14
15/**
16 * @brief Ring buffer structure.
17 */
26
27/**
28 * @brief Create a ring buffer initializer.
29 *
30 * @param bufferPtr Pointer to the buffer memory.
31 * @param bufferSize Size of the buffer memory in bytes.
32 */
33#define RING_CREATE(bufferPtr, bufferSize) \
34 {.buffer = bufferPtr, .size = bufferSize, .readIndex = 0, .writeIndex = 0, .dataLength = 0}
35
36/**
37 * @brief Initialize a ring buffer.
38 *
39 * @param ring Pointer to the ring buffer to initialize.
40 * @param buffer Pointer to the buffer memory.
41 * @param size Size of the buffer memory in bytes.
42 */
43static inline void ring_init(ring_t* ring, void* buffer, uint64_t size)
44{
46 ring->size = size;
47 ring->readIndex = 0;
48 ring->writeIndex = 0;
49 ring->dataLength = 0;
50}
51
52/**
53 * @brief Get the length of data currently stored in the ring buffer.
54 *
55 * @param ring Pointer to the ring buffer.
56 * @return Length of data in bytes.
57 */
58static inline uint64_t ring_data_length(const ring_t* ring)
59{
60 return ring->dataLength;
61}
62
63/**
64 * @brief Get the length of free space in the ring buffer.
65 *
66 * @param ring Pointer to the ring buffer.
67 * @return Length of free space in bytes.
68 */
69static inline uint64_t ring_free_length(const ring_t* ring)
70{
71 return ring->size - ring->dataLength;
72}
73
74/**
75 * @brief Write data to the ring buffer.
76 *
77 * If the data to be written exceeds the free space in the buffer,
78 * the oldest data will be overwritten.
79 *
80 * @param ring Pointer to the ring buffer.
81 * @param buffer Pointer to the data to write.
82 * @param count Number of bytes to write.
83 * @return Number of bytes written.
84 */
85static inline uint64_t ring_write(ring_t* ring, const void* buffer, uint64_t count)
86{
88 {
89 uint64_t overflow = count - ring_free_length(ring);
90 ring->readIndex = (ring->readIndex + overflow) % ring->size;
91 ring->dataLength -= overflow;
92 }
93
94 uint64_t upperHalfSize = ring->size - ring->writeIndex;
95 if (count < upperHalfSize)
96 {
98 }
99 else
100 {
101 memcpy((void*)((uint64_t)ring->buffer + ring->writeIndex), buffer, upperHalfSize);
102
103 uint64_t lowerHalfSize = count - upperHalfSize;
104 memcpy(ring->buffer, (void*)((uint64_t)buffer + upperHalfSize), lowerHalfSize);
105 }
106
109
110 return count;
111}
112
113/**
114 * @brief Read data from the ring buffer.
115 *
116 * @param ring Pointer to the ring buffer.
117 * @param buffer Pointer to the buffer to store the read data.
118 * @param count Number of bytes to read.
119 * @return Number of bytes read, or ERR if not enough data is available.
120 */
122{
124 {
125 return ERR;
126 }
127
128 uint64_t upperHalfSize = ring->size - ring->readIndex;
129 if (count < upperHalfSize)
130 {
132 }
133 else
134 {
135 memcpy(buffer, (void*)((uint64_t)ring->buffer + ring->readIndex), upperHalfSize);
136
137 uint64_t lowerHalfSize = count - upperHalfSize;
138 memcpy((void*)((uint64_t)buffer + upperHalfSize), ring->buffer, lowerHalfSize);
139 }
140
143
144 return count;
145}
146
147/**
148 * @brief Read data from the ring buffer at a specific offset without modifying the read index.
149 *
150 * @param ring Pointer to the ring buffer.
151 * @param offset Offset from the current read index to start reading.
152 * @param buffer Pointer to the buffer to store the read data.
153 * @param count Number of bytes to read.
154 * @return Number of bytes read, or 0 if offset is out of bounds.
155 */
156static inline uint64_t ring_read_at(const ring_t* ring, uint64_t offset, void* buffer, uint64_t count)
157{
158 uint64_t availableBytes = (offset >= ring->dataLength) ? 0 : (ring->dataLength - offset);
159 count = (count > availableBytes) ? availableBytes : count;
160
161 if (count == 0)
162 {
163 return 0;
164 }
165
166 uint64_t pos = (ring->readIndex + offset) % ring->size;
167
168 uint64_t upperHalfSize = ring->size - pos;
169 if (count < upperHalfSize)
170 {
171 memcpy(buffer, (void*)((uint64_t)ring->buffer + pos), count);
172 }
173 else
174 {
175 memcpy(buffer, (void*)((uint64_t)ring->buffer + pos), upperHalfSize);
176 uint64_t lowerHalfSize = count - upperHalfSize;
177 memcpy((void*)((uint64_t)buffer + upperHalfSize), ring->buffer, lowerHalfSize);
178 }
179
180 return count;
181}
182
183/**
184 * @brief Move the read index forward by a specified offset.
185 *
186 * If the offset exceeds the current data length, no action is taken.
187 *
188 * @param ring Pointer to the ring buffer.
189 * @param offset Number of bytes to move the read index forward.
190 */
192{
193 if (offset > ring_data_length(ring))
194 {
195 return;
196 }
197
198 ring->readIndex = (ring->readIndex + offset) % ring->size;
199 ring->dataLength -= offset;
200}
201
202/**
203 * @brief Get a byte from the ring buffer at a specific offset without modifying the read index.
204 *
205 * @param ring Pointer to the ring buffer.
206 * @param offset Offset from the current read index to get the byte.
207 * @param byte Pointer to store the retrieved byte.
208 * @return 0 on success, or `ERR` if offset is out of bounds.
209 */
210static inline uint64_t ring_get_byte(const ring_t* ring, uint64_t offset, uint8_t* byte)
211{
212 if (offset >= ring->dataLength)
213 {
214 return ERR;
215 }
216
217 uint64_t byteIndex = (ring->readIndex + offset) % ring->size;
218 *byte = ((uint8_t*)ring->buffer)[byteIndex];
219 return 0;
220}
221
222/** @} */
static uint64_t ring_write(ring_t *ring, const void *buffer, uint64_t count)
Write data to the ring buffer.
Definition ring.h:85
static void ring_move_read_forward(ring_t *ring, uint64_t offset)
Move the read index forward by a specified offset.
Definition ring.h:191
static uint64_t ring_free_length(const ring_t *ring)
Get the length of free space in the ring buffer.
Definition ring.h:69
static uint64_t ring_get_byte(const ring_t *ring, uint64_t offset, uint8_t *byte)
Get a byte from the ring buffer at a specific offset without modifying the read index.
Definition ring.h:210
static uint64_t ring_data_length(const ring_t *ring)
Get the length of data currently stored in the ring buffer.
Definition ring.h:58
static uint64_t ring_read(ring_t *ring, void *buffer, uint64_t count)
Read data from the ring buffer.
Definition ring.h:121
static uint64_t ring_read_at(const ring_t *ring, uint64_t offset, void *buffer, uint64_t count)
Read data from the ring buffer at a specific offset without modifying the read index.
Definition ring.h:156
static void ring_init(ring_t *ring, void *buffer, uint64_t size)
Initialize a ring buffer.
Definition ring.h:43
#define ERR
Integer error value.
Definition ERR.h:17
static ring_t ring
Definition log_file.c:21
EFI_PHYSICAL_ADDRESS buffer
Definition mem.c:15
static atomic_long count
Definition main.c:10
__UINT64_TYPE__ uint64_t
Definition stdint.h:17
__UINT8_TYPE__ uint8_t
Definition stdint.h:11
_PUBLIC void * memcpy(void *_RESTRICT s1, const void *_RESTRICT s2, size_t n)
Definition memcpy.c:61
Ring buffer structure.
Definition ring.h:19
uint64_t writeIndex
Definition ring.h:23
uint64_t size
Definition ring.h:21
uint64_t readIndex
Definition ring.h:22
void * buffer
Definition ring.h:20
uint64_t dataLength
Definition ring.h:24