Skip to content

Commit ed37609

Browse files
committed
Pack gap flag into size field LSB
Reduce `ringbuf_element_t` from 8 bytes to 4 bytes by encoding the "gap" flag into the LSB of the size field. Since all payload sizes are padded to 8 bytes, the lower 3 bits of size are always zero, making it safe to reuse bit 0. This shrinks the per-element header.
1 parent 0819ea6 commit ed37609

File tree

1 file changed

+18
-15
lines changed

1 file changed

+18
-15
lines changed

ringbuf-shm/ringbuffer.c

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,13 @@
1010
#include <time.h>
1111
#include <unistd.h>
1212

13-
#define RINGBUF_PAD(SIZE) (((size_t)(SIZE) + 7U) & (~7U))
13+
#define RINGBUF_PAD(SIZE) \
14+
(((size_t) (SIZE) + 7U) & (~7U)) /* size is padded to a multiple of 8 */
15+
#define GAP_MASK 1U
16+
#define SIZE_MASK (~GAP_MASK)
1417

1518
typedef struct {
16-
uint32_t size, gap;
19+
uint32_t size_and_gap;
1720
} ringbuf_element_t;
1821

1922
typedef struct {
@@ -54,7 +57,7 @@ static inline ringbuf_t *ringbuf_new(size_t minimum, bool release_and_acquire)
5457
const size_t body_size = ringbuf_body_size(minimum);
5558
const size_t total_size = sizeof(ringbuf_t) + body_size;
5659

57-
posix_memalign((void **) &ringbuf, sizeof(ringbuf_element_t), total_size);
60+
posix_memalign((void **) &ringbuf, 8, total_size);
5861
mlock(ringbuf, total_size); /* prevent memory from being flushed */
5962

6063
if (ringbuf)
@@ -170,19 +173,17 @@ static inline void ringbuf_write_advance(ringbuf_t *ringbuf, size_t written)
170173
/* fill end of first buffer with gap */
171174
ringbuf_element_t *element =
172175
(ringbuf_element_t *) (ringbuf->buf + head);
173-
element->size = ringbuf->gapd - sizeof(ringbuf_element_t);
174-
element->gap = 1;
176+
element->size_and_gap = ringbuf->gapd - sizeof(ringbuf_element_t);
177+
element->size_and_gap |= GAP_MASK;
175178

176179
/* fill written element header */
177180
element = (void *) ringbuf->buf;
178-
element->size = written;
179-
element->gap = 0;
181+
element->size_and_gap = written;
180182
} else {
181183
/* fill written element header */
182184
ringbuf_element_t *element =
183185
(ringbuf_element_t *) (ringbuf->buf + head);
184-
element->size = written;
185-
element->gap = 0;
186+
element->size_and_gap = written;
186187
}
187188

188189
/* advance write head */
@@ -226,7 +227,7 @@ static inline const void *ringbuf_read_request(ringbuf_t *ringbuf,
226227
const size_t len1 = ringbuf->size - tail;
227228
const ringbuf_element_t *element = (const ringbuf_element_t *) buf1;
228229

229-
if (element->gap) { /* gap element? */
230+
if (element->size_and_gap & GAP_MASK) { /* gap element? */
230231
/* skip gap */
231232
_ringbuf_read_advance_raw(ringbuf, tail, len1);
232233

@@ -235,19 +236,19 @@ static inline const void *ringbuf_read_request(ringbuf_t *ringbuf,
235236
/* there will always be at least on element after a gap */
236237
element = (const ringbuf_element_t *) buf2;
237238

238-
*toread = element->size;
239+
*toread = (element->size_and_gap) & SIZE_MASK;
239240
return buf2 + sizeof(ringbuf_element_t);
240241
}
241242

242243
/* valid chunk, use it! */
243-
*toread = element->size;
244+
*toread = (element->size_and_gap) & SIZE_MASK;
244245
return buf1 + sizeof(ringbuf_element_t);
245246
}
246247

247248
/* available buffer is contiguous */
248249
const uint8_t *buf = ringbuf->buf + tail;
249250
const ringbuf_element_t *element = (const ringbuf_element_t *) buf;
250-
*toread = element->size;
251+
*toread = (element->size_and_gap) & SIZE_MASK;
251252
return buf + sizeof(ringbuf_element_t);
252253
}
253254

@@ -267,7 +268,9 @@ static inline void ringbuf_read_advance(ringbuf_t *ringbuf)
267268

268269
/* advance read tail */
269270
_ringbuf_read_advance_raw(
270-
ringbuf, tail, sizeof(ringbuf_element_t) + RINGBUF_PAD(element->size));
271+
ringbuf, tail,
272+
sizeof(ringbuf_element_t) +
273+
RINGBUF_PAD(element->size_and_gap & SIZE_MASK));
271274
}
272275

273276
/* Test program */
@@ -276,7 +279,7 @@ static const struct timespec req = {.tv_sec = 0, .tv_nsec = 1};
276279

277280
static uint64_t iterations = 10000;
278281
#define THRESHOLD (RAND_MAX / 256)
279-
#define PAD(SIZE) (((size_t)(SIZE) + 7U) & (~7U))
282+
#define PAD(SIZE) (((size_t) (SIZE) + 7U) & (~7U))
280283

281284
static void *producer_main(void *arg)
282285
{

0 commit comments

Comments
 (0)