185 lines
4.0 KiB
C
185 lines
4.0 KiB
C
#include "alloc.h"
|
|
#include "klibc.h"
|
|
#include "ringbuffer.h"
|
|
#include "synchro.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));
|
|
if (inst == NULL)
|
|
return NULL;
|
|
inst->data = zalloc(capacity * sizeof(uint8_t));
|
|
if (inst->data == NULL) {
|
|
free(inst);
|
|
return NULL;
|
|
}
|
|
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 ringbufferIsEmpty(ringbuffer_t instance)
|
|
{
|
|
return (!instance->full && (instance->wr_pos == instance->rd_pos));
|
|
}
|
|
|
|
bool_t ringbufferIsFull(ringbuffer_t instance)
|
|
{
|
|
return instance->full;
|
|
}
|
|
|
|
bool_t ringbufferEnqueue(ringbuffer_t instance, uint8_t item)
|
|
{
|
|
if (ringbufferIsFull(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 (ringbufferIsEmpty(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)" : "");
|
|
}
|
|
|
|
struct locked_ringbuffer_instance_t {
|
|
struct ringbuffer_instance_t *ring;
|
|
struct mutex mut;
|
|
};
|
|
|
|
locked_ringbuffer_t lringbufferCreate(uint32_t capacity)
|
|
{
|
|
locked_ringbuffer_t inst = zalloc(sizeof(locked_ringbuffer_t));
|
|
if (inst == NULL)
|
|
return NULL;
|
|
|
|
inst->ring = ringbufferCreate(capacity);
|
|
if (inst->ring == NULL) {
|
|
free(inst);
|
|
return NULL;
|
|
}
|
|
|
|
mutexInit(&inst->mut);
|
|
|
|
return inst;
|
|
}
|
|
|
|
uint32_t lringbufferCapacity(locked_ringbuffer_t instance)
|
|
{
|
|
return instance->ring->capacity;
|
|
}
|
|
|
|
uint32_t lringbufferUsed(locked_ringbuffer_t instance)
|
|
{
|
|
int used;
|
|
mutexLock(&instance->mut);
|
|
used = ringbufferUsed(instance->ring);
|
|
mutexUnlock(&instance->mut);
|
|
return used;
|
|
}
|
|
|
|
bool_t lringbufferEnqueue(locked_ringbuffer_t instance, uint8_t item)
|
|
{
|
|
int ret;
|
|
mutexLock(&instance->mut);
|
|
ret = ringbufferEnqueue(instance->ring, item);
|
|
mutexUnlock(&instance->mut);
|
|
|
|
return ret;
|
|
}
|
|
|
|
bool_t lringbufferDequeue(locked_ringbuffer_t instance, uint8_t *item)
|
|
{
|
|
int ret;
|
|
mutexLock(&instance->mut);
|
|
ret = ringbufferDequeue(instance->ring, item);
|
|
mutexUnlock(&instance->mut);
|
|
|
|
return ret;
|
|
}
|
|
|
|
void lringbufferDestroy(locked_ringbuffer_t instance){
|
|
mutexFree(&instance->mut);
|
|
ringbufferDestroy(instance->ring);
|
|
instance->ring = NULL;
|
|
free(instance);
|
|
}
|
|
|
|
void lringbufferDebug(locked_ringbuffer_t instance)
|
|
{
|
|
mutexLock(&instance->mut);
|
|
ringbufferDebug(instance->ring);
|
|
mutexUnlock(&instance->mut);
|
|
}
|
|
|
|
bool_t lringbufferIsEmpty(locked_ringbuffer_t instance)
|
|
{
|
|
bool_t ret;
|
|
mutexLock(&instance->mut);
|
|
ret = ringbufferIsEmpty(instance->ring);
|
|
mutexUnlock(&instance->mut);
|
|
|
|
return ret;
|
|
}
|
|
|
|
bool_t lringbufferIsFull(locked_ringbuffer_t instance)
|
|
{
|
|
bool_t ret;
|
|
mutexLock(&instance->mut);
|
|
ret = ringbufferIsFull(instance->ring);
|
|
mutexUnlock(&instance->mut);
|
|
|
|
return ret;
|
|
}
|