diff --git a/core/ringbuffer.c b/core/ringbuffer.c new file mode 100644 index 0000000..ed5a050 --- /dev/null +++ b/core/ringbuffer.c @@ -0,0 +1,87 @@ +#include "alloc.h" +#include "klibc.h" +#include "ringbuffer.h" + +struct ringbuffer_instance_t { + int32_t wr_pos; + int32_t rd_pos; + uint8_t *data; + uint32_t capacity; + bool_t full; +}; + +ringbuffer_t ringbufferCreate(uint32_t capacity) +{ + ringbuffer_t inst = zalloc(1* sizeof(struct ringbuffer_instance_t)); + inst->data = zalloc(capacity * sizeof(uint8_t)); + inst->capacity = capacity; + inst->wr_pos = 0; + inst->rd_pos = 0; + inst->full = capacity == 0; + + return inst; +} + +uint32_t ringbufferCapacity(ringbuffer_t instance) +{ + return instance->capacity; +} + +uint32_t ringbufferUsed(ringbuffer_t instance) +{ + if (instance->full) + return instance->capacity; + + return (instance->wr_pos - instance->rd_pos) % instance->capacity; +} + +bool_t ringbufferEmpty(ringbuffer_t instance) +{ + return (!instance->full && (instance->wr_pos == instance->rd_pos)); +} + +bool_t ringbufferFull(ringbuffer_t instance) +{ + return instance->full; +} + +bool_t ringbufferEnqueue(ringbuffer_t instance, uint8_t item) +{ + if (ringbufferFull(instance)) + return FALSE; + + instance->data[instance->wr_pos] = item; + instance->wr_pos = (instance->wr_pos + 1) % instance->capacity; + if (instance->rd_pos == instance->wr_pos) + instance->full = TRUE; + + return TRUE; +} + +bool_t ringbufferDequeue(ringbuffer_t instance, uint8_t *item) +{ + if (ringbufferEmpty(instance)) + return FALSE; + + instance->full = FALSE; + *item = instance->data[instance->rd_pos]; + instance->rd_pos = (instance->rd_pos + 1) % instance->capacity; + + return TRUE; +} + +void ringbufferDestroy(ringbuffer_t instance) +{ + if (instance) { + if (instance->data) { + free(instance->data); + } + free(instance); + } +} + +void ringbufferDebug(ringbuffer_t instance) +{ + printf("%d/%d %d %d %s\n", ringbufferUsed(instance), ringbufferCapacity(instance), + instance->wr_pos, instance->rd_pos, instance->full ? "(full)" : ""); +} diff --git a/core/ringbuffer.h b/core/ringbuffer.h new file mode 100644 index 0000000..5337f15 --- /dev/null +++ b/core/ringbuffer.h @@ -0,0 +1,15 @@ +#pragma once + +#include "stdarg.h" + +typedef struct ringbuffer_instance_t* ringbuffer_t; + +ringbuffer_t ringbufferCreate(uint32_t capacity); +uint32_t ringbufferCapacity(ringbuffer_t instance); +uint32_t ringbufferUsed(ringbuffer_t instance); +bool_t ringbufferEnqueue(ringbuffer_t instance, uint8_t item); +bool_t ringbufferDequeue(ringbuffer_t instance, uint8_t* item); +void ringbufferDestroy(ringbuffer_t instance); +void ringbufferDebug(ringbuffer_t instance); +bool_t ringbufferEmpty(ringbuffer_t instance); +bool_t ringbufferFull(ringbuffer_t instance); diff --git a/tests/test.c b/tests/test.c index b7b92ed..885333e 100644 --- a/tests/test.c +++ b/tests/test.c @@ -16,6 +16,7 @@ #include "synchro.h" #include "syscall.h" #include "swintr.h" +#include "ringbuffer.h" #include "time.h" void testMemcpyPerf() @@ -450,6 +451,49 @@ static void testProcess(){ printf("Running user space app DONE\n"); } +void testRingBuffer() +{ + printf("Testing ring buffer\n"); + ringbuffer_t inst = ringbufferCreate(4); + ringbufferDebug(inst); + uint8_t item; + assert(ringbufferEnqueue(inst, 1)); + ringbufferDebug(inst); + assert(ringbufferEnqueue(inst, 2)); + ringbufferDebug(inst); + assert(ringbufferEnqueue(inst, 3)); + ringbufferDebug(inst); + assert(ringbufferEnqueue(inst, 4)); + ringbufferDebug(inst); + assert(ringbufferEnqueue(inst, 5) == FALSE); + ringbufferDebug(inst); + assert(ringbufferDequeue(inst, &item)); + assert(item == 1); + ringbufferDebug(inst); + assert(ringbufferEnqueue(inst, 5)); + ringbufferDebug(inst); + + assert(ringbufferDequeue(inst, &item)); + assert(item == 2); + ringbufferDebug(inst); + + assert(ringbufferDequeue(inst, &item)); + assert(item == 3); + ringbufferDebug(inst); + + assert(ringbufferDequeue(inst, &item)); + assert(item == 4); + ringbufferDebug(inst); + + assert(ringbufferDequeue(inst, &item)); + assert(item == 5); + ringbufferDebug(inst); + + assert(ringbufferDequeue(inst, &item) == FALSE); + ringbufferDebug(inst); + ringbufferDestroy(inst); +} + void run_test(void) { @@ -494,4 +538,5 @@ void run_test(void) testProcess(); memGetStat(&afterFreemem, &afterUsedmem); printf("free %d -> %d\n", freemem, afterFreemem); + testRingBuffer(); }